diff --git a/packages/devextreme/js/__internal/common/core/animation/frame.ts b/packages/devextreme/js/__internal/common/core/animation/frame.ts index e3c7f7023bb2..2ab76ff12122 100644 --- a/packages/devextreme/js/__internal/common/core/animation/frame.ts +++ b/packages/devextreme/js/__internal/common/core/animation/frame.ts @@ -17,11 +17,13 @@ const window: ExtendedWindow = (hasWindow() ? getWindow() : {}) as ExtendedWindo const FRAME_ANIMATION_STEP_TIME = 1000 / 60; +// eslint-disable-next-line func-names -- description seam for tests let request = function (callback: FrameRequestCallback): number { /* eslint-disable no-restricted-globals */ return setTimeout(callback, FRAME_ANIMATION_STEP_TIME); }; +// eslint-disable-next-line func-names -- description seam for tests let cancel = function (requestID: number): void { clearTimeout(requestID); }; @@ -45,15 +47,37 @@ const setAnimationFrameMethods = callOnce(() => { } }); -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types -export function requestAnimationFrame(...args): number { +/* eslint-disable-next-line + @typescript-eslint/explicit-module-boundary-types, import/no-mutable-exports + -- description seam for tests */ +export let requestAnimationFrame = function (...args): number { setAnimationFrameMethods(); // @ts-ignore return request.apply(window, args); -} +}; -export function cancelAnimationFrame(requestID: number): void { +/* eslint-disable-next-line + import/no-mutable-exports + -- description seam for tests */ +export let cancelAnimationFrame = function (requestID: number): void { setAnimationFrameMethods(); cancel.apply(window, [requestID]); +}; + +/// #DEBUG +/* eslint-disable-next-line @typescript-eslint/naming-convention + -- description seam setter for tests stubs */ +export function DEBUG_set_requestAnimationFrame( + value: typeof requestAnimationFrame, +): void { + requestAnimationFrame = value; +} +/* eslint-disable-next-line @typescript-eslint/naming-convention + -- description seam setter for tests stubs */ +export function DEBUG_set_cancelAnimationFrame( + value: typeof cancelAnimationFrame, +): void { + cancelAnimationFrame = value; } +/// #ENDDEBUG diff --git a/packages/devextreme/js/__internal/common/core/animation/translator.ts b/packages/devextreme/js/__internal/common/core/animation/translator.ts index 001375a94dc6..306152f9b687 100644 --- a/packages/devextreme/js/__internal/common/core/animation/translator.ts +++ b/packages/devextreme/js/__internal/common/core/animation/translator.ts @@ -124,7 +124,8 @@ export const move = function ( } }; -export const resetPosition = function ( +/* eslint-disable import/no-mutable-exports -- description seam for tests */ +export let resetPosition = function ( $element: dxElementWrapper | Element | undefined, finishTransition?: boolean, ): void { @@ -170,3 +171,11 @@ export const parseTranslate = function (translateString: string): TranslateVecto z: parseFloat(result[2]), }; }; + +/// #DEBUG +/* eslint-disable @typescript-eslint/naming-convention + -- description seam setter for tests stubs */ +export function DEBUG_set_resetPosition(value: typeof resetPosition): void { + resetPosition = value; +} +/// #ENDDEBUG diff --git a/packages/devextreme/js/__internal/core/localization/ldml/date.parser.ts b/packages/devextreme/js/__internal/core/localization/ldml/date.parser.ts index 941d4ee6970e..43752f07fbba 100644 --- a/packages/devextreme/js/__internal/core/localization/ldml/date.parser.ts +++ b/packages/devextreme/js/__internal/core/localization/ldml/date.parser.ts @@ -235,7 +235,8 @@ export const isPossibleForParsingFormat = (patterns: string[]): boolean => { }); }; -export const getRegExpInfo = ( +// eslint-disable-next-line import/no-mutable-exports -- description seam for tests +export let getRegExpInfo = ( format: string, dateParts: LdlmDateLocalization, ): { @@ -381,3 +382,11 @@ export const getParser = (format: string, dateParts: LdlmDateLocalization) => { return null; }; }; + +/// #DEBUG +/* eslint-disable-next-line @typescript-eslint/naming-convention + -- description seam setter for tests stubs */ +export function DEBUG_set_getRegExpInfo(value: typeof getRegExpInfo): void { + getRegExpInfo = value; +} +/// #ENDDEBUG diff --git a/packages/devextreme/js/__internal/viz/axes/base_axis.ts b/packages/devextreme/js/__internal/viz/axes/base_axis.ts index 66b8919a6f1d..8811d932f81b 100644 --- a/packages/devextreme/js/__internal/viz/axes/base_axis.ts +++ b/packages/devextreme/js/__internal/viz/axes/base_axis.ts @@ -313,7 +313,8 @@ function getConstantLineSharpDirection(coord, axisCanvas) { return Math.max(axisCanvas.start, axisCanvas.end) !== coord ? 1 : -1; } -export const Axis = function (renderSettings) { +// eslint-disable-next-line import/no-mutable-exports -- description seam for tests +export let Axis = function (renderSettings) { const that = this; that._renderer = renderSettings.renderer; @@ -2839,3 +2840,9 @@ Axis.prototype = { shift: _noop, /// #ENDDEBUG }; + +/// #DEBUG +export function DEBUG_set_Axis(value: typeof Axis): void { + Axis = value; +} +/// #ENDDEBUG diff --git a/packages/devextreme/js/__internal/viz/axes/tick_generator.ts b/packages/devextreme/js/__internal/viz/axes/tick_generator.ts index 09d459922448..7cba1e2fee6f 100644 --- a/packages/devextreme/js/__internal/viz/axes/tick_generator.ts +++ b/packages/devextreme/js/__internal/viz/axes/tick_generator.ts @@ -806,7 +806,8 @@ function dateGenerator(options) { ); } -export const tickGenerator = function (options) { +// eslint-disable-next-line import/no-mutable-exports -- description seam for tests +export let tickGenerator = function (options) { let result; if (options.rangeIsEmpty) { @@ -823,3 +824,11 @@ export const tickGenerator = function (options) { return result; }; + +/// #DEBUG +/* eslint-disable-next-line @typescript-eslint/naming-convention + -- description seam setter for tests stubs */ +export function DEBUG_set_tickGenerator(value: typeof tickGenerator): void { + tickGenerator = value; +} +/// #ENDDEBUG diff --git a/packages/devextreme/js/__internal/viz/chart_components/crosshair.ts b/packages/devextreme/js/__internal/viz/chart_components/crosshair.ts index 61174b64b40d..f6bac1473ba0 100644 --- a/packages/devextreme/js/__internal/viz/chart_components/crosshair.ts +++ b/packages/devextreme/js/__internal/viz/chart_components/crosshair.ts @@ -69,13 +69,14 @@ function getLabelCheckerPosition(x, y, isHorizontal, canvas) { }; } -export function Crosshair(renderer, options, params, group) { +// eslint-disable-next-line import/no-mutable-exports -- description seam for tests +export let Crosshair = function (renderer, options, params, group) { const that = this; that._renderer = renderer; that._crosshairGroup = group; that._options = {}; that.update(options, params); -} +}; Crosshair.prototype = { constructor: Crosshair, @@ -323,3 +324,11 @@ Crosshair.prototype = { } }, }; + +/// #DEBUG +/* eslint-disable-next-line @typescript-eslint/naming-convention + -- description seam setter for tests stubs */ +export function DEBUG_set_Crosshair(value: typeof Crosshair): void { + Crosshair = value; +} +/// #ENDDEBUG diff --git a/packages/devextreme/js/__internal/viz/chart_components/layout_manager.ts b/packages/devextreme/js/__internal/viz/chart_components/layout_manager.ts index f74d419697b7..69500d196043 100644 --- a/packages/devextreme/js/__internal/viz/chart_components/layout_manager.ts +++ b/packages/devextreme/js/__internal/viz/chart_components/layout_manager.ts @@ -122,8 +122,9 @@ function getInnerRadius({ type, innerRadius }) { return type === 'pie' ? 0 : _isNumber(innerRadius) ? Number(innerRadius) : DEFAULT_INNER_RADIUS; } -function LayoutManager() { -} +// eslint-disable-next-line import/no-mutable-exports -- description seam for tests +let LayoutManager = function () { +}; function getAverageLabelWidth(centerX, radius, canvas, sizeLabels) { return (centerX - radius - RADIAL_LABEL_INDENT - canvas.left) / sizeLabels.outerLabelsCount; @@ -278,3 +279,9 @@ LayoutManager.prototype = { }; export { LayoutManager }; + +/// #DEBUG +export function DEBUG_set_LayoutManager(value: typeof LayoutManager): void { + LayoutManager = value; +} +/// #ENDDEBUG diff --git a/packages/devextreme/js/__internal/viz/chart_components/scroll_bar.ts b/packages/devextreme/js/__internal/viz/chart_components/scroll_bar.ts index 449be66e01ea..4d744fc09aaf 100644 --- a/packages/devextreme/js/__internal/viz/chart_components/scroll_bar.ts +++ b/packages/devextreme/js/__internal/viz/chart_components/scroll_bar.ts @@ -23,7 +23,8 @@ const _min = Math.min; const _max = Math.max; const MIN_SCROLL_BAR_SIZE = 10; -export const ScrollBar = function (renderer, group) { +// eslint-disable-next-line import/no-mutable-exports -- description seam for tests +export let ScrollBar = function (renderer, group) { this._translator = new Translator2D({}, {}, {}); this._scroll = renderer.rect().append(group); this._addEvents(); @@ -283,3 +284,9 @@ ScrollBar.prototype = { }); }, }; + +/// #DEBUG +export function DEBUG_set_ScrollBar(value: typeof ScrollBar): void { + ScrollBar = value; +} +/// #ENDDEBUG diff --git a/packages/devextreme/js/__internal/viz/components/chart_theme_manager.ts b/packages/devextreme/js/__internal/viz/components/chart_theme_manager.ts index 214be1c8e5fe..2c2434452d85 100644 --- a/packages/devextreme/js/__internal/viz/components/chart_theme_manager.ts +++ b/packages/devextreme/js/__internal/viz/components/chart_theme_manager.ts @@ -26,7 +26,8 @@ import { import { BaseThemeManager } from '@ts/viz/core/base_theme_manager'; import { extractColor, normalizeEnum as _normalizeEnum } from '@ts/viz/core/utils'; -export const ThemeManager = BaseThemeManager.inherit((function () { +// eslint-disable-next-line import/no-mutable-exports -- description seam for tests +export let ThemeManager = BaseThemeManager.inherit((function () { const ctor = function (params) { const that = this; @@ -245,3 +246,11 @@ export const ThemeManager = BaseThemeManager.inherit((function () { }, }; })()); + +/// #DEBUG +/* eslint-disable-next-line @typescript-eslint/naming-convention + -- description seam setter for tests stubs */ +export function DEBUG_set_ThemeManager(value: typeof ThemeManager): void { + ThemeManager = value; +} +/// #ENDDEBUG diff --git a/packages/devextreme/js/__internal/viz/components/data_validator.ts b/packages/devextreme/js/__internal/viz/components/data_validator.ts index ce855b2f2e60..df90aae1b489 100644 --- a/packages/devextreme/js/__internal/viz/components/data_validator.ts +++ b/packages/devextreme/js/__internal/viz/components/data_validator.ts @@ -505,7 +505,8 @@ function verifyData(source, incidentOccurred) { return data; } -export function validateData(data, groupsData, incidentOccurred, options) { +// eslint-disable-next-line import/no-mutable-exports -- description seam for tests +export let validateData = function (data, groupsData, incidentOccurred, options) { data = verifyData(data, incidentOccurred); groupsData.argumentType = groupsData.argumentAxisType = null; @@ -524,4 +525,10 @@ export function validateData(data, groupsData, incidentOccurred, options) { const dataByArgumentFields = sortData(data, groupsData, options, getUniqueArgumentFields(groupsData)); return dataByArgumentFields; +}; + +/// #DEBUG +export function DEBUG_set_validateData(value: typeof validateData): void { + validateData = value; } +/// #ENDDEBUG diff --git a/packages/devextreme/js/__internal/viz/core/base_theme_manager.ts b/packages/devextreme/js/__internal/viz/core/base_theme_manager.ts index f6b3c66ed460..c380f0b72eef 100644 --- a/packages/devextreme/js/__internal/viz/core/base_theme_manager.ts +++ b/packages/devextreme/js/__internal/viz/core/base_theme_manager.ts @@ -32,7 +32,8 @@ function getThemePart(theme, path) { return _theme; } -export const BaseThemeManager = Class.inherit({ // TODO: test hack +// eslint-disable-next-line import/no-mutable-exports -- description seam for tests +export let BaseThemeManager = Class.inherit({ // TODO: test hack ctor(options) { this._themeSection = options.themeSection; this._fontFields = options.fontFields || []; @@ -115,3 +116,9 @@ export const BaseThemeManager = Class.inherit({ // TODO: test hack _extend(font, this._font, _extend({}, font)); }, }); + +/// #DEBUG +export function DEBUG_set_BaseThemeManager(value: typeof BaseThemeManager): void { + BaseThemeManager = value; +} +/// #ENDDEBUG diff --git a/packages/devextreme/js/__internal/viz/core/plaque.ts b/packages/devextreme/js/__internal/viz/core/plaque.ts index 33f3c017989e..bb4c67808f04 100644 --- a/packages/devextreme/js/__internal/viz/core/plaque.ts +++ b/packages/devextreme/js/__internal/viz/core/plaque.ts @@ -223,7 +223,8 @@ function getCloudPoints({ width, height }, x, y, anchorX, anchorY, { arrowWidth, return buildPath('M', points, 'Z'); } -export class Plaque { +// eslint-disable-next-line import/no-mutable-exports -- description seam for tests +export let Plaque = class { widget; options; @@ -480,4 +481,10 @@ export class Plaque { const { width, height } = this._size || {}; return Math.abs(x - this.x) <= width / 2 && Math.abs(y - this.y) <= height / 2; } +}; + +/// #DEBUG +export function DEBUG_set_Plaque(value: typeof Plaque): void { + Plaque = value; } +/// #ENDDEBUG diff --git a/packages/devextreme/js/__internal/viz/core/renderers/animation.ts b/packages/devextreme/js/__internal/viz/core/renderers/animation.ts index eadbcee48f76..ece2b3283446 100644 --- a/packages/devextreme/js/__internal/viz/core/renderers/animation.ts +++ b/packages/devextreme/js/__internal/viz/core/renderers/animation.ts @@ -144,13 +144,14 @@ Animation.prototype = { }, }; -export function AnimationController(element) { +// eslint-disable-next-line import/no-mutable-exports -- description seam for tests +export let AnimationController = function (element) { const that = this; that._animationCount = 0; that._timerId = null; that._animations = {}; that.element = element; -} +}; AnimationController.prototype = { _loop() { @@ -239,3 +240,11 @@ AnimationController.prototype = { !hasUnstoppableInAnimations && this.stop(); }, }; + +/// #DEBUG +/* eslint-disable-next-line @typescript-eslint/naming-convention + -- description seam setter for tests stubs */ +export function DEBUG_set_AnimationController(value: typeof AnimationController): void { + AnimationController = value; +} +/// #ENDDEBUG diff --git a/packages/devextreme/js/__internal/viz/core/renderers/renderer.ts b/packages/devextreme/js/__internal/viz/core/renderers/renderer.ts index 1f911e926157..9dd0b3b6d9ed 100644 --- a/packages/devextreme/js/__internal/viz/core/renderers/renderer.ts +++ b/packages/devextreme/js/__internal/viz/core/renderers/renderer.ts @@ -1843,7 +1843,7 @@ function unlinkItem(target) { updateIndexes(items, i); } -export function Renderer(options) { +export let Renderer = function (options) { const that = this; that.root = that._createElement('svg', { xmlns: 'http://www.w3.org/2000/svg', @@ -1868,7 +1868,7 @@ export function Renderer(options) { that.root.append({ element: options.container }); that._locker = 0; that._backed = false; -} +}; Renderer.prototype = { constructor: Renderer, @@ -2362,10 +2362,15 @@ const DEBUG_set_ArcSvgElement = function (value) { const DEBUG_set_TextSvgElement = function (value) { TextSvgElement = value; }; + +const DEBUG_set_Renderer = function (value) { + Renderer = value; +}; /// #ENDDEBUG /// #DEBUG exports.DEBUG_set_ArcSvgElement = DEBUG_set_ArcSvgElement; +exports.DEBUG_set_Renderer = DEBUG_set_Renderer; exports.DEBUG_set_PathSvgElement = DEBUG_set_PathSvgElement; exports.DEBUG_set_RectSvgElement = DEBUG_set_RectSvgElement; exports.DEBUG_set_SvgElement = DEBUG_set_SvgElement; diff --git a/packages/devextreme/js/__internal/viz/core/series_family.ts b/packages/devextreme/js/__internal/viz/core/series_family.ts index 25ca9ce1c54c..727ac86c658b 100644 --- a/packages/devextreme/js/__internal/viz/core/series_family.ts +++ b/packages/devextreme/js/__internal/viz/core/series_family.ts @@ -458,7 +458,8 @@ function adjustBubbleSeriesDimensions() { }); } -export function SeriesFamily(options) { +// eslint-disable-next-line import/no-mutable-exports -- description seam for tests +export let SeriesFamily = function (options) { /// #DEBUG debug.assert(options.type, 'type was not passed or empty'); /// #ENDDEBUG @@ -519,7 +520,7 @@ export function SeriesFamily(options) { that.adjustSeriesDimensions = adjustBubbleSeriesDimensions; break; } -} +}; SeriesFamily.prototype = { constructor: SeriesFamily, @@ -543,3 +544,9 @@ SeriesFamily.prototype = { this.series = _map(series, (singleSeries) => (singleSeries.type === type ? singleSeries : null)); }, }; + +/// #DEBUG +export function DEBUG_set_SeriesFamily(value: typeof SeriesFamily): void { + SeriesFamily = value; +} +/// #ENDDEBUG diff --git a/packages/devextreme/js/__internal/viz/core/utils.ts b/packages/devextreme/js/__internal/viz/core/utils.ts index fde5ddc1087e..4c65756fbeb6 100644 --- a/packages/devextreme/js/__internal/viz/core/utils.ts +++ b/packages/devextreme/js/__internal/viz/core/utils.ts @@ -91,7 +91,8 @@ export const degreesToRadians = function (value) { // Calculates sin and cos for in degrees // Expects number, no validation -export const getCosAndSin = function (angle) { +// eslint-disable-next-line import/no-mutable-exports -- description seam for tests +export let getCosAndSin = function (angle) { const angleInRadians = degreesToRadians(angle); return { cos: _cos(angleInRadians), sin: _sin(angleInRadians) }; }; @@ -276,7 +277,8 @@ export const enumParser = function (values) { }; }; -export const patchFontOptions = function (options) { +// eslint-disable-next-line import/no-mutable-exports -- description seam for tests +export let patchFontOptions = function (options) { const fontOptions = {}; each(options || {}, (key, value) => { if (/^(cursor)$/i.test(key)) { @@ -422,7 +424,8 @@ export function normalizePanesHeight(panes) { } } -export function updatePanesCanvases(panes, canvas, rotated) { +// eslint-disable-next-line import/no-mutable-exports -- description seam for tests +export let updatePanesCanvases = function (panes, canvas, rotated) { let distributedSpace = 0; const padding = PANE_PADDING; const paneSpace = rotated ? canvas.width - canvas.left - canvas.right : canvas.height - canvas.top - canvas.bottom; @@ -441,7 +444,7 @@ export function updatePanesCanvases(panes, canvas, rotated) { distributedSpace = distributedSpace + calcLength + padding; setCanvasValues(pane.canvas); }); -} +}; export const unique = function (array) { const values = {}; @@ -671,7 +674,8 @@ export function pointInCanvas(canvas, x, y) { return x >= canvas.left && x <= canvas.right && y >= canvas.top && y <= canvas.bottom; } -export const getNextDefsSvgId = () => `DevExpress_${numDefsSvgElements++}`; +// eslint-disable-next-line import/no-mutable-exports -- description seam for tests +export let getNextDefsSvgId = () => `DevExpress_${numDefsSvgElements++}`; export function extractColor(color, isBase?) { if (isString(color) || !color) { @@ -681,3 +685,21 @@ export function extractColor(color, isBase?) { } return color.fillId || color.base; } + +/// #DEBUG +export function DEBUG_set_getCosAndSin(value: typeof getCosAndSin): void { + getCosAndSin = value; +} + +export function DEBUG_set_patchFontOptions(value: typeof patchFontOptions): void { + patchFontOptions = value; +} + +export function DEBUG_set_updatePanesCanvases(value: typeof updatePanesCanvases): void { + updatePanesCanvases = value; +} + +export function DEBUG_set_getNextDefsSvgId(value: typeof getNextDefsSvgId): void { + getNextDefsSvgId = value; +} +/// #ENDDEBUG diff --git a/packages/devextreme/js/__internal/viz/palette.ts b/packages/devextreme/js/__internal/viz/palette.ts index 6f857efb3b05..8d00c26d2486 100644 --- a/packages/devextreme/js/__internal/viz/palette.ts +++ b/packages/devextreme/js/__internal/viz/palette.ts @@ -194,10 +194,11 @@ export function registerPalette(name, palette) { } } -export function getAccentColor(palette, themeDefault) { +// eslint-disable-next-line import/no-mutable-exports -- description seam for tests +export let getAccentColor = function (palette, themeDefault) { palette = getPalette(palette, { themeDefault }); return palette.accentColor || palette[0]; -} +}; function RingBuf(buf) { let ind = 0; @@ -430,7 +431,8 @@ function getColorMixer(palette, parameters) { }; } -export function createPalette(palette, parameters, themeDefaultPalette?) { +// eslint-disable-next-line import/no-mutable-exports -- description seam for tests +export let createPalette = function (palette, parameters, themeDefaultPalette?) { const paletteObj = { dispose() { this._extensionStrategy = null; @@ -469,7 +471,7 @@ export function createPalette(palette, parameters, themeDefaultPalette?) { paletteObj.reset(); return paletteObj; -} +}; function getAlteredPalette(originalPalette, step) { const palette = []; @@ -495,7 +497,8 @@ function getLightness(color) { return color.r * 0.3 + color.g * 0.59 + color.b * 0.11; } -export function getDiscretePalette(source, size, themeDefaultPalette) { +// eslint-disable-next-line import/no-mutable-exports -- description seam for tests +export let getDiscretePalette = function (source, size, themeDefaultPalette) { const palette = size > 0 ? createDiscreteColors(getPalette(source, { type: 'gradientSet', themeDefault: themeDefaultPalette }), size) : []; return { @@ -503,7 +506,7 @@ export function getDiscretePalette(source, size, themeDefaultPalette) { return palette[index] || null; }, }; -} +}; function createDiscreteColors(source, count) { const colorCount = count - 1; @@ -550,3 +553,15 @@ export function getGradientPalette(source, themeDefaultPalette) { /// #DEBUG export const _DEBUG_palettes = palettes; /// #ENDDEBUG + +/// #DEBUG +export function DEBUG_set_getAccentColor(value: typeof getAccentColor): void { + getAccentColor = value; +} +export function DEBUG_set_createPalette(value: typeof createPalette): void { + createPalette = value; +} +export function DEBUG_set_getDiscretePalette(value: typeof getDiscretePalette): void { + getDiscretePalette = value; +} +/// #ENDDEBUG diff --git a/packages/devextreme/js/__internal/viz/range_selector/range_view.ts b/packages/devextreme/js/__internal/viz/range_selector/range_view.ts index 3d5424ba3beb..ed73becd129f 100644 --- a/packages/devextreme/js/__internal/viz/range_selector/range_view.ts +++ b/packages/devextreme/js/__internal/viz/range_selector/range_view.ts @@ -36,11 +36,12 @@ function merge(a, b) { return a !== undefined ? a : b; } -export function RangeView(params) { +// eslint-disable-next-line import/no-mutable-exports -- description seam for tests +export let RangeView = function (params) { this._params = params; this._clipRect = params.renderer.clipRect(); params.root.attr({ 'clip-path': this._clipRect.id }); -} +}; RangeView.prototype = { constructor: RangeView, @@ -84,3 +85,11 @@ RangeView.prototype = { } }, }; + +/// #DEBUG +/* eslint-disable-next-line @typescript-eslint/naming-convention + -- description seam setter for tests stubs */ +export function DEBUG_set_RangeView(value: typeof RangeView): void { + RangeView = value; +} +/// #ENDDEBUG diff --git a/packages/devextreme/js/__internal/viz/range_selector/series_data_source.ts b/packages/devextreme/js/__internal/viz/range_selector/series_data_source.ts index 46a17f76d824..8eaa6ddb6d7d 100644 --- a/packages/devextreme/js/__internal/viz/range_selector/series_data_source.ts +++ b/packages/devextreme/js/__internal/viz/range_selector/series_data_source.ts @@ -57,7 +57,8 @@ const processSeriesFamilies = function (series, minBubbleSize, maxBubbleSize, ba return families; }; -export const SeriesDataSource = function (options) { +// eslint-disable-next-line import/no-mutable-exports -- description seam for tests +export let SeriesDataSource = function (options) { const that = this; const themeManager = that._themeManager = createThemeManager(options.chart); @@ -278,3 +279,11 @@ SeriesDataSource.prototype = { return this._themeManager; }, }; + +/// #DEBUG +/* eslint-disable-next-line @typescript-eslint/naming-convention + -- description seam setter for tests stubs */ +export function DEBUG_set_SeriesDataSource(value: typeof SeriesDataSource): void { + SeriesDataSource = value; +} +/// #ENDDEBUG diff --git a/packages/devextreme/js/__internal/viz/range_selector/sliders_controller.ts b/packages/devextreme/js/__internal/viz/range_selector/sliders_controller.ts index f2c26e68e6b8..ae3898626ea9 100644 --- a/packages/devextreme/js/__internal/viz/range_selector/sliders_controller.ts +++ b/packages/devextreme/js/__internal/viz/range_selector/sliders_controller.ts @@ -75,7 +75,8 @@ function restoreSetSelectedRange(controller) { delete controller.setSelectedRange; } -export function SlidersController(params) { +// eslint-disable-next-line import/no-mutable-exports -- description seam for tests +export let SlidersController = function (params) { const that = this; const sliderParams = { renderer: params.renderer, root: params.root, trackersGroup: params.trackersGroup, translator: params.translator, @@ -89,7 +90,7 @@ export function SlidersController(params) { // It seems that there is no special reasons to suppress first event - it was accidentally suppressed. // Let it stay so for now. that._processSelectionChanged = dummyProcessSelectionChanged; -} +}; SlidersController.prototype = { constructor: SlidersController, @@ -519,3 +520,11 @@ SlidersController.prototype = { this._sliders[index].toForeground(); }, }; + +/// #DEBUG +/* eslint-disable-next-line @typescript-eslint/naming-convention + -- description seam setter for tests stubs */ +export function DEBUG_set_SlidersController(value: typeof SlidersController): void { + SlidersController = value; +} +/// #ENDDEBUG diff --git a/packages/devextreme/js/__internal/viz/range_selector/tracker.ts b/packages/devextreme/js/__internal/viz/range_selector/tracker.ts index fcc50b508ad1..ee91d4d4b430 100644 --- a/packages/devextreme/js/__internal/viz/range_selector/tracker.ts +++ b/packages/devextreme/js/__internal/viz/range_selector/tracker.ts @@ -222,7 +222,8 @@ function initializeSliderEvents(controller, sliders, state, getRootOffsetLeft) { return docEvents; } -export function Tracker(params) { +// eslint-disable-next-line import/no-mutable-exports -- description seam for tests +export let Tracker = function (params) { const state = this._state = {}; const targets = params.controller.getTrackerTargets(); if (msPointerEnabled) { @@ -242,7 +243,7 @@ export function Tracker(params) { function getRootOffsetLeft() { return params.renderer.getRootOffset().left; } -} +}; Tracker.prototype = { constructor: Tracker, @@ -260,3 +261,11 @@ Tracker.prototype = { state.manualRangeSelectionEnabled = behavior.manualRangeSelectionEnabled; }, }; + +/// #DEBUG +/* eslint-disable-next-line @typescript-eslint/naming-convention + -- description seam setter for tests stubs */ +export function DEBUG_set_Tracker(value: typeof Tracker): void { + Tracker = value; +} +/// #ENDDEBUG diff --git a/packages/devextreme/js/__internal/viz/series/base_series.ts b/packages/devextreme/js/__internal/viz/series/base_series.ts index 3c7a86040693..864025498e3d 100644 --- a/packages/devextreme/js/__internal/viz/series/base_series.ts +++ b/packages/devextreme/js/__internal/viz/series/base_series.ts @@ -179,7 +179,8 @@ function mergePointOptions(base, extra) { return options; } -export function Series(settings, options) { +// eslint-disable-next-line import/no-mutable-exports -- description seam for tests +export let Series = function (settings, options) { const that = this; that.fullState = 0; that._extGroups = settings; @@ -191,7 +192,7 @@ export function Series(settings, options) { that._legendCallback = _noop; that.updateOptions(options, settings); -} +}; function getData(pointData) { return pointData.data; @@ -1382,3 +1383,11 @@ Series.prototype = { }; // @ts-expect-error export const mixins = seriesNS.mixins; + +/// #DEBUG +/* eslint-disable-next-line @typescript-eslint/naming-convention + -- description seam setter for tests stubs */ +export function DEBUG_set_Series(value: typeof Series): void { + Series = value; +} +/// #ENDDEBUG diff --git a/packages/devextreme/js/__internal/viz/series/points/base_point.ts b/packages/devextreme/js/__internal/viz/series/points/base_point.ts index ccb51c7e0c34..acc91bc39396 100644 --- a/packages/devextreme/js/__internal/viz/series/points/base_point.ts +++ b/packages/devextreme/js/__internal/viz/series/points/base_point.ts @@ -89,7 +89,8 @@ function isNoneMode(mode) { return _normalizeEnum(mode) === 'none'; } -export function Point(series, dataItem, options) { +// eslint-disable-next-line import/no-mutable-exports -- description seam for tests +export let Point = function (series, dataItem, options) { this.fullState = NORMAL_STATE; this.series = series; this.update(dataItem, options); @@ -104,7 +105,7 @@ export function Point(series, dataItem, options) { dashStyle: null, filter: null, }; -} +}; // @ts-expect-error mixins.symbolPoint = symbolPoint; // @ts-expect-error @@ -547,3 +548,9 @@ Point.prototype = { }; }, }; + +/// #DEBUG +export function DEBUG_set_Point(value: typeof Point): void { + Point = value; +} +/// #ENDDEBUG diff --git a/packages/devextreme/js/__internal/viz/series/points/label.ts b/packages/devextreme/js/__internal/viz/series/points/label.ts index 1792537c2d71..327f2763845d 100644 --- a/packages/devextreme/js/__internal/viz/series/points/label.ts +++ b/packages/devextreme/js/__internal/viz/series/points/label.ts @@ -290,13 +290,14 @@ function formatText(data, options) { return options.customizeText ? options.customizeText.call(data, data) : options.displayFormat ? processDisplayFormat(options.displayFormat, data) : data.valueText; } -export function Label(renderSettings) { +// eslint-disable-next-line import/no-mutable-exports -- description seam for tests +export let Label = function (renderSettings) { this._renderer = renderSettings.renderer; this._container = renderSettings.labelsGroup; this._point = renderSettings.point; this._strategy = renderSettings.strategy; this._rowCount = 1; -} +}; Label.prototype = { constructor: Label, @@ -551,5 +552,12 @@ Label.prototype = { }; /// #DEBUG -Label._DEBUG_formatText = formatText; +// eslint-disable-next-line @typescript-eslint/no-explicit-any +(Label as any)._DEBUG_formatText = formatText; +/// #ENDDEBUG + +/// #DEBUG +export function DEBUG_set_Label(value: typeof Label): void { + Label = value; +} /// #ENDDEBUG diff --git a/packages/devextreme/js/__internal/viz/translators/range.ts b/packages/devextreme/js/__internal/viz/translators/range.ts index be556c949927..d4ed7f96c59d 100644 --- a/packages/devextreme/js/__internal/viz/translators/range.ts +++ b/packages/devextreme/js/__internal/viz/translators/range.ts @@ -43,7 +43,8 @@ function compareAndReplace(thisValue, otherValue, setValue, compare) { } } -export const Range = function (range?) { +// eslint-disable-next-line import/no-mutable-exports -- description seam for tests +export let Range = function (range?) { range && extend(this, range); }; @@ -156,3 +157,9 @@ _Range.prototype = { } }, }; + +/// #DEBUG +export function DEBUG_set_Range(value: typeof Range): void { + Range = value; +} +/// #ENDDEBUG diff --git a/packages/devextreme/js/__internal/viz/translators/translator1d.ts b/packages/devextreme/js/__internal/viz/translators/translator1d.ts index f0caa9bd9a9e..3f9d1d7479be 100644 --- a/packages/devextreme/js/__internal/viz/translators/translator1d.ts +++ b/packages/devextreme/js/__internal/viz/translators/translator1d.ts @@ -9,9 +9,10 @@ const _Number = Number; -export function Translator1D() { +// eslint-disable-next-line import/no-mutable-exports -- description seam for tests +export let Translator1D = function () { this.setDomain(arguments[0], arguments[1]).setCodomain(arguments[2], arguments[3]).setInverted(false); -} +}; Translator1D.prototype = { constructor: Translator1D, @@ -87,3 +88,9 @@ Translator1D.prototype = { return result; }, }; + +/// #DEBUG +export function DEBUG_set_Translator1D(value: typeof Translator1D): void { + Translator1D = value; +} +/// #ENDDEBUG diff --git a/packages/devextreme/js/__internal/viz/translators/translator2d.ts b/packages/devextreme/js/__internal/viz/translators/translator2d.ts index a14d04727579..c354e9a42896 100644 --- a/packages/devextreme/js/__internal/viz/translators/translator2d.ts +++ b/packages/devextreme/js/__internal/viz/translators/translator2d.ts @@ -164,7 +164,8 @@ function getCheckingMethodsAboutBreaks(inverted) { }; } -const _Translator2d = function (businessRange, canvas, options) { +// eslint-disable-next-line import/no-mutable-exports -- description seam for tests +let _Translator2d = function (businessRange, canvas, options) { this.update(businessRange, canvas, options); }; @@ -722,3 +723,9 @@ _Translator2d.prototype = { }; export { _Translator2d as Translator2D }; + +/// #DEBUG +export function DEBUG_set_Translator2D(value: typeof _Translator2d): void { + _Translator2d = value; +} +/// #ENDDEBUG diff --git a/packages/devextreme/js/__internal/viz/vector_map/control_bar/control_bar.ts b/packages/devextreme/js/__internal/viz/vector_map/control_bar/control_bar.ts index dff2890bb1ef..5c13173ec984 100644 --- a/packages/devextreme/js/__internal/viz/vector_map/control_bar/control_bar.ts +++ b/packages/devextreme/js/__internal/viz/vector_map/control_bar/control_bar.ts @@ -73,7 +73,8 @@ COMMAND_TO_TYPE_MAP[COMMAND_MOVE_UP] = COMMAND_TO_TYPE_MAP[COMMAND_MOVE_RIGHT] = COMMAND_TO_TYPE_MAP[COMMAND_ZOOM_IN] = COMMAND_TO_TYPE_MAP[COMMAND_ZOOM_OUT] = ZoomCommand; COMMAND_TO_TYPE_MAP[COMMAND_ZOOM_DRAG] = ZoomDragCommand; -export function ControlBar(parameters) { +// eslint-disable-next-line import/no-mutable-exports -- description seam for tests +export let ControlBar = function (parameters) { const that = this; that._params = parameters; that._createElements(parameters.renderer, parameters.container, parameters.dataKey); @@ -81,7 +82,7 @@ export function ControlBar(parameters) { that._subscribeToProjection(parameters.projection); that._subscribeToTracker(parameters.tracker); that._createCallbacks(parameters.projection); -} +}; ControlBar.prototype = { constructor: ControlBar, @@ -472,3 +473,9 @@ exports._TESTS_restoreCommandToTypeMap = function () { COMMAND_TO_TYPE_MAP = COMMAND_TO_TYPE_MAP__ORIGINAL; }; /// #ENDDEBUG + +/// #DEBUG +export function DEBUG_set_ControlBar(value: typeof ControlBar): void { + ControlBar = value; +} +/// #ENDDEBUG diff --git a/packages/devextreme/js/__internal/viz/vector_map/data_exchanger.ts b/packages/devextreme/js/__internal/viz/vector_map/data_exchanger.ts index 3f0cf7a4f8a6..7078a0d1096f 100644 --- a/packages/devextreme/js/__internal/viz/vector_map/data_exchanger.ts +++ b/packages/devextreme/js/__internal/viz/vector_map/data_exchanger.ts @@ -6,9 +6,10 @@ import Callbacks from '@js/core/utils/callbacks'; -export function DataExchanger() { +// eslint-disable-next-line import/no-mutable-exports -- description seam for tests +export let DataExchanger = function () { this._store = {}; -} +}; DataExchanger.prototype = { constructor: DataExchanger, @@ -43,3 +44,11 @@ DataExchanger.prototype = { return this; }, }; + +/// #DEBUG +/* eslint-disable-next-line @typescript-eslint/naming-convention + -- description seam setter for tests stubs */ +export function DEBUG_set_DataExchanger(value: typeof DataExchanger): void { + DataExchanger = value; +} +/// #ENDDEBUG diff --git a/packages/devextreme/js/__internal/viz/vector_map/gesture_handler.ts b/packages/devextreme/js/__internal/viz/vector_map/gesture_handler.ts index 0fffd4195425..5e81a443e38a 100644 --- a/packages/devextreme/js/__internal/viz/vector_map/gesture_handler.ts +++ b/packages/devextreme/js/__internal/viz/vector_map/gesture_handler.ts @@ -8,13 +8,14 @@ const _ln = Math.log; const _LN2 = Math.LN2; -export function GestureHandler(params) { +// eslint-disable-next-line import/no-mutable-exports -- description seam for tests +export let GestureHandler = function (params) { const that = this; that._projection = params.projection; that._renderer = params.renderer; that._x = that._y = 0; that._subscribeToTracker(params.tracker); -} +}; GestureHandler.prototype = { constructor: GestureHandler, @@ -106,3 +107,9 @@ GestureHandler.prototype = { } }, }; + +/// #DEBUG +export function DEBUG_set_GestureHandler(value: typeof GestureHandler): void { + GestureHandler = value; +} +/// #ENDDEBUG diff --git a/packages/devextreme/js/__internal/viz/vector_map/layout.ts b/packages/devextreme/js/__internal/viz/vector_map/layout.ts index 8de01f8433b4..f440424f6c94 100644 --- a/packages/devextreme/js/__internal/viz/vector_map/layout.ts +++ b/packages/devextreme/js/__internal/viz/vector_map/layout.ts @@ -207,7 +207,8 @@ function applyLayout(canvas, items) { } } -export function LayoutControl(widget) { +// eslint-disable-next-line import/no-mutable-exports -- description seam for tests +export let LayoutControl = function (widget) { const that = this; that._items = []; that._suspended = 0; @@ -215,7 +216,7 @@ export function LayoutControl(widget) { that._updateLayout = function () { that._update(); }; -} +}; LayoutControl.prototype = { constructor: LayoutControl, @@ -266,3 +267,9 @@ LayoutControl.prototype = { } }, }; + +/// #DEBUG +export function DEBUG_set_LayoutControl(value: typeof LayoutControl): void { + LayoutControl = value; +} +/// #ENDDEBUG diff --git a/packages/devextreme/js/__internal/viz/vector_map/legend.ts b/packages/devextreme/js/__internal/viz/vector_map/legend.ts index eb5d39c0c227..a0cc3472d8da 100644 --- a/packages/devextreme/js/__internal/viz/vector_map/legend.ts +++ b/packages/devextreme/js/__internal/viz/vector_map/legend.ts @@ -119,11 +119,11 @@ Legend.prototype = _extend(clone(_BaseLegend.prototype), { }, }); -export function LegendsControl(parameters) { +export let LegendsControl = function (parameters) { this._params = parameters; this._items = []; parameters.container.virtualLink('legend-base'); -} +}; LegendsControl.prototype = { constructor: LegendsControl, @@ -170,3 +170,9 @@ exports._TESTS_restoreLegendType = function () { Legend = originalLegend; }; /// #ENDDEBUG + +/// #DEBUG +export function DEBUG_set_LegendsControl(value: typeof LegendsControl): void { + LegendsControl = value; +} +/// #ENDDEBUG diff --git a/packages/devextreme/js/__internal/viz/vector_map/map_layer.ts b/packages/devextreme/js/__internal/viz/vector_map/map_layer.ts index fadc174a8208..cb2bbc518577 100644 --- a/packages/devextreme/js/__internal/viz/vector_map/map_layer.ts +++ b/packages/devextreme/js/__internal/viz/vector_map/map_layer.ts @@ -1596,7 +1596,8 @@ function projectLineLabel(coordinates) { return resultData || [[], []]; } -export function MapLayerCollection(params) { +// eslint-disable-next-line import/no-mutable-exports -- description seam for tests +export let MapLayerCollection = function (params) { const that = this; const renderer = params.renderer; that._params = params; @@ -1609,7 +1610,7 @@ export function MapLayerCollection(params) { that._container = renderer.g().attr({ class: 'dxm-layers', 'clip-path': that._clip.id }).append(renderer.root).enableLinks(); that._subscribeToTracker(params.tracker, renderer, params.eventTrigger); that._dataReady = params.dataReady; -} +}; MapLayerCollection.prototype = { constructor: MapLayerCollection, @@ -1745,3 +1746,9 @@ export const _TESTS_stub_groupBySize = function (stub) { export const _TESTS_groupBySize = groupBySize; export const _TESTS_findGroupingIndex = findGroupingIndex; /// #ENDDEBUG + +/// #DEBUG +export function DEBUG_set_MapLayerCollection(value: typeof MapLayerCollection): void { + MapLayerCollection = value; +} +/// #ENDDEBUG diff --git a/packages/devextreme/js/__internal/viz/vector_map/projection.main.ts b/packages/devextreme/js/__internal/viz/vector_map/projection.main.ts index 3a960f5aaac9..953b23ccb8ee 100644 --- a/packages/devextreme/js/__internal/viz/vector_map/projection.main.ts +++ b/packages/devextreme/js/__internal/viz/vector_map/projection.main.ts @@ -65,7 +65,8 @@ function getEngine(engine) { return (engine instanceof Engine && engine) || projection.get(engine) || projection(engine) || projection.get(DEFAULT_ENGINE_NAME); } -export const Projection = function (parameters) { +// eslint-disable-next-line import/no-mutable-exports -- description seam for tests +export let Projection = function (parameters) { const that = this; that._initEvents(); that._params = parameters; @@ -553,3 +554,9 @@ function createProjectUnprojectMethods(project, unproject, p1, p2, delta) { /// #DEBUG export { Engine as _TESTS_Engine }; /// #ENDDEBUG + +/// #DEBUG +export function DEBUG_set_Projection(value: typeof Projection): void { + Projection = value; +} +/// #ENDDEBUG diff --git a/packages/devextreme/js/__internal/viz/vector_map/tooltip_viewer.ts b/packages/devextreme/js/__internal/viz/vector_map/tooltip_viewer.ts index 5e51270096a5..74be4028610a 100644 --- a/packages/devextreme/js/__internal/viz/vector_map/tooltip_viewer.ts +++ b/packages/devextreme/js/__internal/viz/vector_map/tooltip_viewer.ts @@ -9,9 +9,10 @@ const TOOLTIP_OFFSET = 12; // TODO: Somehow it should be merged with the core.Tooltip -export function TooltipViewer(params) { +// eslint-disable-next-line import/no-mutable-exports -- description seam for tests +export let TooltipViewer = function (params) { this._subscribeToTracker(params.tracker, params.tooltip, params.layerCollection); -} +}; TooltipViewer.prototype = { constructor: TooltipViewer, @@ -45,3 +46,11 @@ TooltipViewer.prototype = { }); }, }; + +/// #DEBUG +/* eslint-disable-next-line @typescript-eslint/naming-convention + -- description seam setter for tests stubs */ +export function DEBUG_set_TooltipViewer(value: typeof TooltipViewer): void { + TooltipViewer = value; +} +/// #ENDDEBUG diff --git a/packages/devextreme/js/__internal/viz/vector_map/tracker.ts b/packages/devextreme/js/__internal/viz/vector_map/tracker.ts index 55be5e250222..afbf4e5e91ad 100644 --- a/packages/devextreme/js/__internal/viz/vector_map/tracker.ts +++ b/packages/devextreme/js/__internal/viz/vector_map/tracker.ts @@ -57,7 +57,7 @@ let Focus; setupEvents(); -export function Tracker(parameters) { +export let Tracker = function (parameters) { const that = this; that._root = parameters.root; that._createEventHandlers(parameters.dataKey); @@ -67,7 +67,7 @@ export function Tracker(parameters) { that._fire(name, arg); }); that._attachHandlers(); -} +}; Tracker.prototype = { constructor: Tracker, @@ -580,3 +580,9 @@ function adjustWheelDelta(delta, lock) { } return sign * _delta; } + +/// #DEBUG +export function DEBUG_set_Tracker(value: typeof Tracker): void { + Tracker = value; +} +/// #ENDDEBUG diff --git a/packages/devextreme/js/common/core/events/visibility_change.js b/packages/devextreme/js/common/core/events/visibility_change.js index 93ea077c6d9a..e678ff243c28 100644 --- a/packages/devextreme/js/common/core/events/visibility_change.js +++ b/packages/devextreme/js/common/core/events/visibility_change.js @@ -1,7 +1,21 @@ import VisibilityChangeModule from '../../../__internal/events/m_visibility_change'; -export const triggerShownEvent = VisibilityChangeModule.triggerShownEvent; -export const triggerHidingEvent = VisibilityChangeModule.triggerHidingEvent; -export const triggerResizeEvent = VisibilityChangeModule.triggerResizeEvent; +export let triggerShownEvent = VisibilityChangeModule.triggerShownEvent; +export let triggerHidingEvent = VisibilityChangeModule.triggerHidingEvent; +export let triggerResizeEvent = VisibilityChangeModule.triggerResizeEvent; + +/// #DEBUG +export function DEBUG_set_triggerShownEvent(value) { + triggerShownEvent = value; +} + +export function DEBUG_set_triggerHidingEvent(value) { + triggerHidingEvent = value; +} + +export function DEBUG_set_triggerResizeEvent(value) { + triggerResizeEvent = value; +} +/// #ENDDEBUG export default VisibilityChangeModule; diff --git a/packages/devextreme/js/exporter.js b/packages/devextreme/js/exporter.js index cfcf606cc8ee..0cdb267d06a1 100644 --- a/packages/devextreme/js/exporter.js +++ b/packages/devextreme/js/exporter.js @@ -1,13 +1,16 @@ import * as clientExporter from './__internal/exporter/exporter'; -// Re-exported through local bindings on purpose: `export { … } from './…'` compiles to -// getter-only, non-configurable properties, while tests stub these members -// (see testing/tests/DevExpress.viz.core/export.tests.js). -const _export = clientExporter.export; +let _export = clientExporter.export; export const fileSaver = clientExporter.fileSaver; export const image = clientExporter.image; export const pdf = clientExporter.pdf; export const svg = clientExporter.svg; +/// #DEBUG +export function DEBUG_set_export(value) { + _export = value; +} +/// #ENDDEBUG + export { _export as export }; diff --git a/packages/devextreme/testing/helpers/chartMocks.js b/packages/devextreme/testing/helpers/chartMocks.js index f7acef832d79..6d5945d1c21c 100644 --- a/packages/devextreme/testing/helpers/chartMocks.js +++ b/packages/devextreme/testing/helpers/chartMocks.js @@ -16,7 +16,6 @@ import { } from './vizMocks.js'; import { Range } from 'viz/translators/range'; -const mutableSeriesFamilyModule = seriesFamilyModule.default ?? seriesFamilyModule; const LoadingIndicatorOrig = loadingIndicatorModule.LoadingIndicator; @@ -283,16 +282,28 @@ function createAxis(translatorData, orthogonalTranslatorData, allOptions, isHori return axis; } +// Modules that dropped their generated facade expose a DEBUG_set_* seam; the +// rest are still plain mutable objects. +function setItem(itemKey, moduleName, value) { + const setter = moduleName['DEBUG_set_' + itemKey]; + + if(typeof setter === 'function') { + setter(value); + } else { + moduleName[itemKey] = value; + } +} + function mockItem(itemKey, moduleName, mock) { if(sourceItemsToMocking[itemKey]) { throw 'Item ' + itemKey + ' already mocked'; } sourceItemsToMocking[itemKey] = moduleName[itemKey]; - moduleName[itemKey] = mock; + setItem(itemKey, moduleName, mock); } function restoreItem(itemKey, moduleName) { - moduleName[itemKey] = sourceItemsToMocking[itemKey]; + setItem(itemKey, moduleName, sourceItemsToMocking[itemKey]); sourceItemsToMocking[itemKey] = null; } @@ -396,9 +407,9 @@ export const resetMockFactory = function resetMockFactory() { }; export const setupSeriesFamily = function() { - mutableSeriesFamilyModule.SeriesFamily = function(options) { + seriesFamilyModule.DEBUG_set_SeriesFamily(function(options) { return new MockSeriesFamily(options); - }; + }); }; // Translator diff --git a/packages/devextreme/testing/helpers/esm-shims/mutable_facade.js b/packages/devextreme/testing/helpers/esm-shims/mutable_facade.js deleted file mode 100644 index 8cc00339e1b3..000000000000 --- a/packages/devextreme/testing/helpers/esm-shims/mutable_facade.js +++ /dev/null @@ -1,50 +0,0 @@ -/** - * Shared helpers for mutable ESM facades used by QUnit stubbing. - */ -export function wrapCtor(api, name) { - const ExportWrapper = function(...args) { - const Impl = api[name]; - if(new.target) { - return new Impl(...args); - } - return Impl.apply(this, args); - }; - Object.defineProperty(ExportWrapper, 'name', { value: name, configurable: true }); - // Point at the live implementation prototype so stubClass(import { X }) - // sees real methods (e.g. vizMocks Tooltip/Title/ExportMenu). - // Also inherit statics (Class.inherit / redefine / parent / …) so - // `BaseThemeManager.inherit(...)` keeps working under the facade. - const Impl = api[name]; - if(typeof Impl === 'function') { - Object.setPrototypeOf(ExportWrapper, Impl); - if(Impl.prototype) { - ExportWrapper.prototype = Impl.prototype; - } - } - return ExportWrapper; -} - -/** - * @param {object} original - * @param {string} globalKey - * @param {Record} [debugSets] map DEBUG_set_* → api property name - */ -export function createMutableApi(original, globalKey, debugSets = {}) { - if(globalThis[globalKey]) { - return globalThis[globalKey]; - } - - const api = { ...original }; - Object.entries(debugSets).forEach(([debugName, propName]) => { - const originalDebugSet = api[debugName]; - api[debugName] = (value) => { - api[propName] = value; - if(typeof originalDebugSet === 'function') { - originalDebugSet(value); - } - }; - }); - - globalThis[globalKey] = api; - return api; -} diff --git a/packages/devextreme/testing/helpers/moduleSeam.js b/packages/devextreme/testing/helpers/moduleSeam.js new file mode 100644 index 000000000000..0f02d142dab4 --- /dev/null +++ b/packages/devextreme/testing/helpers/moduleSeam.js @@ -0,0 +1,18 @@ +/* global sinon */ + +export function installSeam(module, name, replacement, setterName = `DEBUG_set_${name}`) { + const original = module[name]; + + replacement.restore = () => module[setterName](original); + module[setterName](replacement); + + return replacement; +} + +export function spySeam(module, name, setterName) { + return installSeam(module, name, sinon.spy(module[name]), setterName); +} + +export function stubSeam(module, name, setterName) { + return installSeam(module, name, sinon.stub(), setterName); +} diff --git a/packages/devextreme/testing/helpers/trackerMock.js b/packages/devextreme/testing/helpers/trackerMock.js index 70c00a82ab46..9b8a6f7e513c 100644 --- a/packages/devextreme/testing/helpers/trackerMock.js +++ b/packages/devextreme/testing/helpers/trackerMock.js @@ -1,5 +1,4 @@ import { stubClass } from './vizMocks.js'; -// Mutate the import-map facade (see esm-shims/viz_chart_tracker.js). import trackerModule from 'viz/chart_components/tracker'; const ChartTrackerStub = stubClass(trackerModule.ChartTracker); diff --git a/packages/devextreme/testing/helpers/visibilityChangeMock.js b/packages/devextreme/testing/helpers/visibilityChangeMock.js new file mode 100644 index 000000000000..01ff2d64e372 --- /dev/null +++ b/packages/devextreme/testing/helpers/visibilityChangeMock.js @@ -0,0 +1,11 @@ +import * as visibilityChange from 'common/core/events/visibility_change'; + +import { spySeam, stubSeam } from './moduleSeam.js'; + +export function spyVisibilityEvent(name) { + return spySeam(visibilityChange, name); +} + +export function stubVisibilityEvent(name) { + return stubSeam(visibilityChange, name); +} diff --git a/packages/devextreme/testing/helpers/vizMocks.js b/packages/devextreme/testing/helpers/vizMocks.js index 9f970a1c93d0..19d5b610f701 100644 --- a/packages/devextreme/testing/helpers/vizMocks.js +++ b/packages/devextreme/testing/helpers/vizMocks.js @@ -1,14 +1,14 @@ /* global currentAssert, currentTest, sinon */ import $ from 'jquery'; -import * as tooltipModule from 'viz/core/tooltip'; -import * as titleModule from 'viz/core/title'; +import tooltipModule from 'viz/core/tooltip'; +import titleModule from 'viz/core/title'; import legendModule from 'viz/components/legend'; import axisModule from 'viz/axes/base_axis'; -import * as pointModule from 'viz/series/points/base_point'; +import pointModule from 'viz/series/points/base_point'; import { Series } from 'viz/series/base_series'; -import * as loadingIndicatorModule from 'viz/core/loading_indicator'; -import * as exportMenuModule from 'viz/core/export'; +import loadingIndicatorModule from 'viz/core/loading_indicator'; +import exportMenuModule from 'viz/core/export'; import rendererModule from 'viz/core/renderers/renderer_default'; import errors from 'viz/core/errors_warnings'; import * as baseWidgetUtils from '__internal/viz/core/base_widget.utils'; diff --git a/packages/devextreme/testing/runner/README.md b/packages/devextreme/testing/runner/README.md index e35639ae1ce2..b1ea2acfb29c 100644 --- a/packages/devextreme/testing/runner/README.md +++ b/packages/devextreme/testing/runner/README.md @@ -25,9 +25,7 @@ HTTP static file server for the QUnit runner. - `aspnet.js` UMD artifact → `cjsInterop.rewriteAspnetArtifactToEsm` - Vendor / Globalize / Intl / VectorMap bundles → wrap as ESM modules - JSON (`?esm-export=1`) → `export default …` -- Serve **generated** mutable facades for modules in `MUTABLE_MODULE_GROUPS` / viz namespace-reexports; redirect only special hand-written cases (e.g. themes). -- For pure `import * as X; export default X` viz reexports, generate facades on the fly via `autoMutableFacade.tryBuildAutoMutableFacade`. -- Support `?dx-original=1` so a shim can import the **real** artifact without being redirected back to itself. +- Redirect the few artifact URLs that have a hand-written shim (themes) — see `handWrittenShims.ts`. This module is the integration point: almost every special-case rewrite for QUnit ESM loading goes through `tryServeStatic`. @@ -51,40 +49,54 @@ Serve-time **CJS → ESM** source rewrites for QUnit tests, helpers, and bundle --- -## `lib/autoMutableFacade.ts` +## Stubbing a module from a test -Generates **mutable ESM facades** at request time so QUnit can `sinon.stub` module APIs without editing `packages/devextreme/js`. +Modules are served as plain ESM artifacts. A module namespace object is frozen, so +`sinon.stub(module, 'name')` and `module.name = fn` both throw — the exporting module +is the only thing that can reassign its own binding. -**Two sources of facades:** +The house pattern is a **`DEBUG_set_*` seam**: turn the export into a `let` and add a +setter inside a `/// #DEBUG` block, which `-c qunit` builds keep and production builds +strip. -1. **`MUTABLE_MODULE_GROUPS`** ([`mutableModuleGroups.ts`](./lib/mutableModuleGroups.ts)) — explicit list of stub-able modules (animation frame, viz renderer, exporter, …). All aliases share one `globalThis` api; named exports use `wrapCtor` / live forwards. Import map points at the ESM artifact URL; `static.ts` serves the generated facade unless `?dx-original=1`. Codegen lives in `autoMutableFacade.ts`. -2. **Namespace-default reexports** (`import * as X; export default X`) under `viz/` — discovered automatically. +```ts +export let Renderer = function (options) { /* … */ }; + +/// #DEBUG +export function DEBUG_set_Renderer(value: typeof Renderer): void { + Renderer = value; +} +/// #ENDDEBUG +``` -Hand-written files under `esm-shims/` remain only for **non-generic** cases (themes composition, CSS inject, jquery/knockout globals, vendor stubs). +Product code that does `import { Renderer } from '…'` sees the new value, because ESM +named exports are live bindings. -Typical generated shape: +In tests, drive the seam through [`testing/helpers/moduleSeam.js`](../helpers/moduleSeam.js), +which re-attaches the `.restore()` that an anonymous `sinon.stub()` lacks: ```js -import * as original from '.../module.js?dx-original=1'; -import { createMutableApi, wrapCtor } from '.../mutable_facade.js'; +import { stubSeam, spySeam } from '../../helpers/moduleSeam.js'; -const api = createMutableApi(original, '__dxAutoMutable_…'); -export const Foo = wrapCtor(api, 'Foo'); -export default api; +// was: sinon.stub(rendererModule, 'Renderer') +const stub = stubSeam(rendererModule, 'Renderer', 'DEBUG_set_Renderer'); +// … +stub.restore(); + +// was: rendererModule.Renderer = fn; +rendererModule.DEBUG_set_Renderer(fn); ``` -To stub a new module, add a group entry in [`mutableModuleGroups.ts`](./lib/mutableModuleGroups.ts): +**Import the barrel that has a default export.** `cjsInterop` rewrites a default import +from a bare specifier to `('default' in ns ? ns.default : { ...ns })`. A barrel with no +default (`viz/core/utils.js`, `viz/core/renderers/renderer.js`) therefore hands the test +a dead **copy** — seams installed elsewhere stay invisible. Use the `_default` barrel +(`viz/core/utils_default`, `viz/core/renderers/renderer_default`), which is +`import * as X; export default X`. -```ts -{ - internal: '__internal/viz/core/title.js', // real module under esm/ - also: ['viz/core/title.js'], // extra artifact URLs → same facade - extraKeys: ['animation/frame'], // optional bare import-map keys - apiFromDefault: true, // when default export is the stub target -} -``` +Older sources use `exports.DEBUG_set_X = DEBUG_set_X` instead of `export function`; +`static.ts` rewrites that to a real ESM export at serve time, so both spellings work. -Import-map keys are derived as `strip(.js)` of `internal`/`also`, plus `extraKeys`. Prefer this over a new hand-written shim. --- ## `testing/helpers/esm-shims/` @@ -93,10 +105,10 @@ Browser modules that the import map (and/or `static.ts` artifact redirects) subs **Why they exist:** -- **Stubbing / mutation** — prefer `MUTABLE_MODULE_GROUPS` in `mutableModuleGroups.ts` (serve-time generated facades via `autoMutableFacade.ts`). Keep a hand-written shim only for custom composition (e.g. themes). +- **Custom composition** — e.g. `themes.js`, which the import map and `static.ts` both point at. Stubbing is *not* a reason to add a shim; use a `DEBUG_set_*` seam instead. - **Globals bridge** — e.g. `jquery.js` / `knockout.js` re-export the classic `