From e784e6f13af5777a508a74544787631e85ec9a05 Mon Sep 17 00:00:00 2001 From: Bayheck Date: Wed, 11 Oct 2023 20:23:35 +0600 Subject: [PATCH 1/7] feat: added typescript testcaferc configuration file support --- src/configuration/configuration-base.ts | 33 ++++++++++++++++++++++++- src/configuration/formats.ts | 1 + 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/configuration/configuration-base.ts b/src/configuration/configuration-base.ts index 5e2922b4940..847efb1fea0 100644 --- a/src/configuration/configuration-base.ts +++ b/src/configuration/configuration-base.ts @@ -1,5 +1,9 @@ -import { extname, isAbsolute } from 'path'; + +import { + extname, isAbsolute, +} from 'path'; import debug from 'debug'; + import JSON5 from 'json5'; import { @@ -21,6 +25,7 @@ import Extensions from './formats'; import { ReadConfigFileError } from '../errors/runtime'; import { RUNTIME_ERRORS } from '../errors/types'; + const DEBUG_LOGGER = debug('testcafe:configuration'); export default class Configuration { @@ -155,6 +160,7 @@ export default class Configuration { } public async _load (): Promise { + if (!this.defaultPaths?.length) return null; @@ -166,6 +172,8 @@ export default class Configuration { if (this._isJSConfiguration(filePath)) options = this._readJsConfigurationFileContent(filePath); + else if (this._isTSConfiguration(filePath)) + options = await this._readTsConfigurationFileContent(filePath); else { const configurationFileContent = await this._readConfigurationFileContent(filePath); @@ -178,6 +186,7 @@ export default class Configuration { const existedConfigs = configs.filter(config => !!config.options); + if (!existedConfigs.length) return null; @@ -210,6 +219,10 @@ export default class Configuration { return Configuration._hasExtension(filePath, Extensions.js) || Configuration._hasExtension(filePath, Extensions.cjs); } + protected _isTSConfiguration (filePath = this.filePath): boolean { + return Configuration._hasExtension(filePath, Extensions.ts) || Configuration._hasExtension(filePath, Extensions.cjs); + } + protected _isJSONConfiguration (filePath = this.filePath): boolean { return Configuration._hasExtension(filePath, Extensions.json); } @@ -229,6 +242,24 @@ export default class Configuration { return null; } + public async _readTsConfigurationFileContent (filePath = this.filePath): Promise { + if (filePath) { + delete require.cache[filePath]; + const TypeScriptTestFileCompiler = require('../compiler/test-file/formats/typescript/compiler'); + const compiler = new TypeScriptTestFileCompiler(); + + const precompiledCode = await compiler.precompile([{ filename: filePath }]); + + await compiler.compile(precompiledCode?.[0], filePath); + const options = require(filePath); + + return options; + } + + return null; + } + + public async _readConfigurationFileContent (filePath = this.filePath): Promise { try { return await readFile(filePath); diff --git a/src/configuration/formats.ts b/src/configuration/formats.ts index a26d8a45df4..3e3cbf542d9 100644 --- a/src/configuration/formats.ts +++ b/src/configuration/formats.ts @@ -2,6 +2,7 @@ enum Extensions { js = '.js', json = '.json', cjs = '.cjs', + ts = '.ts', } export default Extensions; From 6a128f38bb9dd94d2e41d6f36b7c8eb67dd39a7d Mon Sep 17 00:00:00 2001 From: Bayheck Date: Fri, 13 Oct 2023 21:53:09 +0600 Subject: [PATCH 2/7] testing: added test for configuration-test with custom ts config --- test/server/configuration-test.js | 208 +++++++++++------- .../data/configuration/module/module.js | 7 + .../configuration/typescript-module/module.ts | 5 + 3 files changed, 135 insertions(+), 85 deletions(-) create mode 100644 test/server/data/configuration/module/module.js create mode 100644 test/server/data/configuration/typescript-module/module.ts diff --git a/test/server/configuration-test.js b/test/server/configuration-test.js index 6f41c35b30e..e2b5e8a3690 100644 --- a/test/server/configuration-test.js +++ b/test/server/configuration-test.js @@ -36,6 +36,19 @@ const createJsConfig = (filePath, options) => { fs.writeFileSync(filePath, `module.exports = ${JSON.stringify(options)}`); }; +const createTsConfig = (filePath, options) => { + options = options || {}; + fs.writeFileSync(filePath, ` + const fs = require('fs'); + const path = require('path'); + const { nanoid } = require('nanoid'); + const jsCustomModule = require('./test/server/data/configuration/module/module.js'); + const tsCustomModule = require('./test/server/data/configuration/typescript-module/module.ts'); + + \n + module.exports = ${JSON.stringify(options)}`); +}; + const jsConfigIndex = TestCafeConfiguration.FILENAMES.findIndex(file=>file.includes(Extensions.js)); const jsonConfigIndex = TestCafeConfiguration.FILENAMES.findIndex(file=>file.includes(Extensions.json)); @@ -729,6 +742,116 @@ describe('TypeScriptConfiguration', function () { ); }); + describe('Custom Testcafe Config Path', () => { + let configuration; + + afterEach(async () => { + await del(configuration.defaultPaths); + }); + + it('Custom config path is used', () => { + const customConfigFile = 'custom11.testcaferc.json'; + + const options = { + 'hostname': '123.456.789', + 'port1': 1234, + 'port2': 5678, + 'src': 'path1/folder', + 'browser': 'edge', + }; + + createJSONConfig(customConfigFile, options); + + configuration = new TestCafeConfiguration(customConfigFile); + + return configuration.init() + .then(() => { + expect(pathUtil.basename(configuration.filePath)).eql(customConfigFile); + expect(configuration.getOption('hostname')).eql(options.hostname); + expect(configuration.getOption('port1')).eql(options.port1); + expect(configuration.getOption('port2')).eql(options.port2); + expect(configuration.getOption('src')).eql([ options.src ]); + expect(configuration.getOption('browser')).eql(options.browser); + }); + }); + + it('Custom js config path is used', async () => { + const customConfigFile = 'custom11.testcaferc.js'; + + const options = { + 'hostname': '123.456.789', + 'port1': 1234, + 'port2': 5678, + 'src': 'path1/folder', + 'browser': 'edge', + }; + + createJsConfig(customConfigFile, options); + + configuration = new TestCafeConfiguration(customConfigFile); + + await configuration.init(); + + expect(pathUtil.basename(configuration.filePath)).eql(customConfigFile); + expect(configuration.getOption('hostname')).eql(options.hostname); + expect(configuration.getOption('port1')).eql(options.port1); + expect(configuration.getOption('port2')).eql(options.port2); + expect(configuration.getOption('src')).eql([ options.src ]); + expect(configuration.getOption('browser')).eql(options.browser); + }); + + it('Custom ts config path is used', async () => { + const customConfigFile = 'custom11.testcaferc.ts'; + + const options = { + 'hostname': '123.456.789', + 'port1': 1234, + 'port2': 5678, + 'src': 'path1/folder', + 'browser': 'edge', + }; + + createTsConfig(customConfigFile, options); + + configuration = new TestCafeConfiguration(customConfigFile); + + await configuration.init(); + + expect(pathUtil.basename(configuration.filePath)).eql(customConfigFile); + expect(configuration.getOption('hostname')).eql(options.hostname); + expect(configuration.getOption('port1')).eql(options.port1); + expect(configuration.getOption('port2')).eql(options.port2); + expect(configuration.getOption('src')).eql([ options.src ]); + expect(configuration.getOption('browser')).eql(options.browser); + }); + + it('Constructor should revert back to default when no custom config', () => { + const defaultFileLocation = '.testcaferc.json'; + + const options = { + 'hostname': '123.456.789', + 'port1': 1234, + 'port2': 5678, + 'src': 'path1/folder', + 'browser': 'edge', + }; + + createJSONConfig(defaultFileLocation, options); + + configuration = new TestCafeConfiguration(); + + return configuration.init() + .then(() => { + expect(pathUtil.basename(configuration.filePath)).eql(defaultFileLocation); + expect(configuration.getOption('hostname')).eql(options.hostname); + expect(configuration.getOption('port1')).eql(options.port1); + expect(configuration.getOption('port2')).eql(options.port2); + expect(configuration.getOption('src')).eql([ options.src ]); + expect(configuration.getOption('browser')).eql(options.browser); + }); + }); + }); + describe('With configuration file', () => { tmp.setGracefulCleanup(); @@ -917,89 +1040,4 @@ describe('TypeScriptConfiguration', function () { }); }); }); - - describe('Custom Testcafe Config Path', () => { - let configuration; - - afterEach(async () => { - await del(configuration.defaultPaths); - }); - - it('Custom config path is used', () => { - const customConfigFile = 'custom11.testcaferc.json'; - - const options = { - 'hostname': '123.456.789', - 'port1': 1234, - 'port2': 5678, - 'src': 'path1/folder', - 'browser': 'edge', - }; - - createJSONConfig(customConfigFile, options); - - configuration = new TestCafeConfiguration(customConfigFile); - - return configuration.init() - .then(() => { - expect(pathUtil.basename(configuration.filePath)).eql(customConfigFile); - expect(configuration.getOption('hostname')).eql(options.hostname); - expect(configuration.getOption('port1')).eql(options.port1); - expect(configuration.getOption('port2')).eql(options.port2); - expect(configuration.getOption('src')).eql([ options.src ]); - expect(configuration.getOption('browser')).eql(options.browser); - }); - }); - - it('Custom js config path is used', async () => { - const customConfigFile = 'custom11.testcaferc.js'; - - const options = { - 'hostname': '123.456.789', - 'port1': 1234, - 'port2': 5678, - 'src': 'path1/folder', - 'browser': 'edge', - }; - - createJsConfig(customConfigFile, options); - - configuration = new TestCafeConfiguration(customConfigFile); - - await configuration.init(); - - expect(pathUtil.basename(configuration.filePath)).eql(customConfigFile); - expect(configuration.getOption('hostname')).eql(options.hostname); - expect(configuration.getOption('port1')).eql(options.port1); - expect(configuration.getOption('port2')).eql(options.port2); - expect(configuration.getOption('src')).eql([ options.src ]); - expect(configuration.getOption('browser')).eql(options.browser); - }); - - it('Constructor should revert back to default when no custom config', () => { - const defaultFileLocation = '.testcaferc.json'; - - const options = { - 'hostname': '123.456.789', - 'port1': 1234, - 'port2': 5678, - 'src': 'path1/folder', - 'browser': 'edge', - }; - - createJSONConfig(defaultFileLocation, options); - - configuration = new TestCafeConfiguration(); - - return configuration.init() - .then(() => { - expect(pathUtil.basename(configuration.filePath)).eql(defaultFileLocation); - expect(configuration.getOption('hostname')).eql(options.hostname); - expect(configuration.getOption('port1')).eql(options.port1); - expect(configuration.getOption('port2')).eql(options.port2); - expect(configuration.getOption('src')).eql([ options.src ]); - expect(configuration.getOption('browser')).eql(options.browser); - }); - }); - }); }); diff --git a/test/server/data/configuration/module/module.js b/test/server/data/configuration/module/module.js new file mode 100644 index 00000000000..a7ddc5cf0e4 --- /dev/null +++ b/test/server/data/configuration/module/module.js @@ -0,0 +1,7 @@ +function module() { + return 'module'; +} + +module.exports = { + module: module, +} diff --git a/test/server/data/configuration/typescript-module/module.ts b/test/server/data/configuration/typescript-module/module.ts new file mode 100644 index 00000000000..26581fb7116 --- /dev/null +++ b/test/server/data/configuration/typescript-module/module.ts @@ -0,0 +1,5 @@ +function greet (): string { + return 'Hello World!'; +} + +module.exports = { greet }; From 1d5c72698cb8ee5c8af4b6b3f5e2b3b1356adb61 Mon Sep 17 00:00:00 2001 From: Alex Kamaev Date: Mon, 16 Oct 2023 12:00:20 +0400 Subject: [PATCH 3/7] 1 --- test/server/test-run-commands-test.js | 3687 ----------------- test/server/test-run-controller-test.js | 38 - .../server/test-run-driver-task-queue-test.js | 145 - test/server/test-run-error-formatting-test.js | 872 ---- test/server/test-run-request-handler-test.js | 17 - test/server/test-run-tracker-test.js | 86 - test/server/util-test.js | 721 ---- test/server/video-recorder-test.js | 323 -- test/server/warning-log-test.js | 79 - 9 files changed, 5968 deletions(-) delete mode 100644 test/server/test-run-commands-test.js delete mode 100644 test/server/test-run-controller-test.js delete mode 100644 test/server/test-run-driver-task-queue-test.js delete mode 100644 test/server/test-run-error-formatting-test.js delete mode 100644 test/server/test-run-request-handler-test.js delete mode 100644 test/server/test-run-tracker-test.js delete mode 100644 test/server/util-test.js delete mode 100644 test/server/video-recorder-test.js delete mode 100644 test/server/warning-log-test.js diff --git a/test/server/test-run-commands-test.js b/test/server/test-run-commands-test.js deleted file mode 100644 index 6a14600c9cf..00000000000 --- a/test/server/test-run-commands-test.js +++ /dev/null @@ -1,3687 +0,0 @@ -const expect = require('chai').expect; -const TYPE = require('../../lib/test-run/commands/type'); -const createCommandFromObject = require('../../lib/test-run/commands/from-object'); -const SelectorBuilder = require('../../lib/client-functions/selectors/selector-builder'); -const assertThrow = require('./helpers/assert-runtime-error').assertThrow; -const TestController = require('../../lib/api/test-controller'); -const path = require('path'); -const semver = require('semver'); - -const testRunMock = { - test: { - testFile: { - filename: path.join(__dirname, 'test.js'), - }, - }, -}; - -testRunMock.controller = new TestController(testRunMock); - -const CHILD_SELECTOR_PROPERTY_NAMES = [ - 'selector', - 'startSelector', - 'endSelector', - 'destinationSelector', -]; - -function ensureActionId (command, { type }) { - if (!command.actionId) - throw new Error('command does not have action id'); - - command.actionId = type; - - for (const selectorProperty of CHILD_SELECTOR_PROPERTY_NAMES) { - if (command[selectorProperty]) { - if (!command[selectorProperty].actionId) - throw new Error('nested command does not have action id'); - - command[selectorProperty].actionId = 'child-command-selector'; - } - } -} - -function createCommand (obj) { - try { - const command = createCommandFromObject(obj, testRunMock); - - ensureActionId(command, obj); - - return command; - } - catch (e) { - // TODO: add an assertion for APIError - if (e.originError) - e.originError = null; - - throw e; - } -} - -function assertErrorMessage (fn, expectedErrMessage) { - let actualErr = null; - - try { - fn(); - } - catch (err) { - actualErr = err; - } - - expect(actualErr.message).eql(expectedErrMessage); -} - -function makeSelector (str, skipVisibilityCheck, needError, strictError) { - const builder = new SelectorBuilder(str, { - visibilityCheck: !skipVisibilityCheck, - needError, strictError, - }, { instantiation: 'Selector' }); - const command = builder.getCommand(); - - command.actionId = 'child-command-selector'; - - return JSON.parse(JSON.stringify(command)); -} - -describe('Test run commands', () => { - describe('Construction from object and serialization', () => { - it('Should create ClickCommand from object', () => { - let commandObj = { - type: TYPE.click, - selector: '#yo', - - options: { - offsetX: 23, - offsetY: 32, - caretPos: 2, - speed: 0.5, - - modifiers: { - ctrl: true, - shift: true, - alt: true, - meta: true, - }, - }, - }; - - let command = createCommand(commandObj); - - expect(JSON.parse(JSON.stringify(command))).eql({ - type: TYPE.click, - actionId: TYPE.click, - selector: makeSelector('#yo'), - - options: { - offsetX: 23, - offsetY: 32, - caretPos: 2, - speed: 0.5, - - modifiers: { - ctrl: true, - alt: true, - shift: true, - meta: true, - }, - }, - }); - - commandObj = { - type: TYPE.click, - selector: '#yo', - }; - - command = createCommand(commandObj); - - expect(JSON.parse(JSON.stringify(command))).eql({ - type: TYPE.click, - actionId: TYPE.click, - selector: makeSelector('#yo'), - - options: { - offsetX: null, - offsetY: null, - caretPos: null, - speed: null, - - modifiers: { - ctrl: false, - alt: false, - shift: false, - meta: false, - }, - }, - }); - }); - - it('Should create RightClickCommand from object', () => { - let commandObj = { - type: TYPE.rightClick, - selector: '#yo', - - options: { - offsetX: 23, - offsetY: 32, - caretPos: 2, - speed: 0.5, - - modifiers: { - ctrl: true, - shift: false, - alt: true, - meta: false, - }, - }, - }; - - let command = createCommand(commandObj); - - expect(JSON.parse(JSON.stringify(command))).eql({ - type: TYPE.rightClick, - actionId: TYPE.rightClick, - selector: makeSelector('#yo'), - - options: { - offsetX: 23, - offsetY: 32, - caretPos: 2, - speed: 0.5, - - modifiers: { - ctrl: true, - alt: true, - shift: false, - meta: false, - }, - }, - }); - - commandObj = { - type: TYPE.rightClick, - selector: '#yo', - }; - - command = createCommand(commandObj); - - expect(JSON.parse(JSON.stringify(command))).eql({ - type: TYPE.rightClick, - actionId: TYPE.rightClick, - selector: makeSelector('#yo'), - - options: { - offsetX: null, - offsetY: null, - caretPos: null, - speed: null, - - modifiers: { - ctrl: false, - alt: false, - shift: false, - meta: false, - }, - }, - }); - }); - - it('Should create DoubleClickCommand from object', () => { - let commandObj = { - type: TYPE.doubleClick, - selector: '#yo', - - options: { - offsetX: 23, - offsetY: 32, - caretPos: 2, - speed: 0.5, - - modifiers: { - ctrl: true, - shift: false, - alt: true, - meta: false, - }, - }, - }; - - let command = createCommand(commandObj); - - expect(JSON.parse(JSON.stringify(command))).eql({ - type: TYPE.doubleClick, - actionId: TYPE.doubleClick, - selector: makeSelector('#yo'), - - options: { - offsetX: 23, - offsetY: 32, - caretPos: 2, - speed: 0.5, - - modifiers: { - ctrl: true, - alt: true, - shift: false, - meta: false, - }, - }, - }); - - commandObj = { - type: TYPE.doubleClick, - selector: '#yo', - }; - - command = createCommand(commandObj); - - expect(JSON.parse(JSON.stringify(command))).eql({ - type: TYPE.doubleClick, - actionId: TYPE.doubleClick, - selector: makeSelector('#yo'), - - options: { - offsetX: null, - offsetY: null, - caretPos: null, - speed: null, - - modifiers: { - ctrl: false, - alt: false, - shift: false, - meta: false, - }, - }, - }); - }); - - it('Should create HoverCommand from object', () => { - let commandObj = { - type: TYPE.hover, - selector: '#yo', - - options: { - offsetX: 23, - offsetY: 32, - speed: 0.5, - - modifiers: { - ctrl: true, - shift: false, - alt: true, - meta: false, - }, - }, - }; - - let command = createCommand(commandObj); - - expect(JSON.parse(JSON.stringify(command))).eql({ - type: TYPE.hover, - actionId: TYPE.hover, - selector: makeSelector('#yo'), - - options: { - offsetX: 23, - offsetY: 32, - speed: 0.5, - - modifiers: { - ctrl: true, - alt: true, - shift: false, - meta: false, - }, - }, - }); - - commandObj = { - type: TYPE.hover, - selector: '#yo', - }; - - command = createCommand(commandObj); - - expect(JSON.parse(JSON.stringify(command))).eql({ - type: TYPE.hover, - actionId: TYPE.hover, - selector: makeSelector('#yo'), - - options: { - offsetX: null, - offsetY: null, - speed: null, - - modifiers: { - ctrl: false, - alt: false, - shift: false, - meta: false, - }, - }, - }); - }); - - it('Should create DragCommand from object', () => { - let commandObj = { - type: TYPE.drag, - selector: '#yo', - dragOffsetX: 10, - dragOffsetY: -15, - - options: { - offsetX: 23, - offsetY: 32, - speed: 0.5, - - modifiers: { - ctrl: true, - shift: false, - alt: true, - meta: false, - }, - }, - }; - - let command = createCommand(commandObj); - - expect(JSON.parse(JSON.stringify(command))).eql({ - type: TYPE.drag, - actionId: TYPE.drag, - selector: makeSelector('#yo'), - dragOffsetX: 10, - dragOffsetY: -15, - - options: { - offsetX: 23, - offsetY: 32, - speed: 0.5, - - modifiers: { - ctrl: true, - alt: true, - shift: false, - meta: false, - }, - }, - }); - - commandObj = { - type: TYPE.drag, - selector: '#yo', - dragOffsetX: 10, - dragOffsetY: -15, - }; - - command = createCommand(commandObj); - - expect(JSON.parse(JSON.stringify(command))).eql({ - type: TYPE.drag, - actionId: TYPE.drag, - selector: makeSelector('#yo'), - dragOffsetX: 10, - dragOffsetY: -15, - - options: { - offsetX: null, - offsetY: null, - speed: null, - - modifiers: { - ctrl: false, - alt: false, - shift: false, - meta: false, - }, - }, - }); - }); - - it('Should create DragToElementCommand from object', () => { - let commandObj = { - type: TYPE.dragToElement, - selector: '#yo', - destinationSelector: '#destination', - - options: { - offsetX: 23, - offsetY: 32, - destinationOffsetX: 12, - destinationOffsetY: 21, - speed: 0.5, - - modifiers: { - ctrl: true, - shift: false, - alt: true, - meta: false, - }, - }, - }; - - let command = createCommand(commandObj); - - expect(JSON.parse(JSON.stringify(command))).eql({ - type: TYPE.dragToElement, - actionId: TYPE.dragToElement, - selector: makeSelector('#yo'), - destinationSelector: makeSelector('#destination'), - - options: { - offsetX: 23, - offsetY: 32, - destinationOffsetX: 12, - destinationOffsetY: 21, - speed: 0.5, - - - modifiers: { - ctrl: true, - alt: true, - shift: false, - meta: false, - }, - }, - }); - - commandObj = { - type: TYPE.dragToElement, - selector: '#yo', - destinationSelector: '#destination', - }; - - command = createCommand(commandObj); - - expect(JSON.parse(JSON.stringify(command))).eql({ - type: TYPE.dragToElement, - actionId: TYPE.dragToElement, - - selector: makeSelector('#yo'), - destinationSelector: makeSelector('#destination'), - - options: { - offsetX: null, - offsetY: null, - destinationOffsetX: null, - destinationOffsetY: null, - speed: null, - - modifiers: { - ctrl: false, - alt: false, - shift: false, - meta: false, - }, - }, - }); - }); - - it('Should create TypeTextCommand from object', () => { - let commandObj = { - type: TYPE.typeText, - selector: '#yo', - text: 'testText', - - options: { - offsetX: 23, - offsetY: 32, - caretPos: 2, - speed: 0.5, - replace: true, - paste: true, - - modifiers: { - ctrl: true, - shift: false, - alt: false, - meta: false, - }, - - confidential: true, - }, - }; - - let command = createCommand(commandObj); - - expect(JSON.parse(JSON.stringify(command))).eql({ - type: TYPE.typeText, - actionId: TYPE.typeText, - selector: makeSelector('#yo', false, true, true), - text: 'testText', - - options: { - offsetX: 23, - offsetY: 32, - caretPos: 2, - speed: 0.5, - replace: true, - paste: true, - - modifiers: { - ctrl: true, - alt: false, - shift: false, - meta: false, - }, - - confidential: true, - }, - }); - - commandObj = { - type: TYPE.typeText, - selector: '#yo', - text: 'testText', - }; - - command = createCommand(commandObj); - - expect(JSON.parse(JSON.stringify(command))).eql({ - type: TYPE.typeText, - actionId: TYPE.typeText, - selector: makeSelector('#yo', false, true, true), - text: 'testText', - - options: { - offsetX: null, - offsetY: null, - caretPos: null, - speed: null, - replace: false, - paste: false, - - modifiers: { - ctrl: false, - alt: false, - shift: false, - meta: false, - }, - }, - }); - }); - - it('Should create SelectTextCommand from object', () => { - let commandObj = { - type: TYPE.selectText, - selector: '#yo', - startPos: 1, - endPos: 2, - - options: { - speed: 0.5, - }, - }; - - let command = createCommand(commandObj); - - expect(JSON.parse(JSON.stringify(command))).eql({ - type: TYPE.selectText, - actionId: TYPE.selectText, - selector: makeSelector('#yo'), - startPos: 1, - endPos: 2, - - options: { - speed: 0.5, - }, - }); - - commandObj = { - type: TYPE.selectText, - selector: '#yo', - }; - - command = createCommand(commandObj); - - expect(JSON.parse(JSON.stringify(command))).eql({ - type: TYPE.selectText, - actionId: TYPE.selectText, - selector: makeSelector('#yo'), - startPos: null, - endPos: null, - - options: { - speed: null, - }, - }); - }); - - it('Should create SelectTextAreaContentCommand from object', () => { - let commandObj = { - type: TYPE.selectTextAreaContent, - selector: '#yo', - startLine: 0, - startPos: 1, - endLine: 2, - endPos: 3, - - options: { - speed: 0.5, - }, - }; - - let command = createCommand(commandObj); - - expect(JSON.parse(JSON.stringify(command))).eql({ - type: TYPE.selectTextAreaContent, - actionId: TYPE.selectTextAreaContent, - selector: makeSelector('#yo'), - startLine: 0, - startPos: 1, - endLine: 2, - endPos: 3, - - options: { - speed: 0.5, - }, - }); - - commandObj = { - type: TYPE.selectTextAreaContent, - selector: '#yo', - }; - - command = createCommand(commandObj); - - expect(JSON.parse(JSON.stringify(command))).eql({ - type: TYPE.selectTextAreaContent, - actionId: TYPE.selectTextAreaContent, - selector: makeSelector('#yo'), - startLine: null, - startPos: null, - endLine: null, - endPos: null, - - options: { - speed: null, - }, - }); - }); - - it('Should create SelectEditableContentCommand from object', () => { - let commandObj = { - type: TYPE.selectEditableContent, - startSelector: '#node1', - endSelector: '#node2', - - options: { - speed: 0.5, - }, - }; - - let command = createCommand(commandObj); - - expect(JSON.parse(JSON.stringify(command))).eql({ - type: TYPE.selectEditableContent, - actionId: TYPE.selectEditableContent, - startSelector: makeSelector('#node1'), - endSelector: makeSelector('#node2'), - - options: { - speed: 0.5, - }, - }); - - commandObj = { - type: TYPE.selectEditableContent, - startSelector: '#node1', - }; - - command = createCommand(commandObj); - - expect(JSON.parse(JSON.stringify(command))).eql({ - type: TYPE.selectEditableContent, - actionId: TYPE.selectEditableContent, - startSelector: makeSelector('#node1'), - endSelector: null, - - options: { - speed: null, - }, - }); - }); - - it('Should create PressKeyCommand from object', () => { - const commandObj = { - type: TYPE.pressKey, - keys: 'a+b c', - - options: { - speed: 0.5, - }, - }; - - const command = createCommand(commandObj); - - expect(JSON.parse(JSON.stringify(command))).eql({ - type: TYPE.pressKey, - actionId: TYPE.pressKey, - keys: 'a+b c', - - options: { - speed: 0.5, - }, - }); - }); - - it('Should create WaitCommand from object', () => { - const commandObj = { - type: TYPE.wait, - timeout: 1000, - }; - const command = createCommand(commandObj); - - expect(JSON.parse(JSON.stringify(command))).eql({ - type: TYPE.wait, - actionId: TYPE.wait, - timeout: 1000, - }); - }); - - it('Should create NavigateToCommand from object', () => { - const commandObj = { - type: TYPE.navigateTo, - url: 'localhost', - stateSnapshot: 'stateSnapshot', - forceReload: true, - }; - - const command = createCommand(commandObj); - - expect(JSON.parse(JSON.stringify(command))).eql({ - type: TYPE.navigateTo, - actionId: TYPE.navigateTo, - url: 'localhost', - stateSnapshot: 'stateSnapshot', - forceReload: true, - }); - }); - - it('Should create SetFilesToUploadCommand from object', function () { - let commandObj = { - type: TYPE.setFilesToUpload, - selector: '#yo', - filePath: '/test/path', - }; - - let command = createCommand(commandObj); - - expect(JSON.parse(JSON.stringify(command))).eql({ - type: TYPE.setFilesToUpload, - actionId: TYPE.setFilesToUpload, - selector: makeSelector('#yo', true), - filePath: '/test/path', - }); - - commandObj = { - type: TYPE.setFilesToUpload, - selector: '#yo', - filePath: ['/test/path/1', '/test/path/2'], - }; - - command = createCommand(commandObj); - - expect(JSON.parse(JSON.stringify(command))).eql({ - type: TYPE.setFilesToUpload, - actionId: TYPE.setFilesToUpload, - selector: makeSelector('#yo', true), - filePath: ['/test/path/1', '/test/path/2'], - }); - }); - - it('Should create ClearUploadCommand from object', function () { - const commandObj = { - type: TYPE.clearUpload, - selector: '#yo', - }; - - const command = createCommand(commandObj); - - expect(JSON.parse(JSON.stringify(command))).eql({ - type: TYPE.clearUpload, - actionId: TYPE.clearUpload, - selector: makeSelector('#yo', true), - }); - }); - - it('Should create TakeScreenshotCommand from object', function () { - let commandObj = { - type: TYPE.takeScreenshot, - path: 'custom', - fullPage: true, - }; - - let command = createCommand(commandObj); - - expect(JSON.parse(JSON.stringify(command))).eql({ - type: TYPE.takeScreenshot, - actionId: TYPE.takeScreenshot, - markData: '', - markSeed: null, - path: 'custom', - fullPage: true, - }); - - commandObj = { - type: TYPE.takeScreenshot, - fullPage: void 0, - }; - - command = createCommand(commandObj); - - expect(JSON.parse(JSON.stringify(command))).eql({ - type: TYPE.takeScreenshot, - actionId: TYPE.takeScreenshot, - markData: '', - markSeed: null, - path: '', - }); - }); - - it('Should create TakeElementScreenshotCommand from object', function () { - const commandObj = { - type: TYPE.takeElementScreenshot, - selector: '#yo', - path: 'custom', - - options: { - crop: { - left: 50, - top: 13, - }, - }, - }; - - const command = createCommand(commandObj); - - expect(JSON.parse(JSON.stringify(command))).eql({ - type: TYPE.takeElementScreenshot, - actionId: TYPE.takeElementScreenshot, - markData: '', - markSeed: null, - selector: makeSelector('#yo'), - path: 'custom', - - options: { - scrollTargetX: null, - scrollTargetY: null, - speed: null, - - crop: { - left: 50, - right: null, - top: 13, - bottom: null, - }, - - includeMargins: false, - includeBorders: true, - includePaddings: true, - }, - }); - }); - - it('Should create ResizeWindowCommand from object', function () { - const commandObj = { - type: TYPE.resizeWindow, - width: 100, - height: 100, - }; - - const command = createCommand(commandObj); - - expect(JSON.parse(JSON.stringify(command))).eql({ - type: TYPE.resizeWindow, - actionId: TYPE.resizeWindow, - width: 100, - height: 100, - }); - }); - - it('Should create ResizeWindowToFitDeviceCommand from object', function () { - let commandObj = { - type: TYPE.resizeWindowToFitDevice, - device: 'iPhone', - - options: { - portraitOrientation: true, - }, - }; - - let command = createCommand(commandObj); - - expect(JSON.parse(JSON.stringify(command))).eql({ - type: TYPE.resizeWindowToFitDevice, - actionId: TYPE.resizeWindowToFitDevice, - device: 'iPhone', - options: { portraitOrientation: true }, - }); - - commandObj = { - type: TYPE.resizeWindowToFitDevice, - device: 'iPhone', - }; - - command = createCommand(commandObj); - - expect(JSON.parse(JSON.stringify(command))).eql({ - type: TYPE.resizeWindowToFitDevice, - actionId: TYPE.resizeWindowToFitDevice, - device: 'iPhone', - options: { portraitOrientation: false }, - }); - }); - - it('Should create SwitchToIframeCommand from object', function () { - const commandObj = { - type: TYPE.switchToIframe, - selector: '#iframe', - }; - const command = createCommand(commandObj); - - expect(JSON.parse(JSON.stringify(command))).eql({ - type: TYPE.switchToIframe, - actionId: TYPE.switchToIframe, - selector: makeSelector('#iframe'), - }); - }); - - it('Should create SwitchToMainWindowCommand from object', function () { - const commandObj = { - type: TYPE.switchToMainWindow, - }; - const command = createCommand(commandObj); - - expect(JSON.parse(JSON.stringify(command))).eql({ - type: TYPE.switchToMainWindow, - actionId: TYPE.switchToMainWindow, - }); - }); - - it('Should create SetTestSpeedCommand from object', function () { - const commandObj = { - type: TYPE.setTestSpeed, - speed: 0.5, - }; - const command = createCommand(commandObj); - - expect(JSON.parse(JSON.stringify(command))).eql({ - type: TYPE.setTestSpeed, - actionId: TYPE.setTestSpeed, - speed: 0.5, - }); - }); - - it('Should create SetPageLoadTimeoutCommand from object', function () { - const commandObj = { - type: TYPE.setPageLoadTimeout, - duration: 3, - }; - const command = createCommand(commandObj); - - expect(JSON.parse(JSON.stringify(command))).eql({ - type: TYPE.setPageLoadTimeout, - actionId: TYPE.setPageLoadTimeout, - duration: 3, - }); - }); - - it('Should create AssertionCommand from object', function () { - let commandObj = { - type: TYPE.assertion, - assertionType: 'eql', - actual: 1, - expected: 0.2, - expected2: 3.5, - message: 'ok', - - options: { - timeout: 100, - }, - }; - - let command = createCommand(commandObj); - - expect(JSON.parse(JSON.stringify(command))).eql({ - type: TYPE.assertion, - actionId: TYPE.assertion, - assertionType: 'eql', - actual: 1, - expected: 0.2, - expected2: 3.5, - message: 'ok', - - options: { - timeout: 100, - allowUnawaitedPromise: false, - }, - }); - - commandObj = { - type: TYPE.assertion, - assertionType: 'ok', - actual: 1, - }; - - command = createCommand(commandObj); - - expect(JSON.parse(JSON.stringify(command))).eql({ - type: TYPE.assertion, - actionId: TYPE.assertion, - assertionType: 'ok', - actual: 1, - message: null, - - options: { - allowUnawaitedPromise: false, - }, - }); - }); - - it('Should create ExecuteExpressionCommand from object', function () { - let commandObj = { - type: TYPE.executeExpression, - - expression: 'js-expression', - resultVariableName: 'variable', - }; - - let command = createCommand(commandObj); - - expect(JSON.parse(JSON.stringify(command))).eql({ - type: TYPE.executeExpression, - actionId: TYPE.executeExpression, - - expression: 'js-expression', - resultVariableName: 'variable', - }); - - commandObj = { - type: TYPE.executeExpression, - expression: 'js-expression', - }; - - command = createCommand(commandObj); - - expect(JSON.parse(JSON.stringify(command))).eql({ - type: TYPE.executeExpression, - actionId: TYPE.executeExpression, - - expression: 'js-expression', - resultVariableName: null, - }); - }); - - it('Should process js expression as a Selector', function () { - const commandObj = { - type: TYPE.click, - selector: { - type: 'js-expr', - value: 'Selector(\'#yo\')', - }, - }; - - const command = createCommand(commandObj); - - expect(JSON.parse(JSON.stringify(command))).eql({ - type: TYPE.click, - actionId: TYPE.click, - selector: makeSelector('#yo'), - - options: { - offsetX: null, - offsetY: null, - caretPos: null, - speed: null, - - modifiers: { - ctrl: false, - alt: false, - shift: false, - meta: false, - }, - }, - }); - }); - - it('Should process js expression as an assertion parameter', function () { - const commandObj = { - type: TYPE.assertion, - assertionType: 'eql', - - actual: { - type: 'js-expr', - value: '1 + 2', - }, - - expected: 1, - }; - - const command = createCommand(commandObj); - - expect(JSON.parse(JSON.stringify(command))).eql({ - type: TYPE.assertion, - actionId: TYPE.assertion, - assertionType: 'eql', - actual: 3, - expected: 1, - message: null, - - options: { - allowUnawaitedPromise: false, - }, - }); - }); - - it('Should create RecorderCommand from object', function () { - let commandObj = { - type: TYPE.recorder, - subtype: 'test', - }; - - let command = createCommand(commandObj); - - expect(JSON.parse(JSON.stringify(command))).eql({ - type: TYPE.recorder, - actionId: TYPE.recorder, - subtype: 'test', - - forceExecutionInTopWindowOnly: false, - }); - - commandObj = { - type: TYPE.recorder, - subtype: 'test', - - forceExecutionInTopWindowOnly: true, - }; - - command = createCommand(commandObj); - - expect(JSON.parse(JSON.stringify(command))).eql({ - type: TYPE.recorder, - actionId: TYPE.recorder, - subtype: 'test', - - forceExecutionInTopWindowOnly: true, - }); - }); - - it('Should create GetCookiesCommand from object', () => { - const commandObj = { - type: TYPE.getCookies, - urls: ['http://localhost/'], - - cookies: [{ - 'name': 'apiCookie1', - }], - }; - - const command = createCommand(commandObj); - - expect(JSON.parse(JSON.stringify(command))).eql({ - type: TYPE.getCookies, - actionId: TYPE.getCookies, - urls: ['http://localhost/'], - - cookies: [{ - 'name': 'apiCookie1', - }], - }); - }); - - it('Should create SetCookiesCommand from object', () => { - const commandObj = { - type: TYPE.setCookies, - url: [], - - cookies: [{ - name: 'apiCookie13', - value: 'value13', - domain: 'some-another-domain.com', - path: '/', - }], - }; - - const command = createCommand(commandObj); - - expect(JSON.parse(JSON.stringify(command))).eql({ - type: TYPE.setCookies, - actionId: TYPE.setCookies, - url: [], - - cookies: [{ - name: 'apiCookie13', - value: 'value13', - domain: 'some-another-domain.com', - path: '/', - }], - }); - }); - - it('Should create DeleteCookiesCommand from object', () => { - const commandObj = { - type: TYPE.deleteCookies, - urls: ['http://localhost/'], - - cookies: [{ - name: 'apiCookie13', - }], - }; - - const command = createCommand(commandObj); - - expect(JSON.parse(JSON.stringify(command))).eql({ - type: TYPE.deleteCookies, - actionId: TYPE.deleteCookies, - urls: ['http://localhost/'], - - cookies: [{ - name: 'apiCookie13', - }], - }); - }); - - it('Should create RequestCommand from object', () => { - const commandObj = { - type: TYPE.request, - url: 'http://localhost/', - - options: { - method: 'GET', - }, - }; - - const command = createCommand(commandObj); - - expect(JSON.parse(JSON.stringify(command))).eql({ - type: TYPE.request, - actionId: TYPE.request, - url: 'http://localhost/', - - options: { - method: 'GET', - }, - }); - }); - }); - - describe('Validation', function () { - it('Should validate СlickСommand', function () { - assertThrow( - function () { - return createCommand({ - type: TYPE.click, - }); - }, - { - isTestCafeError: true, - code: 'E23', - selectorName: 'selector', - errMsg: 'Cannot initialize a Selector because Selector is undefined, and not one of the following: ' + - 'a CSS selector string, a Selector object, a node snapshot, a function, or a Promise returned by a Selector.', - - callsite: null, - originError: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.click, - selector: 1, - }); - }, - { - isTestCafeError: true, - code: 'E23', - selectorName: 'selector', - errMsg: 'Cannot initialize a Selector because Selector is number, and not one of the following: ' + - 'a CSS selector string, a Selector object, a node snapshot, a function, or a Promise returned by a Selector.', - - callsite: null, - originError: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.click, - selector: 'element', - options: 1, - }); - }, - { - isTestCafeError: true, - code: 'E14', - actualType: 'number', - callsite: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.click, - selector: 'element', - options: { - offsetX: 'ClickOptions.offsetX', - }, - }); - }, - { - isTestCafeError: true, - code: 'E9', - optionName: 'ClickOptions.offsetX', - actualValue: 'string', - callsite: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.click, - selector: 'element', - options: { - offsetX: 10.5, - }, - }); - }, - { - isTestCafeError: true, - code: 'E9', - optionName: 'ClickOptions.offsetX', - actualValue: 10.5, - callsite: null, - } - ); - }); - - it('Should validate RightСlickСommand', function () { - assertThrow( - function () { - return createCommand({ - type: TYPE.rightClick, - }); - }, - { - isTestCafeError: true, - code: 'E23', - selectorName: 'selector', - errMsg: 'Cannot initialize a Selector because Selector is undefined, and not one of the following: ' + - 'a CSS selector string, a Selector object, a node snapshot, a function, or a Promise returned by a Selector.', - - callsite: null, - originError: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.rightClick, - selector: true, - }); - }, - { - isTestCafeError: true, - code: 'E23', - selectorName: 'selector', - errMsg: 'Cannot initialize a Selector because Selector is boolean, and not one of the following: ' + - 'a CSS selector string, a Selector object, a node snapshot, a function, or a Promise returned by a Selector.', - - callsite: null, - originError: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.rightClick, - selector: 'element', - options: 'options', - }); - }, - { - isTestCafeError: true, - code: 'E14', - actualType: 'string', - callsite: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.rightClick, - selector: 'element', - options: { - offsetX: false, - }, - }); - }, - { - isTestCafeError: true, - code: 'E9', - optionName: 'ClickOptions.offsetX', - actualValue: 'boolean', - callsite: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.rightClick, - selector: 'element', - options: { - modifiers: { - shift: 'true', - }, - }, - }); - }, - { - isTestCafeError: true, - code: 'E11', - optionName: 'ModifiersOptions.shift', - actualValue: 'string', - callsite: null, - } - ); - }); - - it('Should validate DoubleСlickСommand', function () { - assertThrow( - function () { - return createCommand({ - type: TYPE.doubleClick, - }); - }, - { - isTestCafeError: true, - code: 'E23', - selectorName: 'selector', - errMsg: 'Cannot initialize a Selector because Selector is undefined, and not one of the following: ' + - 'a CSS selector string, a Selector object, a node snapshot, a function, or a Promise returned by a Selector.', - - callsite: null, - originError: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.doubleClick, - selector: true, - }); - }, - { - isTestCafeError: true, - code: 'E23', - selectorName: 'selector', - errMsg: 'Cannot initialize a Selector because Selector is boolean, and not one of the following: ' + - 'a CSS selector string, a Selector object, a node snapshot, a function, or a Promise returned by a Selector.', - - callsite: null, - originError: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.doubleClick, - selector: 'element', - options: 1, - }); - }, - { - isTestCafeError: true, - code: 'E14', - actualType: 'number', - callsite: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.doubleClick, - selector: 'element', - options: { - caretPos: '5', - }, - }); - }, - { - isTestCafeError: true, - code: 'E10', - optionName: 'ClickOptions.caretPos', - actualValue: 'string', - callsite: null, - } - ); - }); - - it('Should validate HoverСommand', function () { - assertThrow( - function () { - return createCommand({ - type: TYPE.hover, - }); - }, - { - isTestCafeError: true, - code: 'E23', - selectorName: 'selector', - errMsg: 'Cannot initialize a Selector because Selector is undefined, and not one of the following: ' + - 'a CSS selector string, a Selector object, a node snapshot, a function, or a Promise returned by a Selector.', - - callsite: null, - originError: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.hover, - selector: 1, - }); - }, - { - isTestCafeError: true, - code: 'E23', - selectorName: 'selector', - errMsg: 'Cannot initialize a Selector because Selector is number, and not one of the following: ' + - 'a CSS selector string, a Selector object, a node snapshot, a function, or a Promise returned by a Selector.', - - callsite: null, - originError: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.hover, - selector: 'element', - options: true, - }); - }, - { - isTestCafeError: true, - code: 'E14', - actualType: 'boolean', - callsite: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.hover, - selector: 'element', - options: { - offsetX: 'offsetX', - }, - }); - }, - { - isTestCafeError: true, - code: 'E9', - optionName: 'MouseOptions.offsetX', - actualValue: 'string', - callsite: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.hover, - selector: 'element', - options: { - offsetY: 1.01, - }, - }); - }, - { - isTestCafeError: true, - code: 'E9', - optionName: 'MouseOptions.offsetY', - actualValue: 1.01, - callsite: null, - } - ); - }); - - it('Should validate DragСommand', function () { - assertThrow( - function () { - return createCommand({ - type: TYPE.drag, - }); - }, - { - isTestCafeError: true, - code: 'E23', - selectorName: 'selector', - errMsg: 'Cannot initialize a Selector because Selector is undefined, and not one of the following: ' + - 'a CSS selector string, a Selector object, a node snapshot, a function, or a Promise returned by a Selector.', - - callsite: null, - originError: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.drag, - selector: 1, - }); - }, - { - isTestCafeError: true, - code: 'E23', - selectorName: 'selector', - errMsg: 'Cannot initialize a Selector because Selector is number, and not one of the following: ' + - 'a CSS selector string, a Selector object, a node snapshot, a function, or a Promise returned by a Selector.', - - callsite: null, - originError: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.drag, - selector: 'element', - }); - }, - { - isTestCafeError: true, - code: 'E20', - argumentName: 'dragOffsetX', - actualValue: 'undefined', - callsite: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.drag, - selector: 'element', - dragOffsetX: 10, - }); - }, - { - isTestCafeError: true, - code: 'E20', - argumentName: 'dragOffsetY', - actualValue: 'undefined', - callsite: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.drag, - selector: 'element', - dragOffsetX: 10, - dragOffsetY: 10.5, - }); - }, - { - isTestCafeError: true, - code: 'E20', - argumentName: 'dragOffsetY', - actualValue: 10.5, - callsite: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.drag, - selector: 'element', - dragOffsetX: 1, - dragOffsetY: -1, - options: 1, - }); - }, - { - isTestCafeError: true, - code: 'E14', - actualType: 'number', - callsite: null, - } - ); - }); - - it('Should validate DragToElementСommand', function () { - assertThrow( - function () { - return createCommand({ - type: TYPE.dragToElement, - }); - }, - { - isTestCafeError: true, - code: 'E23', - selectorName: 'selector', - errMsg: 'Cannot initialize a Selector because Selector is undefined, and not one of the following: ' + - 'a CSS selector string, a Selector object, a node snapshot, a function, or a Promise returned by a Selector.', - - callsite: null, - originError: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.dragToElement, - selector: 1, - }); - }, - { - isTestCafeError: true, - code: 'E23', - selectorName: 'selector', - errMsg: 'Cannot initialize a Selector because Selector is number, and not one of the following: ' + - 'a CSS selector string, a Selector object, a node snapshot, a function, or a Promise returned by a Selector.', - - callsite: null, - originError: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.dragToElement, - selector: 'element', - }); - }, - { - isTestCafeError: true, - code: 'E23', - selectorName: 'destinationSelector', - errMsg: 'Cannot initialize a Selector because Selector is undefined, and not one of the following: ' + - 'a CSS selector string, a Selector object, a node snapshot, a function, or a Promise returned by a Selector.', - - callsite: null, - originError: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.dragToElement, - selector: 'element', - destinationSelector: 1, - }); - }, - { - isTestCafeError: true, - code: 'E23', - selectorName: 'destinationSelector', - errMsg: 'Cannot initialize a Selector because Selector is number, and not one of the following: ' + - 'a CSS selector string, a Selector object, a node snapshot, a function, or a Promise returned by a Selector.', - - callsite: null, - originError: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.dragToElement, - selector: 'element', - destinationSelector: 'destination', - options: 1, - }); - }, - { - isTestCafeError: true, - code: 'E14', - actualType: 'number', - callsite: null, - } - ); - }); - - it('Should validate TypeTextСommand', function () { - assertThrow( - function () { - return createCommand({ - type: TYPE.typeText, - }); - }, - { - isTestCafeError: true, - code: 'E23', - selectorName: 'selector', - errMsg: 'Cannot initialize a Selector because Selector is undefined, and not one of the following: ' + - 'a CSS selector string, a Selector object, a node snapshot, a function, or a Promise returned by a Selector.', - - callsite: null, - originError: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.typeText, - selector: 1, - }); - }, - { - isTestCafeError: true, - code: 'E23', - selectorName: 'selector', - errMsg: 'Cannot initialize a Selector because Selector is number, and not one of the following: ' + - 'a CSS selector string, a Selector object, a node snapshot, a function, or a Promise returned by a Selector.', - - callsite: null, - originError: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.typeText, - selector: 'element', - }); - }, - { - isTestCafeError: true, - code: 'E16', - argumentName: 'text', - actualValue: 'undefined', - callsite: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.typeText, - selector: 'element', - text: 2, - }); - }, - { - isTestCafeError: true, - code: 'E16', - argumentName: 'text', - actualValue: 'number', - callsite: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.typeText, - selector: 'element', - text: '', - }); - }, - { - isTestCafeError: true, - code: 'E16', - argumentName: 'text', - actualValue: '""', - callsite: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.typeText, - selector: 'element', - text: 'testText', - options: true, - }); - }, - { - isTestCafeError: true, - code: 'E14', - actualType: 'boolean', - callsite: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.typeText, - selector: 'element', - text: 'testText', - options: { - offsetX: 'offsetX', - }, - }); - }, - { - isTestCafeError: true, - code: 'E9', - optionName: 'TypeOptions.offsetX', - actualValue: 'string', - callsite: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.typeText, - selector: 'element', - text: 'testText', - options: { - replace: 10, - }, - }); - }, - { - isTestCafeError: true, - code: 'E11', - optionName: 'TypeOptions.replace', - actualValue: 'number', - callsite: null, - } - ); - }); - - it('Should validate SelectTextСommand', function () { - assertThrow( - function () { - return createCommand({ - type: TYPE.selectText, - }); - }, - { - isTestCafeError: true, - code: 'E23', - selectorName: 'selector', - errMsg: 'Cannot initialize a Selector because Selector is undefined, and not one of the following: ' + - 'a CSS selector string, a Selector object, a node snapshot, a function, or a Promise returned by a Selector.', - - callsite: null, - originError: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.selectText, - selector: {}, - }); - }, - { - isTestCafeError: true, - code: 'E23', - selectorName: 'selector', - errMsg: 'Cannot initialize a Selector because Selector is object, and not one of the following: ' + - 'a CSS selector string, a Selector object, a node snapshot, a function, or a Promise returned by a Selector.', - - callsite: null, - originError: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.selectText, - selector: 'element', - startPos: '', - }); - }, - { - isTestCafeError: true, - code: 'E22', - argumentName: 'startPos', - actualValue: 'string', - callsite: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.selectText, - selector: 'element', - startPos: 5.5, - }); - }, - { - isTestCafeError: true, - code: 'E22', - argumentName: 'startPos', - actualValue: 5.5, - callsite: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.selectText, - selector: 'element', - endPos: NaN, - }); - }, - { - isTestCafeError: true, - code: 'E22', - argumentName: 'endPos', - actualValue: NaN, - callsite: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.selectText, - selector: 'element', - endPos: -1, - }); - }, - { - isTestCafeError: true, - code: 'E22', - argumentName: 'endPos', - actualValue: -1, - callsite: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.selectText, - selector: 'element', - options: 1, - }); - }, - { - isTestCafeError: true, - code: 'E14', - actualType: 'number', - callsite: null, - } - ); - }); - - it('Should validate SelectTextAreaContentСommand', function () { - assertThrow( - function () { - return createCommand({ - type: TYPE.selectTextAreaContent, - }); - }, - { - isTestCafeError: true, - code: 'E23', - selectorName: 'selector', - errMsg: 'Cannot initialize a Selector because Selector is undefined, and not one of the following: ' + - 'a CSS selector string, a Selector object, a node snapshot, a function, or a Promise returned by a Selector.', - - callsite: null, - originError: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.selectTextAreaContent, - selector: {}, - }); - }, - { - isTestCafeError: true, - code: 'E23', - selectorName: 'selector', - errMsg: 'Cannot initialize a Selector because Selector is object, and not one of the following: ' + - 'a CSS selector string, a Selector object, a node snapshot, a function, or a Promise returned by a Selector.', - - callsite: null, - originError: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.selectTextAreaContent, - selector: 'element', - startLine: '', - }); - }, - { - isTestCafeError: true, - code: 'E22', - argumentName: 'startLine', - actualValue: 'string', - callsite: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.selectTextAreaContent, - selector: 'element', - startLine: 5.5, - }); - }, - { - isTestCafeError: true, - code: 'E22', - argumentName: 'startLine', - actualValue: 5.5, - callsite: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.selectTextAreaContent, - selector: 'element', - endLine: NaN, - }); - }, - { - isTestCafeError: true, - code: 'E22', - argumentName: 'endLine', - actualValue: NaN, - callsite: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.selectTextAreaContent, - selector: 'element', - endLine: -1, - }); - }, - { - isTestCafeError: true, - code: 'E22', - argumentName: 'endLine', - actualValue: -1, - callsite: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.selectTextAreaContent, - selector: 'element', - options: 1, - }); - }, - { - isTestCafeError: true, - code: 'E14', - actualType: 'number', - callsite: null, - } - ); - }); - - it('Should validate SelectEditableContentСommand', function () { - assertThrow( - function () { - return createCommand({ - type: TYPE.selectEditableContent, - }); - }, - { - isTestCafeError: true, - code: 'E23', - selectorName: 'startSelector', - errMsg: 'Cannot initialize a Selector because Selector is undefined, and not one of the following: ' + - 'a CSS selector string, a Selector object, a node snapshot, a function, or a Promise returned by a Selector.', - - callsite: null, - originError: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.selectEditableContent, - startSelector: 1, - }); - }, - { - isTestCafeError: true, - code: 'E23', - selectorName: 'startSelector', - errMsg: 'Cannot initialize a Selector because Selector is number, and not one of the following: ' + - 'a CSS selector string, a Selector object, a node snapshot, a function, or a Promise returned by a Selector.', - - callsite: null, - originError: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.selectEditableContent, - startSelector: 'node1', - endSelector: true, - }); - }, - { - isTestCafeError: true, - code: 'E23', - selectorName: 'endSelector', - errMsg: 'Cannot initialize a Selector because Selector is boolean, and not one of the following: ' + - 'a CSS selector string, a Selector object, a node snapshot, a function, or a Promise returned by a Selector.', - - callsite: null, - originError: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.selectEditableContent, - startSelector: 'node1', - endSelector: 'node2', - options: 1, - }); - }, - { - isTestCafeError: true, - code: 'E14', - actualType: 'number', - callsite: null, - } - ); - }); - - it('Should validate PressKeyСommand', function () { - assertThrow( - function () { - return createCommand({ - type: TYPE.pressKey, - }); - }, - { - isTestCafeError: true, - code: 'E16', - argumentName: 'keys', - actualValue: 'undefined', - callsite: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.pressKey, - keys: true, - }); - }, - { - isTestCafeError: true, - code: 'E16', - argumentName: 'keys', - actualValue: 'boolean', - callsite: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.pressKey, - keys: '', - }); - }, - { - isTestCafeError: true, - code: 'E16', - argumentName: 'keys', - actualValue: '""', - callsite: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.pressKey, - keys: 'a', - options: 1, - }); - }, - { - isTestCafeError: true, - code: 'E14', - actualType: 'number', - callsite: null, - } - ); - }); - - it('Should validate WaitСommand', function () { - assertThrow( - function () { - return createCommand({ - type: TYPE.wait, - }); - }, - { - isTestCafeError: true, - code: 'E22', - argumentName: 'timeout', - actualValue: 'undefined', - callsite: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.wait, - timeout: -5, - }); - }, - { - isTestCafeError: true, - code: 'E22', - argumentName: 'timeout', - actualValue: -5, - callsite: null, - } - ); - }); - - it('Should validate NavigateToCommand', function () { - assertThrow( - function () { - return createCommand({ - type: TYPE.navigateTo, - }); - }, - { - isTestCafeError: true, - code: 'E16', - argumentName: 'url', - actualValue: 'undefined', - callsite: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.navigateTo, - url: true, - }); - }, - { - isTestCafeError: true, - code: 'E16', - argumentName: 'url', - actualValue: 'boolean', - callsite: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.navigateTo, - url: '', - }); - }, - { - isTestCafeError: true, - code: 'E16', - argumentName: 'url', - actualValue: '""', - callsite: null, - } - ); - - assertErrorMessage( - function () { - return createCommand({ - type: TYPE.navigateTo, - url: 'mail://testcafe@devexpress.com', - }); - }, - 'Cannot prepare tests due to the following error:\n\nInvalid test page URL: "mail://testcafe@devexpress.com". TestCafe cannot execute the test because the test page URL includes the mail protocol. TestCafe supports the following protocols: http://, https:// and file://.' - ); - }); - - it('Should validate SetFilesToUploadCommand', function () { - assertThrow( - function () { - return createCommand({ - type: TYPE.setFilesToUpload, - }); - }, - { - isTestCafeError: true, - code: 'E23', - selectorName: 'selector', - errMsg: 'Cannot initialize a Selector because Selector is undefined, and not one of the following: ' + - 'a CSS selector string, a Selector object, a node snapshot, a function, or a Promise returned by a Selector.', - - callsite: null, - originError: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.setFilesToUpload, - selector: 1, - }); - }, - { - isTestCafeError: true, - code: 'E23', - selectorName: 'selector', - errMsg: 'Cannot initialize a Selector because Selector is number, and not one of the following: ' + - 'a CSS selector string, a Selector object, a node snapshot, a function, or a Promise returned by a Selector.', - - callsite: null, - originError: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.setFilesToUpload, - selector: 'element', - }); - }, - { - isTestCafeError: true, - code: 'E18', - argumentName: 'filePath', - actualValue: 'undefined', - callsite: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.setFilesToUpload, - selector: 'element', - filePath: 2, - }); - }, - { - isTestCafeError: true, - code: 'E18', - argumentName: 'filePath', - actualValue: 'number', - callsite: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.setFilesToUpload, - selector: 'element', - filePath: '', - }); - }, - { - isTestCafeError: true, - code: 'E18', - argumentName: 'filePath', - actualValue: '""', - callsite: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.setFilesToUpload, - selector: 'element', - filePath: {}, - }); - }, - { - isTestCafeError: true, - code: 'E18', - argumentName: 'filePath', - actualValue: 'object', - callsite: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.setFilesToUpload, - selector: 'element', - filePath: [], - }); - }, - { - isTestCafeError: true, - code: 'E18', - argumentName: 'filePath', - actualValue: '[]', - callsite: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.setFilesToUpload, - selector: 'element', - filePath: ['123', 42], - }); - }, - { - isTestCafeError: true, - code: 'E19', - argumentName: 'filePath', - actualValue: 'number', - elementIndex: 1, - callsite: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.setFilesToUpload, - selector: 'element', - filePath: ['123', ''], - }); - }, - { - isTestCafeError: true, - code: 'E19', - argumentName: 'filePath', - actualValue: '""', - elementIndex: 1, - callsite: null, - } - ); - }); - - it('Should validate ClearUploadCommand', function () { - assertThrow( - function () { - return createCommand({ - type: TYPE.clearUpload, - }); - }, - { - isTestCafeError: true, - code: 'E23', - selectorName: 'selector', - errMsg: 'Cannot initialize a Selector because Selector is undefined, and not one of the following: ' + - 'a CSS selector string, a Selector object, a node snapshot, a function, or a Promise returned by a Selector.', - - callsite: null, - originError: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.clearUpload, - selector: 1, - }); - }, - { - isTestCafeError: true, - code: 'E23', - selectorName: 'selector', - errMsg: 'Cannot initialize a Selector because Selector is number, and not one of the following: ' + - 'a CSS selector string, a Selector object, a node snapshot, a function, or a Promise returned by a Selector.', - - callsite: null, - originError: null, - } - ); - }); - - it('Should validate TakeScreenshot', function () { - assertThrow( - function () { - return createCommand({ - type: TYPE.takeScreenshot, - path: 1, - }); - }, - { - isTestCafeError: true, - code: 'E16', - actualValue: 'number', - argumentName: 'path', - callsite: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.takeScreenshot, - path: '', - }); - }, - { - isTestCafeError: true, - code: 'E16', - actualValue: '""', - argumentName: 'path', - callsite: null, - } - ); - }); - - it('Should validate ResizeWindowСommand', function () { - assertThrow( - function () { - return createCommand({ - type: TYPE.resizeWindow, - }); - }, - { - isTestCafeError: true, - code: 'E22', - argumentName: 'width', - actualValue: 'undefined', - callsite: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.resizeWindow, - width: 5, - height: -5, - }); - }, - { - isTestCafeError: true, - code: 'E22', - argumentName: 'height', - actualValue: -5, - callsite: null, - } - ); - }); - - it('Should validate ResizeWindowToFitDeviceСommand', function () { - assertThrow( - function () { - return createCommand({ - type: TYPE.resizeWindowToFitDevice, - }); - }, - { - isTestCafeError: true, - code: 'E16', - argumentName: 'device', - actualValue: 'undefined', - callsite: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.resizeWindowToFitDevice, - device: 5, - }); - }, - { - isTestCafeError: true, - code: 'E16', - argumentName: 'device', - actualValue: 'number', - callsite: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.resizeWindowToFitDevice, - device: '', - }); - }, - { - isTestCafeError: true, - code: 'E16', - argumentName: 'device', - actualValue: '""', - callsite: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.resizeWindowToFitDevice, - device: 'iPhone 555', - }); - }, - { - isTestCafeError: true, - code: 'E38', - argumentName: 'device', - actualValue: 'iPhone 555', - callsite: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.resizeWindowToFitDevice, - device: 'iPhone', - options: { portraitOrientation: {} }, - }); - }, - { - isTestCafeError: true, - code: 'E11', - optionName: 'ResizeToFitDeviceOptions.portraitOrientation', - actualValue: 'object', - callsite: null, - } - ); - }); - - it('Should validate SetTestSpeedCommand', function () { - assertThrow( - function () { - return createCommand({ - type: TYPE.setTestSpeed, - }); - }, - { - isTestCafeError: true, - code: 'E47', - argumentName: 'speed', - actualValue: 'undefined', - callsite: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.setTestSpeed, - speed: 2, - }); - }, - { - isTestCafeError: true, - code: 'E47', - argumentName: 'speed', - actualValue: 2, - callsite: null, - } - ); - }); - - it('Should validate SetPageLoadTimeoutCommand', function () { - assertThrow( - function () { - return createCommand({ - type: TYPE.setPageLoadTimeout, - }); - }, - { - isTestCafeError: true, - code: 'E22', - argumentName: 'duration', - actualValue: 'undefined', - callsite: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.setPageLoadTimeout, - duration: -1, - }); - }, - { - isTestCafeError: true, - code: 'E22', - argumentName: 'duration', - actualValue: -1, - callsite: null, - } - ); - }); - - it('Should validate AssertionСommand', function () { - assertThrow( - function () { - return createCommand({ - type: TYPE.assertion, - }); - }, - { - isTestCafeError: true, - code: 'E16', - argumentName: 'assertionType', - actualValue: 'undefined', - callsite: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.assertion, - assertionType: 123, - }); - }, - { - isTestCafeError: true, - code: 'E16', - argumentName: 'assertionType', - actualValue: 'number', - callsite: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.assertion, - assertionType: 'ok', - options: 1, - }); - }, - { - isTestCafeError: true, - code: 'E14', - actualType: 'number', - callsite: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.assertion, - assertionType: 'ok', - options: { - timeout: 'timeout', - }, - }); - }, - { - isTestCafeError: true, - code: 'E10', - optionName: 'AssertionOptions.timeout', - actualValue: 'string', - callsite: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.assertion, - assertionType: 'ok', - options: { - timeout: 10.5, - }, - }); - }, - { - isTestCafeError: true, - code: 'E10', - optionName: 'AssertionOptions.timeout', - actualValue: 10.5, - callsite: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.assertion, - assertionType: 'ok', - - actual: { - type: 'js-expr', - value: 'invalid js code', - }, - }); - }, - { - isTestCafeError: true, - argumentName: 'actual', - actualValue: 'invalid js code', - errMsg: semver.gte(process.version, '19.0.0') ? "Unexpected identifier 'js'" : 'Unexpected identifier', - code: 'E59', - callsite: null, - originError: null, - } - ); - }); - - it('Should validate ExecuteExpressionСommand', function () { - assertThrow( - function () { - return createCommand({ - type: TYPE.executeExpression, - }); - }, - { - isTestCafeError: true, - code: 'E16', - argumentName: 'expression', - actualValue: 'undefined', - callsite: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.executeExpression, - expression: 123, - }); - }, - { - isTestCafeError: true, - code: 'E16', - argumentName: 'expression', - actualValue: 'number', - callsite: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.executeExpression, - expression: 'js-expression', - resultVariableName: 123, - }); - }, - { - isTestCafeError: true, - code: 'E16', - argumentName: 'resultVariableName', - actualValue: 'number', - callsite: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.executeExpression, - expression: 'js-expression', - resultVariableName: '', - }); - }, - { - isTestCafeError: true, - code: 'E16', - argumentName: 'resultVariableName', - actualValue: '""', - callsite: null, - } - ); - }); - - it('Should validate ExecuteAsyncExpressionCommand', function () { - assertThrow( - function () { - return createCommand({ - type: TYPE.executeAsyncExpression, - }); - }, - { - isTestCafeError: true, - code: 'E16', - argumentName: 'expression', - actualValue: 'undefined', - callsite: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.executeAsyncExpression, - expression: 123, - }); - }, - { - isTestCafeError: true, - code: 'E16', - argumentName: 'expression', - actualValue: 'number', - callsite: null, - } - ); - }); - - it('Should validate js expression as Selector', function () { - assertThrow( - function () { - return createCommand({ - type: TYPE.click, - selector: { - type: 'js-expr', - value: 'Selector()', - }, - }); - }, - { - isTestCafeError: true, - code: 'E23', - selectorName: 'selector', - errMsg: 'Cannot initialize a Selector because Selector is undefined, and not one of the following: ' + - 'a CSS selector string, a Selector object, a node snapshot, a function, or a Promise returned by a Selector.', - - callsite: null, - originError: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.click, - selector: { - type: 'js-expr', - value: 'yo', - }, - }); - }, - { - isTestCafeError: true, - code: 'E23', - selectorName: 'selector', - errMsg: 'yo is not defined', - - callsite: null, - originError: null, - } - ); - }); - - it('Should validate RecorderCommand', function () { - assertThrow( - function () { - return createCommand({ - type: TYPE.recorder, - }); - }, - { - isTestCafeError: true, - code: 'E16', - argumentName: 'subtype', - actualValue: 'undefined', - callsite: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.recorder, - subtype: '', - }); - }, - { - isTestCafeError: true, - code: 'E16', - argumentName: 'subtype', - actualValue: '""', - callsite: null, - } - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.recorder, - subtype: 2, - }); - }, - { - isTestCafeError: true, - code: 'E16', - argumentName: 'subtype', - actualValue: 'number', - callsite: null, - } - ); - }); - - it('Should validate GetCookiesCommand', function () { - assertThrow( - function () { - return createCommand({ - type: TYPE.getCookies, - cookies: [ - void 0, - ], - }); - }, - { - isTestCafeError: true, - code: 'E86', - callsite: null, - }, - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.getCookies, - cookies: [ - { - name: 'name', - }, - void 0, - ], - }); - }, - { - actualValue: void 0, - index: 1, - isTestCafeError: true, - code: 'E87', - callsite: null, - }, - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.getCookies, - urls: ['url.url'], - }); - }, - { - isTestCafeError: true, - code: 'E88', - callsite: null, - }, - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.getCookies, - urls: [ - 'http://localhost/', - 'url.url', - ], - }); - }, - { - actualValue: 'url.url', - index: 1, - isTestCafeError: true, - code: 'E89', - callsite: null, - }, - ); - }); - - it('Should validate SetCookiesCommand', function () { - assertThrow( - function () { - return createCommand({ - type: TYPE.setCookies, - cookies: [], - }); - }, - { - isTestCafeError: true, - code: 'E85', - callsite: null, - }, - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.setCookies, - cookies: [ - void 0, - ], - }); - }, - { - isTestCafeError: true, - code: 'E86', - callsite: null, - }, - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.setCookies, - cookies: [ - { - name: 'name', - }, - void 0, - ], - }); - }, - { - actualValue: void 0, - index: 1, - isTestCafeError: true, - code: 'E87', - callsite: null, - }, - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.setCookies, - url: ['url.url'], - }); - }, - { - isTestCafeError: true, - code: 'E88', - callsite: null, - }, - ); - }); - - it('Should validate DeleteCookiesCommand', function () { - assertThrow( - function () { - return createCommand({ - type: TYPE.deleteCookies, - cookies: [ - void 0, - ], - }); - }, - { - isTestCafeError: true, - code: 'E86', - callsite: null, - }, - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.deleteCookies, - cookies: [ - { - name: 'name', - }, - void 0, - ], - }); - }, - { - index: 1, - actualValue: void 0, - isTestCafeError: true, - code: 'E87', - callsite: null, - }, - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.deleteCookies, - urls: ['url.url'], - }); - }, - { - isTestCafeError: true, - code: 'E88', - callsite: null, - }, - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.deleteCookies, - urls: [ - 'http://localhost/', - 'url.url', - ], - }); - }, - { - index: 1, - actualValue: 'url.url', - isTestCafeError: true, - code: 'E89', - callsite: null, - }, - ); - }); - - it('Should validate RequestCommand', function () { - assertThrow( - function () { - return createCommand({ - type: TYPE.request, - url: true, - }); - }, - { - actualValue: 'boolean', - argumentName: 'url', - isTestCafeError: true, - code: 'E96', - callsite: null, - }, - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.request, - options: { - method: true, - }, - }); - }, - { - optionName: 'RequestOptions.method', - actualValue: 'boolean', - isTestCafeError: true, - code: 'E90', - callsite: null, - }, - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.request, - options: { - headers: true, - }, - }); - }, - { - optionName: 'RequestOptions.headers', - actualValue: 'boolean', - isTestCafeError: true, - code: 'E95', - callsite: null, - }, - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.request, - options: { - params: true, - }, - }); - }, - { - optionName: 'RequestOptions.params', - actualValue: 'boolean', - isTestCafeError: true, - code: 'E94', - callsite: null, - }, - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.request, - options: { - timeout: 'true', - }, - }); - }, - { - optionName: 'RequestOptions.timeout', - actualValue: 'string', - isTestCafeError: true, - code: 'E92', - callsite: null, - }, - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.request, - options: { - withCredentials: 'true', - }, - }); - }, - { - optionName: 'RequestOptions.withCredentials', - actualValue: 'string', - isTestCafeError: true, - code: 'E11', - callsite: null, - }, - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.request, - options: { - auth: true, - }, - }); - }, - { - optionName: 'RequestOptions.auth', - actualValue: 'boolean', - isTestCafeError: true, - code: 'E95', - callsite: null, - }, - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.request, - options: { - auth: { - username: true, - password: 'password', - }, - }, - }); - }, - { - optionName: 'RequestAuthOptions.username', - actualValue: 'boolean', - isTestCafeError: true, - code: 'E90', - callsite: null, - }, - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.request, - options: { - auth: { - username: 'username', - password: true, - }, - }, - }); - }, - { - optionName: 'RequestAuthOptions.password', - actualValue: 'boolean', - isTestCafeError: true, - code: 'E90', - callsite: null, - }, - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.request, - options: { - proxy: true, - }, - }); - }, - { - optionName: 'RequestOptions.proxy', - actualValue: 'boolean', - isTestCafeError: true, - code: 'E95', - callsite: null, - }, - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.request, - options: { - proxy: { - protocol: true, - }, - }, - }); - }, - { - optionName: 'RequestProxyOptions.protocol', - actualValue: 'boolean', - isTestCafeError: true, - code: 'E90', - callsite: null, - }, - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.request, - options: { - proxy: { - host: true, - port: 3000, - }, - }, - }); - }, - { - optionName: 'RequestProxyOptions.host', - actualValue: 'boolean', - isTestCafeError: true, - code: 'E90', - callsite: null, - }, - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.request, - options: { - proxy: { - host: 'localhost', - port: {}, - }, - }, - }); - }, - { - optionName: 'RequestProxyOptions.port', - actualValue: 'object', - isTestCafeError: true, - code: 'E92', - callsite: null, - }, - ); - - assertThrow( - function () { - return createCommand({ - type: TYPE.request, - options: { - rawResponse: 'true', - }, - }); - }, - { - optionName: 'RequestOptions.rawResponse', - actualValue: 'string', - isTestCafeError: true, - code: 'E11', - callsite: null, - }, - ); - }); - }); -}); diff --git a/test/server/test-run-controller-test.js b/test/server/test-run-controller-test.js deleted file mode 100644 index 6750b4d468f..00000000000 --- a/test/server/test-run-controller-test.js +++ /dev/null @@ -1,38 +0,0 @@ -const { expect } = require('chai'); -const { noop } = require('lodash'); -const TestRunController = require('../../lib/runner/test-run-controller'); - -describe('TestRunController', () => { - it('Should raise an error on start in nativeAutomation mode with browser without its support', async () => { - const testMock = { - isNativeAutomation: true, - }; - - const browserConnectionMock = { - supportNativeAutomation: () => false, - - browserInfo: { - providerName: 'testBrowser', - }, - }; - - const messageBusMock = { - emit: noop, - }; - - const testRunController = new TestRunController({ - test: testMock, - messageBus: messageBusMock, - opts: { - nativeAutomation: true, - }, - }); - - try { - await testRunController.start(browserConnectionMock); - } - catch (err) { - expect(err.message).to.equal('The "testBrowser" do not support the Native Automation mode. Use the "disable native automation" option to continue.'); - } - }); -}); diff --git a/test/server/test-run-driver-task-queue-test.js b/test/server/test-run-driver-task-queue-test.js deleted file mode 100644 index 0a54a88479c..00000000000 --- a/test/server/test-run-driver-task-queue-test.js +++ /dev/null @@ -1,145 +0,0 @@ -const CLIENT_MESSAGES = require('../../lib/test-run/client-messages'); -const RequestHook = require('../../lib/api/request-hooks/hook'); -const { expect } = require('chai'); - -const { - PressKeyCommand, - ExecuteAsyncExpressionCommand, - ExecuteExpressionCommand, - AddRequestHooksCommand, - RemoveRequestHooksCommand, - RecorderCommand, -} = require('../../lib/test-run/commands/actions'); - -const { WaitCommand } = require('../../lib/test-run/commands/observation'); -const BaseTestRunMock = require('./helpers/base-test-run-mock'); - - -class TestRunMock extends BaseTestRunMock { - _executeJsExpression () { - return 'expression result'; - } - - _executeAsyncJsExpression () { - return 'async expression result'; - } -} - -class EmptyRequestHook extends RequestHook { - onRequest () {} - - onResponse () {} -} - -const testRunMock = new TestRunMock(); - -function createDriverStatusMsg (id = 'id') { - return { - cmd: 'ready', - status: { - id, - pageError: null, - consoleMessages: [], - isCommandResult: true, - }, - }; -} - -function imitateCommandResolvingFromClient () { - setTimeout(() => { - testRunMock[CLIENT_MESSAGES.ready](createDriverStatusMsg('1')) - .then(() => { - return testRunMock[CLIENT_MESSAGES.ready](createDriverStatusMsg('2')); - }); - }, 0); -} - -describe('Driver task queue', () => { - it('Should return real queue length after all client commands are added', async () => { - const commandExecutionPromises = [ - testRunMock._internalExecuteCommand(new PressKeyCommand({ keys: 'a' })), - testRunMock._internalExecuteCommand(new PressKeyCommand({ keys: 'b' })), - ]; - - const driverTaskQueueLength = testRunMock.driverTaskQueue.length; - const realDriverTaskQueueLength = await testRunMock.driverTaskQueueLength; - - imitateCommandResolvingFromClient(); - - await Promise.all(commandExecutionPromises); - - expect(driverTaskQueueLength).eql(0); - expect(realDriverTaskQueueLength).eql(2); - }); - - it('Should return real queue length after all server commands are added', async () => { - const commandExecutionPromises = [ - testRunMock.executeCommand(new WaitCommand({ timeout: 0 })), - testRunMock.executeCommand(new WaitCommand({ timeout: 0 })), - ]; - - const driverTaskQueueLength = testRunMock.driverTaskQueue.length; - const realDriverTaskQueueLength = await testRunMock.driverTaskQueueLength; - - imitateCommandResolvingFromClient(); - - await Promise.all(commandExecutionPromises); - - expect(driverTaskQueueLength).eql(0); - expect(realDriverTaskQueueLength).eql(0); - }); - - it('Should return real queue length after execute-expression commands are added', async () => { - const commandExecutionPromises = [ - testRunMock.executeCommand(new ExecuteExpressionCommand({ - resultVariableName: 'el1', - expression: 'Selector(\'div\')', - })), - testRunMock.executeCommand(new ExecuteExpressionCommand({ - resultVariableName: 'el2', - expression: 'Selector(\'div\')', - })), - testRunMock.executeCommand(new ExecuteAsyncExpressionCommand({ - expression: 'return Selector(\'div\')', - })), - testRunMock.executeCommand(new ExecuteAsyncExpressionCommand({ - expression: ` - await t.click('#input1'); - await t.click('#input2'); - await t.click('#input3'); - `, - })), - ]; - - const driverTaskQueueLength = testRunMock.driverTaskQueue.length; - const realDriverTaskQueueLength = await testRunMock.driverTaskQueueLength; - - imitateCommandResolvingFromClient(); - - await Promise.all(commandExecutionPromises); - - expect(driverTaskQueueLength).eql(0); - expect(realDriverTaskQueueLength).eql(0); - }); - - it('Should return real queue length after hooks commands are added', async () => { - const hook = new EmptyRequestHook(); - - const commandExecutionPromises = [ - testRunMock.executeCommand(new AddRequestHooksCommand({ hooks: [ hook ] })), - testRunMock.executeCommand(new RemoveRequestHooksCommand({ hooks: [ hook ] })), - testRunMock.executeCommand(new RecorderCommand({ subtype: 'record' })), - testRunMock.executeCommand(new RecorderCommand({ subtype: 'record' })), - ]; - - imitateCommandResolvingFromClient(); - - await Promise.all(commandExecutionPromises); - - const driverTaskQueueLength = testRunMock.driverTaskQueue.length; - const realDriverTaskQueueLength = await testRunMock.driverTaskQueueLength; - - expect(driverTaskQueueLength).eql(0); - expect(realDriverTaskQueueLength).eql(0); - }); -}); diff --git a/test/server/test-run-error-formatting-test.js b/test/server/test-run-error-formatting-test.js deleted file mode 100644 index 0369ac11dc7..00000000000 --- a/test/server/test-run-error-formatting-test.js +++ /dev/null @@ -1,872 +0,0 @@ -const { assert, expect } = require('chai'); -const { pull: remove, chain, values } = require('lodash'); -const TestRun = require('../../lib/test-run'); -const TEST_RUN_PHASE = require('../../lib/test-run/phase'); -const { TEST_RUN_ERRORS, RUNTIME_ERRORS } = require('../../lib/errors/types'); -const TestRunErrorFormattableAdapter = require('../../lib/errors/test-run/formattable-adapter'); -const testCallsite = require('./data/test-callsite'); -const assertTestRunError = require('./helpers/assert-test-run-error'); - -const { - AssertionExecutableArgumentError, - AssertionWithoutMethodCallError, - AssertionUnawaitedPromiseError, - ActionIntegerOptionError, - ActionPositiveIntegerOptionError, - ActionIntegerArgumentError, - ActionPositiveIntegerArgumentError, - ActionBooleanOptionError, - ActionBooleanArgumentError, - ActionSpeedOptionError, - ActionSelectorError, - ActionOptionsTypeError, - ActionStringArgumentError, - ActionNullableStringArgumentError, - ActionStringOrStringArrayArgumentError, - ActionStringArrayElementError, - ActionFunctionArgumentError, - PageLoadError, - UncaughtErrorOnPage, - UncaughtErrorInTestCode, - UncaughtErrorInClientFunctionCode, - UncaughtNonErrorObjectInTestCode, - UncaughtErrorInCustomDOMPropertyCode, - UnhandledPromiseRejectionError, - UncaughtExceptionError, - ActionElementNotFoundError, - ActionElementIsInvisibleError, - ActionElementIsNotTargetError, - ActionSelectorMatchesWrongNodeTypeError, - ActionAdditionalElementNotFoundError, - ActionAdditionalElementIsInvisibleError, - ActionAdditionalSelectorMatchesWrongNodeTypeError, - ActionElementNonEditableError, - ActionElementNonContentEditableError, - ActionRootContainerNotFoundError, - ActionElementNotTextAreaError, - ActionIncorrectKeysError, - ActionCannotFindFileToUploadError, - ActionElementIsNotFileInputError, - ActionUnsupportedDeviceTypeError, - ActionInvalidScrollTargetError, - ClientFunctionExecutionInterruptionError, - ActionElementNotIframeError, - ActionIframeIsNotLoadedError, - CurrentIframeIsNotLoadedError, - CurrentIframeNotFoundError, - CurrentIframeIsInvisibleError, - MissingAwaitError, - ExternalAssertionLibraryError, - DomNodeClientFunctionResultError, - InvalidSelectorResultError, - NativeDialogNotHandledError, - UncaughtErrorInNativeDialogHandler, - SetNativeDialogHandlerCodeWrongTypeError, - CannotObtainInfoForElementSpecifiedBySelectorError, - WindowDimensionsOverflowError, - ForbiddenCharactersInScreenshotPathError, - InvalidElementScreenshotDimensionsError, - SetTestSpeedArgumentError, - RoleSwitchInRoleInitializerError, - ActionRoleArgumentError, - RequestHookNotImplementedMethodError, - RequestHookUnhandledError, - UncaughtErrorInCustomClientScriptCode, - UncaughtErrorInCustomClientScriptLoadedFromModule, - UncaughtErrorInCustomScript, - UncaughtTestCafeErrorInCustomScript, - ChildWindowIsNotLoadedError, - ChildWindowNotFoundError, - CannotSwitchToWindowError, - CloseChildWindowError, - ChildWindowClosedBeforeSwitchingError, - WindowNotFoundError, - ParentWindowNotFoundError, - PreviousWindowNotFoundError, - SwitchToWindowPredicateError, - CannotCloseWindowWithChildrenError, - MultipleWindowsModeIsDisabledError, - CannotCloseWindowWithoutParentError, - MultipleWindowsModeIsNotAvailableInRemoteBrowserError, - MultipleWindowsModeIsNotSupportedInNativeAutomationModeError, - CannotRestoreChildWindowError, - TimeoutError, - ActionCookieArgumentError, - ActionCookieArgumentsError, - ActionUrlCookieArgumentError, - ActionUrlsCookieArgumentError, - ActionRequiredCookieArguments, - ActionStringOptionError, - ActionDateOptionError, - ActionNumberOptionError, - ActionUrlOptionError, - ActionUrlSearchParamsOptionError, - ActionObjectOptionError, - ActionUrlArgumentError, - ActionSkipJsErrorsArgumentTypeError, -} = require('../../lib/errors/test-run'); -const { - ActionStringOrRegexOptionError, - ActionFunctionOptionError, - ActionInvalidObjectPropertyError, -} = require('../../lib/shared/errors'); - -const untestedErrorTypes = Object.keys(TEST_RUN_ERRORS).map(key => TEST_RUN_ERRORS[key]); - -const userAgentMock = 'Chrome 15.0.874.120 / macOS 10.15'; - -function equalAssertArray () { - expect([1, 2, 3, [4, 5], 6]).eql([1, 4, 2, 3, [5, 6, [7]]]); -} - -function equalAssertBoolean () { - expect(true).eql(false); -} - -function equalAssertBuffer () { - expect(Buffer.from('test')).eql(Buffer.from([1, 2, 3])); -} - -function equalAssertEmptyString () { - expect([]).eql(''); -} - -function equalAssertFunction () { - expect(function () { - return true; - }).eql(function () { - return false; - }); -} - -function equalAssertNumber () { - expect(1).eql(2); -} - -function equalAssertObject () { - const obj1 = { - first: { - second: { - third: { - fourth: { - fifth: { - hello: 'world', - six: '6', - }, - }, - }, - }, - }, - }; - - const obj2 = { - first: { - second: { - third: { - fourth: { - fifth: { - hello: 'world', - }, - }, - }, - }, - }, - }; - - expect(obj1).eql(obj2); -} - -function equalAssertString () { - expect('line1\nline2').eql('line1'); -} - -function equalAssertUndefinedNull () { - expect(void 0).eql(null); -} - -function notEqualAssertString () { - assert.notEqual('foo', 'foo'); -} - -function okAssertBoolean () { - expect(false).ok; -} - -function notOkAssertBoolean () { - expect(true).not.ok; -} - -function containsAssertString () { - expect('foo').contains('bar'); -} - -function notContainsAssertString () { - expect('foobar').not.contains('bar'); -} - -function matchAssertRegExp () { - expect('some text').match(/some regexp/); -} - -function notMatchAssertRegExp () { - expect('some text').not.match(/some \w+/); -} - -function typeOfAssertNull () { - assert.typeOf(false, 'null'); -} - -function notTypeOfAssertNull () { - assert.notTypeOf(null, 'null'); -} - -function withinAssertNumber () { - expect(0).within(1, 2); -} - -function notWithinAssertNumber () { - expect(0).not.within(0, 1); -} - -function ltAssertNumber () { - expect(1).lt(0); -} - -function lteAssertNumber () { - expect(1).lte(0); -} - -function gtAssertNumber () { - expect(0).gt(1); -} - -function gteAssertNumber () { - expect(0).gte(1); -} - -const createAssertionError = fn => { - try { - fn(); - } - catch (err) { - return err; - } - - return null; -}; - -const ASSERT_ERRORS = { - equal: { - array: createAssertionError(equalAssertArray), - boolean: createAssertionError(equalAssertBoolean), - buffer: createAssertionError(equalAssertBuffer), - emptyString: createAssertionError(equalAssertEmptyString), - function: createAssertionError(equalAssertFunction), - number: createAssertionError(equalAssertNumber), - object: createAssertionError(equalAssertObject), - string: createAssertionError(equalAssertString), - undefinedNull: createAssertionError(equalAssertUndefinedNull), - }, - notEqual: { string: createAssertionError(notEqualAssertString) }, - ok: { boolean: createAssertionError(okAssertBoolean) }, - notOk: { boolean: createAssertionError(notOkAssertBoolean) }, - contains: { string: createAssertionError(containsAssertString) }, - notContains: { string: createAssertionError(notContainsAssertString) }, - match: { regexp: createAssertionError(matchAssertRegExp) }, - notMatch: { regexp: createAssertionError(notMatchAssertRegExp) }, - typeOf: { null: createAssertionError(typeOfAssertNull) }, - notTypeOf: { null: createAssertionError(notTypeOfAssertNull) }, - within: { number: createAssertionError(withinAssertNumber) }, - notWithin: { number: createAssertionError(notWithinAssertNumber) }, - lt: { number: createAssertionError(ltAssertNumber) }, - lte: { number: createAssertionError(lteAssertNumber) }, - gt: { number: createAssertionError(gtAssertNumber) }, - gte: { number: createAssertionError(gteAssertNumber) }, -}; - -const longSelector = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua'; - -function getErrorAdapter (err) { - const screenshotPath = '/unix/path/with/'; - - return new TestRunErrorFormattableAdapter(err, { - userAgent: userAgentMock, - screenshotPath: screenshotPath, - callsite: testCallsite, - testRunPhase: TEST_RUN_PHASE.initial, - }); -} - -function assertErrorMessage (file, err) { - assertTestRunError(err, '../data/expected-test-run-errors/' + file); - - // NOTE: check that the list of error types contains an - // error of this type and remove tested messages from the list - expect(untestedErrorTypes.includes(err.code)).to.be.ok; - remove(untestedErrorTypes, err.code); -} - -describe('Error formatting', () => { - describe('Errors', () => { - it('Base error formattable adapter properties', () => { - const testRunMock = TestRun.prototype; - - testRunMock._ensureErrorId = err => { - err.id = 'error-id'; - }; - - Object.assign(testRunMock, { - session: { id: 'test-run-id' }, - browserConnection: { userAgent: 'chrome' }, - errScreenshotPath: 'screenshot-path', - phase: 'test-run-phase', - callsite: 'callsite', - errs: [], - }); - - TestRun.prototype.addError.call(testRunMock, { callsite: 'callsite' }); - - const err = testRunMock.errs[0]; - - expect(err).instanceOf(TestRunErrorFormattableAdapter); - - expect(err).eql({ - userAgent: 'chrome', - screenshotPath: 'screenshot-path', - testRunId: 'test-run-id', - testRunPhase: 'test-run-phase', - callsite: 'callsite', - id: 'error-id', - }); - }); - - it('Should not throw if the specified decorator was not found', () => { - expect(() => { - const error = new ExternalAssertionLibraryError(createAssertionError(equalAssertArray), testCallsite); - - error.diff = '
text
'; - - getErrorAdapter(error).formatMessage('', 100); - }).to.not.throw(); - }); - - it('Should format "actionIntegerOptionError" message', () => { - assertErrorMessage('action-integer-option-error', new ActionIntegerOptionError('offsetX', '1.01')); - }); - - it('Should format "actionPositiveIntegerOptionError" message', () => { - assertErrorMessage('action-positive-integer-option-error', new ActionPositiveIntegerOptionError('caretPos', '-1')); - }); - - it('Should format "actionIntegerArgumentError" message', () => { - assertErrorMessage('action-integer-argument-error', new ActionIntegerArgumentError('dragOffsetX', 'NaN')); - }); - - it('Should format "actionPositiveIntegerArgumentError" message', () => { - assertErrorMessage('action-positive-integer-argument-error', new ActionPositiveIntegerArgumentError('startPos', '-1')); - }); - - it('Should format "actionBooleanOptionError" message', () => { - assertErrorMessage('action-boolean-option-error', new ActionBooleanOptionError('modifier.ctrl', 'object')); - }); - - it('Should format the "actionBooleanArgumentError" message', () => { - assertErrorMessage('action-boolean-argument-error', new ActionBooleanArgumentError('isAsyncExpression', 'object')); - }); - - it('Should format "actionSpeedOptionError" message', () => { - assertErrorMessage('action-speed-option-error', new ActionSpeedOptionError('speed', 'object')); - }); - - it('Should format "pageLoadError" message', () => { - assertErrorMessage('page-load-error', new PageLoadError('Failed to find a DNS-record for the resource', 'http://some-url.example.com')); - }); - - it('Should format "uncaughtErrorOnPage" message (with error stack)', () => { - const errStack = [ - 'Test error:', - ' at method3 (http://example.com):1:3', - ' at method2 (http://example.com):1:2', - ' at method1 (http://example.com):1:1', - ].join('\n'); - - assertErrorMessage('uncaught-js-error-on-page', new UncaughtErrorOnPage(errStack, 'http://example.org')); - }); - - it('Should format "uncaughtErrorInTestCode" message', () => { - assertErrorMessage('uncaught-js-error-in-test-code', new UncaughtErrorInTestCode(new Error('Custom script error'), testCallsite)); - }); - - it('Should format "uncaughtNonErrorObjectInTestCode" message', () => { - assertErrorMessage('uncaught-non-error-object-in-test-code', new UncaughtNonErrorObjectInTestCode('Hey ya!')); - }); - - it('Should format "uncaughtErrorInAddCustomDOMProperties" message', () => { - assertErrorMessage('uncaught-error-in-add-custom-dom-properties-code', new UncaughtErrorInCustomDOMPropertyCode(testCallsite, new Error('Custom script error'), 'prop')); - }); - - it('Should format "unhandledPromiseRejectionError" message', () => { - assertErrorMessage('unhandled-promise-rejection-error', new UnhandledPromiseRejectionError('Hey ya!')); - }); - - it('Should format "uncaughtExceptionError" message', () => { - assertErrorMessage('uncaught-exception-error', new UncaughtExceptionError('Hey ya!')); - }); - - it('Should format "actionElementNotFoundError" message', () => { - assertErrorMessage('action-element-not-found-error', new ActionElementNotFoundError(null, { - apiFnChain: [longSelector, 'one', 'two', 'three'], - apiFnIndex: 1, - })); - }); - - it('Should format "actionElementIsInvisibleError" message', () => { - assertErrorMessage('action-element-is-invisible-error', new ActionElementIsInvisibleError()); - }); - - it('Should format "actionElementIsNotTargetError" message', () => { - assertErrorMessage('action-element-is-not-target-error', new ActionElementIsNotTargetError()); - }); - - it('Should format "actionSelectorMatchesWrongNodeTypeError" message', () => { - assertErrorMessage('action-selector-matches-wrong-node-type-error', new ActionSelectorMatchesWrongNodeTypeError('text')); - }); - - it('Should format "actionElementNonEditableError" message', () => { - assertErrorMessage('action-element-non-editable-error', new ActionElementNonEditableError()); - }); - - it('Should format "actionRootContainerNotFoundError" message', () => { - assertErrorMessage('action-root-container-not-found-error', new ActionRootContainerNotFoundError()); - }); - - it('Should format "actionElementNonContentEditableError" message', () => { - assertErrorMessage('action-element-non-content-editable-error', new ActionElementNonContentEditableError('startSelector')); - }); - - it('Should format "actionElementNotTextAreaError" message', () => { - assertErrorMessage('action-element-not-text-area-error', new ActionElementNotTextAreaError()); - }); - - it('Should format "actionElementNotIframeError" message', () => { - assertErrorMessage('action-element-not-iframe-error', new ActionElementNotIframeError()); - }); - - it('Should format "actionSelectorError" message', () => { - assertErrorMessage('action-selector-error', new ActionSelectorError('selector', { rawMessage: 'Yo!' }, true)); - }); - - it('Should format "actionOptionsTypeError" message', () => { - assertErrorMessage('action-options-type-error', new ActionOptionsTypeError(typeof 1)); - }); - - it('Should format "actionAdditionalElementNotFoundError" message', () => { - assertErrorMessage('action-additional-element-not-found-error', new ActionAdditionalElementNotFoundError('startSelector', { - apiFnChain: [longSelector, 'one', 'two', 'three'], - apiFnIndex: 1, - })); - }); - - it('Should format "actionAdditionalElementIsInvisibleError" message', () => { - assertErrorMessage('action-additional-element-is-invisible-error', new ActionAdditionalElementIsInvisibleError('startSelector')); - }); - - it('Should format "actionAdditionalSelectorMatchesWrongNodeTypeError" message', () => { - assertErrorMessage('action-additional-selector-matches-wrong-node-type-error', new ActionAdditionalSelectorMatchesWrongNodeTypeError('startSelector', 'text')); - }); - - it('Should format "actionStringArgumentError" message', () => { - assertErrorMessage('action-string-argument-error', new ActionStringArgumentError('text', typeof 1)); - }); - - it('Should format "actionNullableStringArgumentError" message', () => { - assertErrorMessage('action-nullable-string-argument-error', new ActionNullableStringArgumentError('text', typeof 1)); - }); - - it('Should format "actionIncorrectKeysError" message', () => { - assertErrorMessage('action-incorrect-keys-error', new ActionIncorrectKeysError('keys')); - }); - - it('Should format "actionNonEmptyStringArrayArgumentError" message', () => { - assertErrorMessage('action-non-empty-string-array-argument-error', new ActionStringOrStringArrayArgumentError('array', null)); - }); - - it('Should format "actionStringArrayElementError" message', () => { - assertErrorMessage('action-string-array-element-error', new ActionStringArrayElementError('array', 'number', 1)); - }); - - it('Should format "actionElementIsNotFileInputError" message', () => { - assertErrorMessage('action-element-is-not-file-input-error', new ActionElementIsNotFileInputError()); - }); - - it('Should format "actionCannotFindFileToUploadError" message', () => { - const filePaths = ['/path/1', '/path/2']; - const scannedFilepaths = ['full-path-to/path/1', 'full-path-to/path/2']; - const err = new ActionCannotFindFileToUploadError(filePaths, scannedFilepaths); - - assertErrorMessage('action-cannot-find-file-to-upload-error', err); - }); - - it('Should format "actionUnsupportedDeviceTypeError" message', () => { - assertErrorMessage('action-unsupported-device-type-error', new ActionUnsupportedDeviceTypeError('device', 'iPhone 555')); - }); - - it('Should format "actionInvalidScrollTargetError" message', () => { - assertErrorMessage('action-invalid-scroll-target-error', new ActionInvalidScrollTargetError(false, true)); - }); - - it('Should format "actionIframeIsNotLoadedError" message', () => { - assertErrorMessage('action-iframe-is-not-loaded-error', new ActionIframeIsNotLoadedError()); - }); - - it('Should format "currentIframeIsNotLoadedError" message', () => { - assertErrorMessage('current-iframe-is-not-loaded-error', new CurrentIframeIsNotLoadedError()); - }); - - it('Should format "currentIframeNotFoundError" message', () => { - assertErrorMessage('current-iframe-not-found-error', new CurrentIframeNotFoundError()); - }); - - it('Should format "currentIframeIsInvisibleError" message', () => { - assertErrorMessage('current-iframe-is-invisible-error', new CurrentIframeIsInvisibleError()); - }); - - it('Should format "missingAwaitError"', () => { - assertErrorMessage('missing-await-error', new MissingAwaitError(testCallsite)); - }); - - describe('Should format "externalAssertionLibraryError"', () => { - const filepath = function (assertion, filename) { - return `../data/expected-test-run-errors/external-assertion-library-errors/builtin/${assertion}/${filename}`; - }; - - it('Deep Equal', () => { - assertTestRunError(new ExternalAssertionLibraryError(ASSERT_ERRORS.equal.array, testCallsite), filepath('equal', 'array')); - assertTestRunError(new ExternalAssertionLibraryError(ASSERT_ERRORS.equal.boolean, testCallsite), filepath('equal', 'boolean')); - assertTestRunError(new ExternalAssertionLibraryError(ASSERT_ERRORS.equal.buffer, testCallsite), filepath('equal', 'buffer')); - assertTestRunError(new ExternalAssertionLibraryError(ASSERT_ERRORS.equal.emptyString, testCallsite), filepath('equal', 'empty-string')); - assertTestRunError(new ExternalAssertionLibraryError(ASSERT_ERRORS.equal.function, testCallsite), filepath('equal', 'function')); - assertTestRunError(new ExternalAssertionLibraryError(ASSERT_ERRORS.equal.number, testCallsite), filepath('equal', 'number')); - assertTestRunError(new ExternalAssertionLibraryError(ASSERT_ERRORS.equal.object, testCallsite), filepath('equal', 'object')); - assertTestRunError(new ExternalAssertionLibraryError(ASSERT_ERRORS.equal.string, testCallsite), filepath('equal', 'string')); - - assertErrorMessage('external-assertion-library-errors/builtin/equal/undefined-null', new ExternalAssertionLibraryError(ASSERT_ERRORS.equal.undefinedNull, testCallsite)); - }); - - it('Not Deep Equal', () => { - assertTestRunError(new ExternalAssertionLibraryError(ASSERT_ERRORS.notEqual.string, testCallsite), filepath('not-equal', 'string')); - }); - - it('Ok', () => { - assertTestRunError(new ExternalAssertionLibraryError(ASSERT_ERRORS.ok.boolean, testCallsite), filepath('ok', 'boolean')); - }); - - it('Not Ok', () => { - assertTestRunError(new ExternalAssertionLibraryError(ASSERT_ERRORS.notOk.boolean, testCallsite), filepath('not-ok', 'boolean')); - }); - - it('Contains', () => { - assertTestRunError(new ExternalAssertionLibraryError(ASSERT_ERRORS.contains.string, testCallsite), filepath('contains', 'string')); - }); - - it('Not Contains', () => { - assertTestRunError(new ExternalAssertionLibraryError(ASSERT_ERRORS.notContains.string, testCallsite), filepath('not-contains', 'string')); - }); - - it('Match', () => { - assertTestRunError(new ExternalAssertionLibraryError(ASSERT_ERRORS.match.regexp, testCallsite), filepath('match', 'regexp')); - }); - - it('Not Match', () => { - assertTestRunError(new ExternalAssertionLibraryError(ASSERT_ERRORS.notMatch.regexp, testCallsite), filepath('not-match', 'regexp')); - }); - - it('Type of', () => { - assertTestRunError(new ExternalAssertionLibraryError(ASSERT_ERRORS.typeOf.null, testCallsite), filepath('type-of', 'null')); - }); - - it('Not Type of', () => { - assertTestRunError(new ExternalAssertionLibraryError(ASSERT_ERRORS.notTypeOf.null, testCallsite), filepath('not-type-of', 'null')); - }); - - it('Within', () => { - assertTestRunError(new ExternalAssertionLibraryError(ASSERT_ERRORS.within.number, testCallsite), filepath('within', 'number')); - }); - - it('Not Within', () => { - assertTestRunError(new ExternalAssertionLibraryError(ASSERT_ERRORS.notWithin.number, testCallsite), filepath('not-within', 'number')); - }); - - it('Less than', () => { - assertTestRunError(new ExternalAssertionLibraryError(ASSERT_ERRORS.lt.number, testCallsite), filepath('less-than', 'number')); - }); - - it('Less than or Equal to', () => { - assertTestRunError(new ExternalAssertionLibraryError(ASSERT_ERRORS.lte.number, testCallsite), filepath('less-than-or-equal', 'number')); - }); - - it('Greater than', () => { - assertTestRunError(new ExternalAssertionLibraryError(ASSERT_ERRORS.gt.number, testCallsite), filepath('greater-than', 'number')); - }); - - it('Greater than or Equal to', () => { - assertTestRunError(new ExternalAssertionLibraryError(ASSERT_ERRORS.gte.number, testCallsite), filepath('greater-than-or-equal', 'number')); - }); - }); - - it('Should format "uncaughtErrorInClientFunctionCode"', () => { - assertErrorMessage('uncaught-error-in-client-function-code', new UncaughtErrorInClientFunctionCode('Selector', new Error('Some error.'))); - }); - - it('Should format "clientFunctionExecutionInterruptionError"', () => { - assertErrorMessage('client-function-execution-interruption-error', new ClientFunctionExecutionInterruptionError('eval')); - }); - - it('Should format "domNodeClientFunctionResultError"', () => { - assertErrorMessage('dom-node-client-function-result-error', new DomNodeClientFunctionResultError('ClientFunction')); - }); - - it('Should format "invalidSelectorResultError"', () => { - assertErrorMessage('invalid-selector-result-error', new InvalidSelectorResultError()); - }); - - it('Should format "nativeDialogNotHandledError"', () => { - assertErrorMessage('native-dialog-not-handled-error', new NativeDialogNotHandledError('alert', 'http://example.org')); - }); - - it('Should format "uncaughtErrorInNativeDialogHandler"', () => { - assertErrorMessage('uncaught-error-in-native-dialog-handler', new UncaughtErrorInNativeDialogHandler('alert', 'error message', 'http://example.org')); - }); - - it('Should format "setNativeDialogHandlerCodeWrongTypeError"', () => { - assertErrorMessage('set-native-dialog-handler-code-wrong-type-error', new SetNativeDialogHandlerCodeWrongTypeError('number')); - }); - - it('Should format "cannotObtainInfoForElementSpecifiedBySelectorError"', () => { - assertErrorMessage('cannot-obtain-info-for-element-specified-by-selector-error', new CannotObtainInfoForElementSpecifiedBySelectorError(testCallsite, { - apiFnChain: [longSelector, 'one', 'two', 'three'], - apiFnIndex: 1, - })); - }); - - it('Should format "windowDimensionsOverflowError"', () => { - assertErrorMessage('window-dimensions-overflow-error', new WindowDimensionsOverflowError()); - }); - - it('Should format "forbiddenCharactersInScreenshotPathError"', () => { - assertErrorMessage('forbidden-characters-in-screenshot-path-error', new ForbiddenCharactersInScreenshotPathError('/root/bla:bla', [{ - chars: ':', - index: 9, - }])); - }); - - it('Should format "invalidElementScreenshotDimensionsError"', () => { - assertErrorMessage('invalid-element-screenshot-dimensions-error', new InvalidElementScreenshotDimensionsError(0, 10)); - }); - - it('Should format "setTestSpeedArgumentError"', () => { - assertErrorMessage('set-test-speed-argument-error', new SetTestSpeedArgumentError('speed', 'string')); - }); - - it('Should format "roleSwitchInRoleInitializerError"', () => { - assertErrorMessage('role-switch-in-role-initializer-error', new RoleSwitchInRoleInitializerError(testCallsite)); - }); - - it('Should format "actionRoleArgumentError"', () => { - assertErrorMessage('action-role-argument-error', new ActionRoleArgumentError('role', 'number')); - }); - - it('Should format "assertionExecutableArgumentError"', () => { - assertErrorMessage('assertion-executable-argument-error', new AssertionExecutableArgumentError('actual', '1 + temp', { rawMessage: 'Unexpected identifier' }, true)); - }); - - it('Should format "assertionWithoutMethodCallError"', () => { - assertErrorMessage('assertion-without-method-call-error', new AssertionWithoutMethodCallError(testCallsite)); - }); - - it('Should format "assertionUnawaitedPromiseError"', () => { - assertErrorMessage('assertion-unawaited-promise-error', new AssertionUnawaitedPromiseError(testCallsite)); - }); - - it('Should format "requestHookNotImplementedError"', () => { - assertErrorMessage('request-hook-method-not-implemented-error', new RequestHookNotImplementedMethodError('onRequest', 'MyHook')); - }); - - it('Should format "requestHookUnhandledError"', () => { - assertErrorMessage('request-hook-unhandled-error', new RequestHookUnhandledError(new Error('Test error'), 'MyHook', 'onRequest')); - }); - - it('Should format "uncaughtErrorInCustomClientScriptCode"', () => { - assertErrorMessage('uncaught-error-in-custom-client-script-code', new UncaughtErrorInCustomClientScriptCode(new TypeError('Cannot read property "prop" of undefined'))); - }); - - it('Should format "uncaughtErrorInCustomClientScriptCodeLoadedFromModule"', () => { - assertErrorMessage('uncaught-error-in-custom-client-script-code-loaded-from-module', new UncaughtErrorInCustomClientScriptLoadedFromModule(new TypeError('Cannot read property "prop" of undefined'), 'test-module')); - }); - - it('Should format "uncaughtErrorInCustomScript"', () => { - assertErrorMessage('uncaught-error-in-custom-script', new UncaughtErrorInCustomScript(new Error('Test error'), '1+1', 1, 1, 'RAW API callsite')); - }); - - it('Should format "uncaughtTestCafeErrorInCustomScript"', () => { - const expression = 'Hey ya!'; - const originError = getErrorAdapter(new UncaughtNonErrorObjectInTestCode(expression)); - - assertErrorMessage('uncaught-test-cafe-error-in-custom-script', new UncaughtTestCafeErrorInCustomScript(originError, expression, void 0, void 0, 'RAW API callsite')); - }); - - it('Should format "childWindowIsNotLoadedError"', () => { - assertErrorMessage('child-window-is-not-loaded-error', new ChildWindowIsNotLoadedError()); - }); - - it('Should format "childWindowNotFoundError"', () => { - assertErrorMessage('child-window-not-found-error', new ChildWindowNotFoundError()); - }); - - it('Should format "cannotSwitchToWindowError"', () => { - assertErrorMessage('cannot-switch-to-child-window-error', new CannotSwitchToWindowError()); - }); - - it('Should format "closeChildWindowError"', () => { - assertErrorMessage('close-child-window-error', new CloseChildWindowError()); - }); - - it('Should format "childWindowClosedBeforeSwitchingError"', () => { - assertErrorMessage('child-window-closed-before-switching-error', new ChildWindowClosedBeforeSwitchingError()); - }); - - it('Should format "cannotCloseWindowWithChildrenError"', () => { - assertErrorMessage('cannot-close-window-with-children-error', new CannotCloseWindowWithChildrenError()); - }); - - it('Should format "cannotCloseWindowWithoutParentError"', () => { - assertErrorMessage('cannot-close-window-without-parent-error', new CannotCloseWindowWithoutParentError()); - }); - - it('Should format "windowNotFoundError"', () => { - assertErrorMessage('window-not-found-error', new WindowNotFoundError()); - }); - - it('Should format "parentWindowNotFoundError"', () => { - assertErrorMessage('parent-window-not-found-error', new ParentWindowNotFoundError()); - }); - - it('Should format "previousWindowNotFoundError"', () => { - assertErrorMessage('previous-window-not-found-error', new PreviousWindowNotFoundError()); - }); - - it('Should format "switchToWindowPredicateError"', () => { - assertErrorMessage('switch-to-window-predicate-error', new SwitchToWindowPredicateError('error message')); - }); - - it('Should format "actionFunctionArgumentError"', () => { - assertErrorMessage('action-function-argument-error', new ActionFunctionArgumentError('predicate', 'number')); - }); - - it('Should format "multipleWindowsModeIsDisabledError"', () => { - assertErrorMessage('multiple-windows-mode-is-disabled-error', new MultipleWindowsModeIsDisabledError('openWindow')); - }); - - it('Should format "multipleWindowsModeIsNotSupportedInRemoteBrowserError"', () => { - assertErrorMessage('multiple-windows-mode-is-not-available-in-remote-browser-error', new MultipleWindowsModeIsNotAvailableInRemoteBrowserError('openWindow')); - }); - - it('Should format "multipleWindowsModeIsNotSupportedInNativeAutomationError"', () => { - assertErrorMessage('multiple-windows-mode-is-not-supported-in-native-automation-error', new MultipleWindowsModeIsNotSupportedInNativeAutomationModeError('openWindow')); - }); - - it('Should format "cannotRestoreChildWindowError"', () => { - assertErrorMessage('cannot-restore-child-window-error', new CannotRestoreChildWindowError()); - }); - - it('Should format "executionTimeoutExceeded"', () => { - assertErrorMessage('execution-timeout-exceeded', new TimeoutError(500, 'Scope')); - }); - - it('Should format "actionCookieArgumentError"', () => { - assertErrorMessage('action-cookie-argument-error', new ActionCookieArgumentError()); - }); - - it('Should format "actionCookieArgumentsError"', () => { - assertErrorMessage('action-cookie-arguments-error', new ActionCookieArgumentsError(0, false)); - }); - - it('Should format "actionUrlCookieArgumentError"', () => { - assertErrorMessage('action-url-cookie-argument-error', new ActionUrlCookieArgumentError()); - }); - - it('Should format "ActionUrlsCookieArgumentError"', () => { - assertErrorMessage('action-urls-cookie-argument-error', new ActionUrlsCookieArgumentError(0, 'crash')); - }); - - it('Should format "actionRequiredSetCookieArgumentsAreMissedError"', () => { - assertErrorMessage('action-required-cookie-arguments', new ActionRequiredCookieArguments()); - }); - - it('Should format "actionStringOptionError"', () => { - assertErrorMessage('action-string-option-error', new ActionStringOptionError('name', 'object')); - }); - - it('Should format "actionExpiresOptionError"', () => { - assertErrorMessage('action-date-option-error', new ActionDateOptionError('expires', 'string')); - }); - - it('Should format "actionNumberOptionError"', () => { - assertErrorMessage('action-number-option-error', new ActionNumberOptionError('maxAge', 'object')); - }); - - it('Should format "actionUrlOptionError"', () => { - assertErrorMessage('action-url-option-error', new ActionUrlOptionError('url', 'object')); - }); - - it('Should format "actionUrlSearchParamsOptionError"', () => { - assertErrorMessage('action-url-search-params-option-error', new ActionUrlSearchParamsOptionError('params', 'number')); - }); - - it('Should format "actionObjectOptionError"', () => { - assertErrorMessage('action-object-option-error', new ActionObjectOptionError('headers', 'number')); - }); - - it('Should format "actionUrlArgumentError"', () => { - assertErrorMessage('action-url-argument-error', new ActionUrlArgumentError('url', 'object')); - }); - - it('Should format "actionStringOrRegexOptionError"', () => { - assertErrorMessage('action-string-or-regex-argument-error', new ActionStringOrRegexOptionError('SkipJsErrorsOptions.message', 'object')); - }); - - it('Should format "actionSkipJsErrorsArgumentTypeError"', () => { - assertErrorMessage('action-skip-js-errors-argument-error', new ActionSkipJsErrorsArgumentTypeError('options', 'string')); - }); - - it('Should format "actionFunctionOptionError"', () => { - assertErrorMessage('action-function-option-error', new ActionFunctionOptionError('fn', 'string')); - }); - - it('Should format "actionInvalidObjectPropertyError"', () => { - assertErrorMessage('action-invalid-object-property-error', new ActionInvalidObjectPropertyError('ClickOptions', 'invalidProp', ['alt', 'ctrl'])); - }); - }); - - describe('Test coverage', () => { - it('Should test messages for all error codes', () => { - expect(untestedErrorTypes).to.be.empty; - }); - - it('Errors codes should be unique', () => { - function getDuplicates (codes) { - return chain(codes).groupBy().pickBy(x => x.length > 1).keys().value(); - } - - const testRunErrorCodes = values(TEST_RUN_ERRORS); - const runtimeErrorCodes = values(RUNTIME_ERRORS); - const testRunErrorCodeDuplicates = getDuplicates(testRunErrorCodes); - const runtimeErrorCodeDuplicates = getDuplicates(runtimeErrorCodes); - const testRunAndRuntimeErrorCodeDuplicates = getDuplicates(testRunErrorCodes.concat(runtimeErrorCodes)); - - expect(testRunErrorCodeDuplicates, 'TestRunErrorCode duplicates').to.be.empty; - expect(runtimeErrorCodeDuplicates, 'RuntimeErrorCode duplicates').to.be.empty; - expect(testRunAndRuntimeErrorCodeDuplicates, 'Intersections between TestRunErrorCodes and RuntimeErrorCodes').to.be.empty; - }); - }); -}); diff --git a/test/server/test-run-request-handler-test.js b/test/server/test-run-request-handler-test.js deleted file mode 100644 index 4559fb8e5a1..00000000000 --- a/test/server/test-run-request-handler-test.js +++ /dev/null @@ -1,17 +0,0 @@ -const delay = require('../../lib/utils/delay'); -const BaseTestRunMock = require('./helpers/base-test-run-mock'); - -describe('Request handling', () => { - it("Should abort request if it's longer than 3s", function () { - this.timeout(4000); - - const testRun = new BaseTestRunMock(); - const handleRequestPromise = testRun.ready({ status: { id: 1, consoleMessages: [] } }); - - const timeoutPromise = delay(3500).then(() => { - throw new Error('timeout is exceeded'); - }); - - return Promise.race([handleRequestPromise, timeoutPromise]); - }); -}); diff --git a/test/server/test-run-tracker-test.js b/test/server/test-run-tracker-test.js deleted file mode 100644 index 2e1dfa4c3a0..00000000000 --- a/test/server/test-run-tracker-test.js +++ /dev/null @@ -1,86 +0,0 @@ -const { expect } = require('chai'); -const fill = require('lodash/fill'); -const Compiler = require('../../lib/compiler'); -const BaseTestRunMock = require('./helpers/base-test-run-mock'); - - -describe('Test run tracker', function () { - this.timeout(20000); - - function runTest (testName) { - const src = 'test/server/data/test-run-tracking/' + testName; - const compiler = new Compiler([src]); - const testRunMock = new BaseTestRunMock(); - const expected = fill(Array(3), testRunMock.id); - - return compiler.getTests() - .then(function (tests) { - const test = tests[0]; - - return Promise.all([ - test.fixture.beforeEachFn ? test.fixture.beforeEachFn(testRunMock) : testRunMock.id, - test.fn(testRunMock), - test.fixture.afterEachFn ? test.fixture.afterEachFn(testRunMock) : testRunMock.id, - ]); - }) - .then(function (res) { - expect(res).eql(expected); - }); - } - - it('Should find test run ID in test function call', function () { - return runTest('in-test-function.js'); - }); - - it('Should find test run ID in test function after `await`', function () { - return runTest('in-test-function-after-await.js'); - }); - - it('Should find test run ID in test function after `await` with error', function () { - return runTest('in-function-after-await-with-error.js'); - }); - - it('Should find test run ID in helper', function () { - return runTest('in-helper.js'); - }); - - it('Should find test run ID in helper after `await`', function () { - return runTest('in-helper-after-await.js'); - }); - - it('Should find test run ID in `setInterval`', function () { - return runTest('in-set-interval.js'); - }); - - it('Should find test run ID in `setTimeout`', function () { - return runTest('in-set-timeout.js'); - }); - - it('Should find test run ID in `setImmediate`', function () { - return runTest('in-set-immediate.js'); - }); - - it('Should find test run ID in `nextTick`', function () { - return runTest('in-next-tick.js'); - }); - - it('Should find test run ID in `Promise.then()`', function () { - return runTest('in-promise-then.js'); - }); - - it('Should find test run ID in `Promise.catch()`', function () { - return runTest('in-promise-catch.js'); - }); - - it('Should find test run ID in `Promise.then()` second handler', function () { - return runTest('in-promise-then-second-handler.js'); - }); - - it('Should find test run ID in `Promise.resolve()`', function () { - return runTest('in-promise-resolve.js'); - }); - - it('Should find test run ID in Promise ctor', function () { - return runTest('in-promise-ctor.js'); - }); -}); diff --git a/test/server/util-test.js b/test/server/util-test.js deleted file mode 100644 index 31f484ccde2..00000000000 --- a/test/server/util-test.js +++ /dev/null @@ -1,721 +0,0 @@ -const path = require('path'); -const { PassThrough } = require('stream'); -const EventEmitter = require('events'); -const Module = require('module'); -const fs = require('fs'); -const del = require('del'); -const osFamily = require('os-family'); -const { expect } = require('chai'); -const { noop } = require('lodash'); -const proxyquire = require('proxyquire').noPreserveCache(); -const sinon = require('sinon'); -const correctFilePath = require('../../lib/utils/correct-file-path'); -const escapeUserAgent = require('../../lib/utils/escape-user-agent'); -const parseFileList = require('../../lib/utils/parse-file-list'); -const TempDirectory = require('../../lib/utils/temp-directory'); -const { getConcatenatedValuesString } = require('../../lib/utils/string'); -const getCommonPath = require('../../lib/utils/get-common-path'); -const resolvePathRelativelyCwd = require('../../lib/utils/resolve-path-relatively-cwd'); -const getFilterFn = require('../../lib/utils/get-filter-fn'); -const prepareReporters = require('../../lib/utils/prepare-reporters'); -const createTempProfile = require('../../lib/browser/provider/built-in/dedicated/chrome/create-temp-profile'); -const { parseUserAgent } = require('../../lib/utils/parse-user-agent'); -const diff = require('../../lib/utils/diff'); -const { generateScreenshotMark } = require('../../lib/screenshots/utils'); -const getViewPortWidth = require('../../lib/utils/get-viewport-width'); -const TEST_RUN_PHASE = require('../../lib/test-run/phase'); -const { - replaceLeadingSpacesWithNbsp, - markup, - SUBTITLES, -} = require('../../lib/errors/test-run/utils'); -const { - buildChromeArgs, - CONTAINERIZED_CHROME_FLAGS, -} = require('../../lib/browser/provider/built-in/dedicated/chrome/build-chrome-args'); - -describe('Utils', () => { - it('Correct File Path', () => { - expect(correctFilePath('\\test')).eql(path.sep + 'test'); - expect(correctFilePath('"')).eql(''); - expect(correctFilePath('test.png', 'test.png')); - expect(correctFilePath('test', 'png')).eql('test.png'); - }); - - it('Escape user agent', () => { - expect(escapeUserAgent('Chrome 67.0.3396 / Windows 8.1.0.0')).eql('Chrome_67.0.3396_Windows_8.1.0.0'); - }); - - it('Diff', () => { - expect(diff(null, null)).eql({}); - expect(diff(void 0, void 0)).eql({}); - expect(diff(1, 2)).eql({}); - expect(diff({ a: void 0 }, { b: void 0 })).eql({}); - expect(diff({ a: null }, { b: null })).eql({}); - expect(diff({ a: null }, { a: 1 })).eql({ a: 1 }); - expect(diff({ a: 1 }, { a: 1 })).eql({}); - expect(diff({ a: 1 }, { a: void 0 })).eql({ a: void 0 }); - expect(diff({ a: 1 }, { a: null })).eql({ a: null }); - expect(diff({ a: 1, b: 1 }, { a: 1, b: 1 })).eql({}); - expect(diff({ a: 1, b: {} }, { a: 1, b: {} })).eql({}); - expect(diff({ a: 1, b: { c: 3 } }, { a: 1, b: { c: 3 } })).eql({}); - expect(diff({ a: 1, b: { c: { d: 4 } } }, { a: 1, b: { c: { d: 4 } } })).eql({}); - expect(diff({ a: 0 }, { a: 1 })).eql({ a: 1 }); - expect(diff({ a: 1 }, { a: 0 })).eql({ a: 0 }); - expect(diff({ a: 1 }, { a: 2 })).eql({ a: 2 }); - expect(diff({ a: 1, b: 1 }, { a: 1, b: 2 })).eql({ b: 2 }); - expect(diff({ a: 1, b: { c: 3 } }, { a: 1, b: { c: 4 } })).eql({ b: { c: 4 } }); - expect(diff({ a: 1, b: { c: 3 } }, { a: 2, b: { c: 4 } })).eql({ a: 2, b: { c: 4 } }); - expect(diff({ a: 1, b: { c: { d: 4 } } }, { a: 1, b: { c: { d: 5 } } })).eql({ b: { c: { d: 5 } } }); - }); - - it('Parse user agent', () => { - const expectedEmptyParsedUA = { - name: 'Other', - version: '0.0', - platform: 'other', - os: { name: 'Other', version: '0.0' }, - engine: { name: 'Other', version: '0.0' }, - prettyUserAgent: 'Other 0.0 / Other 0.0', - userAgent: '', - }; - - const testCases = [ - { - sourceUA: '', - expected: expectedEmptyParsedUA, - }, - { - sourceUA: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.70 Safari/537.36', - expected: { - name: 'Chrome', - version: '78.0.3904.70', - platform: 'desktop', - os: { name: 'Windows', version: '10' }, - engine: { name: 'Blink', version: '0.0' }, - prettyUserAgent: 'Chrome 78.0.3904.70 / Windows 10', - userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.70 Safari/537.36', - }, - }, - { - sourceUA: 'Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.1 Mobile/15E148 Safari/604.1', - expected: { - name: 'Safari', - version: '12.1', - platform: 'tablet', - os: { name: 'iOS', version: '12.2' }, - engine: { name: 'WebKit', version: '605.1.15' }, - prettyUserAgent: 'Safari 12.1 / iOS 12.2', - userAgent: 'Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.1 Mobile/15E148 Safari/604.1', - }, - }, - { - sourceUA: 'Mozilla/5.0 (Linux; Android 8.1.0; Android SDK built for x86 Build/OSM1.180201.026) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Mobile Safari/537.36', - expected: { - name: 'Chrome', - version: '67.0.3396.87', - platform: 'mobile', - os: { name: 'Android', version: '8.1.0' }, - engine: { name: 'Blink', version: '0.0' }, - prettyUserAgent: 'Chrome 67.0.3396.87 / Android 8.1.0', - userAgent: 'Mozilla/5.0 (Linux; Android 8.1.0; Android SDK built for x86 Build/OSM1.180201.026) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Mobile Safari/537.36', - }, - }, - { - sourceUA: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.130 Electron/7.1.7 Safari/537.36', - expected: { - name: 'Electron', - version: '7.1.7', - platform: 'desktop', - os: { name: 'Windows', version: '10' }, - engine: { name: 'Blink', version: '0.0' }, - prettyUserAgent: 'Electron 7.1.7 / Windows 10', - userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.130 Electron/7.1.7 Safari/537.36', - }, - }, - { - sourceUA: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/113.0.1774.42 Safari/537.36 HeadlessEdg/113.0.1774.42', - expected: { - 'engine': { 'name': 'Blink', 'version': '0.0' }, - 'name': 'Microsoft Edge', - 'os': { 'name': 'Windows', 'version': '10' }, - 'platform': 'desktop', - 'prettyUserAgent': 'Microsoft Edge 113.0.1774.42 / Windows 10', - 'userAgent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/113.0.1774.42 Safari/537.36 HeadlessEdg/113.0.1774.42', - 'version': '113.0.1774.42', - }, - }, - ]; - - testCases.forEach(testCase => { - expect(parseUserAgent(testCase.sourceUA)).to.deep.eql(testCase.expected); - }); - - expect(parseUserAgent()).to.deep.eql(expectedEmptyParsedUA); - }); - - describe('Parse file list', () => { - it('Default directories', () => { - const workingDir = path.join(__dirname, './data/file-list'); - - const expectedFiles = [ - 'test/test-dir-file.js', - 'tests/tests-dir-file.js', - ].map(file => { - return path.resolve(workingDir, file); - }); - - return parseFileList(void 0, workingDir) - .then(actualFiles => { - expect(actualFiles).eql(expectedFiles); - }); - }); - - it('File, directory and glob pattern', () => { - const cwd = process.cwd(); - - let expectedFiles = [ - 'test/server/data/file-list/file-1.js', - 'test/server/data/file-list/file-2.js', - 'test/server/data/file-list/dir1/dir1-1/file-1-1-1.js', - 'test/server/data/file-list/dir1/file-1-1.js', - 'test/server/data/file-list/dir1/file-1-2.js', - 'test/server/data/file-list/dir1/file-1-3.testcafe', - 'test/server/data/file-list/dir1/file-1-4.ts', - 'test/server/data/file-list/dir2/file-2-2.js', - 'test/server/data/file-list/dir2/file-2-3.js', - 'test/server/data/file-list/dir4/dir4-1/file-4-1-1.js', - 'test/server/data/file-list/dir4/dir4-1/file-4-1-2.ts', - 'test/server/data/file-list/dir4/dir4-1/file-4-1-3.testcafe', - 'test/server/data/file-list/dir4/dir4-2/file-4-2-1.js', - 'test/server/data/file-list/dir4/dir4-2/file-4-2-2.ts', - 'test/server/data/file-list/dir4/dir4-2/file-4-2-3.testcafe', - ]; - - if (osFamily.win) { - expectedFiles.push( - 'test/server/data/file-list/dir5/file-5-1.js', - 'test/server/data/file-list/dir6/file-6-1.js' - ); - } - - expectedFiles = expectedFiles.map(file => { - return path.resolve(cwd, file); - }); - - const fileList = [ - 'test/server/data/file-list/file-1.js', - path.join(cwd, 'test/server/data/file-list/file-2.js'), - 'test/server/data/file-list/dir1', - 'test/server/data/file-list/dir2/*.js', - '!test/server/data/file-list/dir2/file-2-1.js', - 'test/server/data/file-list/dir3/', - 'test/server/data/file-list/dir4/**/*/', - ]; - - if (osFamily.win) { - fileList.push( - 'test\\server\\data\\file-list\\dir5\\*\\', - 'test\\server\\data\\file-list\\dir6\\' - ); - } - - return parseFileList(fileList, cwd).then(actualFiles => { - expect(actualFiles).eql(expectedFiles); - }); - }); - - if (osFamily.win) { - it('File on same drive but with different letter case in label (win only)', () => { - const { root, dir, base } = path.parse(process.cwd()); - - const cwd1 = path.join(root.toLowerCase(), path.relative(root, dir), base); - const cwd2 = path.join(root.toUpperCase(), path.relative(root, dir), base); - - const sources = [path.resolve(cwd1, 'test/server/data/file-list/file-1.js')]; - const expected = [path.resolve(cwd2, 'test/server/data/file-list/file-1.js')]; - - return parseFileList(sources, cwd2).then(actualFiles => { - expect(actualFiles).eql(expected); - }); - }); - } - }); - - describe('Temp Directory', () => { - const TMP_ROOT = resolvePathRelativelyCwd('__tmp__'); - const savedTmpRoot = TempDirectory.TEMP_DIRECTORIES_ROOT; - - beforeEach(() => { - TempDirectory.TEMP_DIRECTORIES_ROOT = TMP_ROOT; - - return del(TMP_ROOT); - }); - - afterEach(() => { - TempDirectory.TEMP_DIRECTORIES_ROOT = savedTmpRoot; - - return del(TMP_ROOT); - }); - - it('Should reuse existing temp directories after synchronous disposal', function () { - const tempDir1 = new TempDirectory(); - const tempDir2 = new TempDirectory(); - const tempDir3 = new TempDirectory(); - - return tempDir1 - .init() - .then(() => tempDir2.init()) - .then(() => tempDir1._disposeSync()) - .then(() => tempDir3.init()) - .then(() => { - const subDirs = fs.readdirSync(TempDirectory.TEMP_DIRECTORIES_ROOT); - - expect(subDirs.length).eql(2); - expect(tempDir3.path).eql(tempDir1.path); - }); - }); - - it('Should remove temp directories after asynchronous disposal', function () { - const tempDir = new TempDirectory(); - - return tempDir - .init() - .then(() => { - const subDirs = fs.readdirSync(TempDirectory.TEMP_DIRECTORIES_ROOT); - - expect(subDirs.length).eql(1); - }) - .then(() => tempDir.dispose()) - .then(() => { - const subDirs = fs.readdirSync(TempDirectory.TEMP_DIRECTORIES_ROOT); - - expect(subDirs.length).eql(0); - }); - }); - - describe('Cleanup Process', () => { - const origArgv0 = process.argv[0]; - - beforeEach(() => { - process.argv[0] = origArgv0; - }); - - afterEach(() => { - process.argv[0] = origArgv0; - }); - - it('Should always start a subprocess using the correct Node.js path (GH-4276)', async () => { - class FakeChildProcess extends EventEmitter { - constructor () { - super(); - - this.unref = noop; - this.stdout = new PassThrough(); - this.stdout.unref = noop; - this.stderr = new PassThrough(); - this.stderr.unref = noop; - this.channel = new EventEmitter(); - this.channel.unref = noop; - - this.on('newListener', () => process.nextTick(() => this.emit('exit'))); - } - } - - const fakeSpawn = sinon.stub().returns(new FakeChildProcess()); - - process.argv[0] = 'wrong path'; - - const cleanupProcess = proxyquire('../../lib/utils/temp-directory/cleanup-process', { - 'child_process': { - spawn: fakeSpawn, - }, - }); - - await cleanupProcess.init(); - - expect(fakeSpawn.args[0][0]).contains('node'); - }); - }); - }); - - describe('Error utils', () => { - it('Markup should return correct value for error in "pendingFinalization" phase', () => { - const err = { - userAgent: 'Chrome 104.0.5112.81 / Windows 10', - screenshotPath: '', - testRunId: 'UGqL1Nz7Z', - testRunPhase: 'pendingFinalization', - code: 'E53', - isTestCafeError: true, - callsite: '0', - errMsg: 'AssertionError: expected false to be truthy', - diff: false, - id: '7fTLOzU', - - getCallsiteMarkup: () => '0', - }; - const msgMarkup = '\n AssertionError: expected false to be truthy\n\n \n'; - const expectedResult = '
AssertionError: expected false to be truthy
\n\n' + - 'Browser: Chrome 104.0.5112.81 / Windows 10\n\n0'; - - expect(markup(err, msgMarkup)).eql(expectedResult); - }); - - it('SUBTITLES should contains definitions of all test run phases', () => { - for (const phase in TEST_RUN_PHASE) - expect(phase in SUBTITLES).to.be.ok; - }); - - it('Replace leading spaces with  ', () => { - expect(replaceLeadingSpacesWithNbsp('test')).eql('test'); - expect(replaceLeadingSpacesWithNbsp(' test')).eql(' test'); - expect(replaceLeadingSpacesWithNbsp(' test')).eql('  test'); - expect(replaceLeadingSpacesWithNbsp(' test1 test2 ')).eql(' test1 test2 '); - expect(replaceLeadingSpacesWithNbsp(' test1\n test2 \r\ntest3 ')).eql('  test1\n test2 \r\ntest3 '); - }); - }); - - it('Get common path', () => { - const winPaths = ['D:\\home', 'D:\\home\\user\\tmp', 'D:\\home\\user', 'D:\\home\\temp']; - const unixPaths = ['/home', '/home/user/tmp', '/home/user', '/home/temp']; - const paths = path.sep === '/' ? unixPaths : winPaths; - - expect(getCommonPath([paths[1]])).eql(paths[1]); - expect(getCommonPath([paths[1], paths[1]])).eql(paths[1]); - expect(getCommonPath([paths[1], paths[2]])).eql(paths[2]); - expect(getCommonPath([paths[1], paths[2], paths[3]])).eql(paths[0]); - }); - - describe('Get Filter Fn', () => { - it('Should return "undefined" if no filtering options were specified', () => { - expect(getFilterFn({})).is.undefined; - }); - - it('Should filter by a test name', () => { - const filter = getFilterFn({ test: 'test' }); - - expect(filter('test', void 0, void 0, void 0, void 0)).to.be.true; - expect(filter('test2', void 0, void 0, void 0, void 0)).to.be.false; - }); - - it('Should filter by a fixture name', () => { - const filter = getFilterFn({ fixture: 'fixture' }); - - expect(filter(void 0, 'fixture', void 0, void 0, void 0)).to.be.true; - expect(filter(void 0, 'fixture1', void 0, void 0, void 0)).to.be.false; - }); - - it('Should filter by a test name RegExp', () => { - const filter = getFilterFn({ testGrep: /test\d/ }); - - expect(filter('test1', void 0, void 0, void 0, void 0)).to.be.true; - expect(filter('testX', void 0, void 0, void 0, void 0)).to.be.false; - }); - - it('Should filter by a fixture name RegExp', () => { - const filter = getFilterFn({ fixtureGrep: /fixture\d/ }); - - expect(filter(void 0, 'fixture1', void 0, void 0, void 0)).to.be.true; - expect(filter(void 0, 'fixtureA', void 0, void 0, void 0)).to.be.false; - }); - - it('Should filter by a test meta', () => { - const filter = getFilterFn({ testMeta: { test: 'meta' } }); - - expect(filter(void 0, void 0, void 0, { test: 'meta' }, void 0)).to.be.true; - expect(filter(void 0, void 0, void 0, { test: 'metaX' }, void 0)).to.be.false; - }); - - it('Should filter by a fixture meta', () => { - const filter = getFilterFn({ fixtureMeta: { fixture: 'meta' } }); - - expect(filter(void 0, void 0, void 0, void 0, { fixture: 'meta' })).to.be.true; - expect(filter(void 0, void 0, void 0, void 0, { fixture: 'metaX' })).to.be.false; - }); - }); - - it('Get concatenated values string', () => { - expect(getConcatenatedValuesString([1])).eql('"1"'); - expect(getConcatenatedValuesString(['1', '2'])).eql('"1" and "2"'); - expect(getConcatenatedValuesString([1, 2, 3])).eql('"1", "2", and "3"'); - expect(getConcatenatedValuesString([1, 2], '\n')).eql('"1"\n"2"'); - }); - - describe('Moment Module Loader', () => { - const moduleCacheDesciptor = Object.getOwnPropertyDescriptor(Module, '_cache'); - const originalLoad = Module._load; - - beforeEach(() => { - for (const cachedModule of Object.keys(require.cache)) - delete require.cache[cachedModule]; - }); - - afterEach(() => { - Module._load = originalLoad; - - Object.defineProperty(Module, '_cache', moduleCacheDesciptor); - }); - - it('Should work when multiple moment modules are installed (GH-1750)', () => { - const momentModulePath = require.resolve('moment'); - - for (const cachedModule of Object.keys(require.cache)) - delete require.cache[cachedModule]; - - Module._load = function (...args) { - const modulePath = Module._resolveFilename(...args); - - // NOTE: Remove cached moment module to simulate multiple installations of moment - if (modulePath === modulePath) - delete Module._cache[momentModulePath]; - - return originalLoad.apply(this, args); - }; - - const moment = require('../../lib/utils/moment-loader'); - - expect(moment.duration.format).to.be.ok; - }); - - it('Should work when modules cache is disabled (GH-2500)', () => { - Object.defineProperty(Module, '_cache', { - enumerable: true, - configurable: true, - - get: () => Object.create(null), - set: v => v, - }); - - const moment = require('../../lib/utils/moment-loader'); - - expect(moment.duration.format).to.be.ok; - }); - }); - - describe('Prepare reporters', () => { - it('Single string name', () => { - const result = prepareReporters('minimal'); - - expect(result).instanceOf(Array); - expect(result.length).eql(1); - expect(result[0].name).eql('minimal'); - expect(result[0].output).is.undefined; - }); - - it('Array of string names', () => { - const result = prepareReporters(['json', 'minimal']); - - expect(result.length).eql(2); - expect(result[0].name).eql('json'); - expect(result[1].name).eql('minimal'); - }); - - it('Function as reporter name', () => { - const fn1 = function () { - }; - const fn2 = function () { - }; - - const result = prepareReporters([fn1, fn2]); - - expect(result.length).eql(2); - expect(result[0].name).eql(fn1); - expect(result[1].name).eql(fn2); - }); - - it('Name and output stream', () => { - const result = prepareReporters('minimal', 'path/to/file'); - - expect(result.length).eql(1); - expect(result[0].name).eql('minimal'); - expect(result[0].output).eql('path/to/file'); - }); - - it('Array of names and output streams', () => { - const data = [ - { - name: 'minimal', - outStream: 'path/to/file/1', - }, - { - name: 'json', - outStream: 'path/to/file/2', - }, - ]; - - const result = prepareReporters(data); - - expect(result).eql(data); - }); - - it('Reporter output validation', () => { - const shouldThrowCases = [ - {}, - null, - 9, - function () { - }, - ]; - - shouldThrowCases.forEach(output => { - expect(() => { - prepareReporters('test', output); - }).to.throw("Specify a file name or a writable stream as the reporter's output target"); - }); - - const shouldNotThrowCases = [ - void 0, - 'path/to/file', - { - write: noop, - end: noop, - }, - new PassThrough(), - ]; - - shouldNotThrowCases.forEach(output => { - expect(() => { - prepareReporters('test', output); - }).to.not.throw(); - }); - }); - }); - - it('Build Chrome arguments', () => { - const config = { - userProfile: false, - headless: false, - userArgs: '', - }; - - const cdpPort = ''; - const platformArgs = '--no-first-run'; - - const tempProfileDir = { - path: '/temp/testcafe/chrome-profile-34904xxzNmO5Vkbtz', - }; - - let chromeArgs = ''; - - const IN_DOCKER_FLAGS_RE = new RegExp(CONTAINERIZED_CHROME_FLAGS.join(' ')); - const SANDBOX_FLAG_RE = new RegExp('--no-sandbox'); - const DISABLE_DEV_SHM_USAGE_RE = new RegExp('--disable-dev-shm-usage'); - - let containerizedChromeFlags = null; - - chromeArgs = buildChromeArgs({ config, cdpPort, platformArgs, tempProfileDir, isContainerized: false }); - containerizedChromeFlags = chromeArgs.match(IN_DOCKER_FLAGS_RE); - - expect(containerizedChromeFlags).eql(null); - - chromeArgs = buildChromeArgs({ config, cdpPort, platformArgs, tempProfileDir, isContainerized: true }); - containerizedChromeFlags = chromeArgs.match(IN_DOCKER_FLAGS_RE); - - expect(containerizedChromeFlags.length).eql(1); - - // NOTE: Flag should not be duplicated - config.userArgs = '--no-sandbox --disable-dev-shm-usage'; - chromeArgs = buildChromeArgs({ config, cdpPort, platformArgs, tempProfileDir, isContainerized: true }); - containerizedChromeFlags = chromeArgs.match(SANDBOX_FLAG_RE); - - expect(containerizedChromeFlags.length).eql(1); - - containerizedChromeFlags = chromeArgs.match(DISABLE_DEV_SHM_USAGE_RE); - - expect(containerizedChromeFlags.length).eql(1); - }); - - describe('Create temporary profile for the Google Chrome browser', () => { - const TMP_ROOT = resolvePathRelativelyCwd('__tmp__'); - const savedTmpRoot = TempDirectory.TEMP_DIRECTORIES_ROOT; - - beforeEach(() => { - TempDirectory.TEMP_DIRECTORIES_ROOT = TMP_ROOT; - - return del(TMP_ROOT); - }); - - afterEach(() => { - TempDirectory.TEMP_DIRECTORIES_ROOT = savedTmpRoot; - - return del(TMP_ROOT); - }); - - it("Without 'disableMultipleWindows' option", async () => { - const tempDir = await createTempProfile('testhost', false); - const profileFile = path.join(tempDir.path, 'Default', 'Preferences'); - const preferences = JSON.parse(fs.readFileSync(profileFile)); - - expect(preferences.profile.content_settings.exceptions.popups).eql({ 'testhost': { setting: 1 } }); - }); - - it("With 'disableMultipleWindows' option", async () => { - const tempDir = await createTempProfile('testhost', true); - const profileFile = path.join(tempDir.path, 'Default', 'Preferences'); - const preferences = JSON.parse(fs.readFileSync(profileFile)); - - expect(preferences.profile.content_settings.exceptions.popups).to.be.undefined; - }); - }); - - it('generateScreenshotMark', () => { - const { markSeed } = generateScreenshotMark(); - - expect(markSeed.length).eql(128); - - for (const markPixel of markSeed) - expect(markPixel === 0 || markPixel === 255).is.true; - }); - - it('getViewPortWidth', () => { - const nonTTYStreamMock = {}; - - expect(getViewPortWidth(nonTTYStreamMock)).eql(Infinity); - }); - - describe('checkIsVM', () => { - const vendors = ['virtual', 'vmware', 'hyperv', 'wsl', 'hyper-v', 'microsoft', 'parallels', 'qemu']; - - const checkVMVendors = async (platform, stdout = '') => { - const { checkIsVM } = proxyquire('../../lib/utils/check-is-vm', { - '../../lib/utils/promisified-functions': { - exec: () => Promise.resolve({ stdout }), - }, - 'os': { - platform: () => platform, - }, - }); - - return await checkIsVM(); - }; - - it('should return false on real machine', async () => { - const vm = await checkVMVendors('win32', ''); - - expect(vm).false; - }); - - it('should detect windows machine', async () => { - await Promise.all(vendors.map(async vendor => { - const vm = await checkVMVendors('win32', vendor); - - expect(vm).true; - })); - }); - - it('should detect linux machine', async () => { - const vm = await checkVMVendors('linux'); - - expect(vm).true; - }); - - it('should detect macos machine', async () => { - await Promise.all(vendors.map(async vendor => { - const vm = await checkVMVendors('darwin', vendor); - - expect(vm).true; - })); - }); - }); -}); diff --git a/test/server/video-recorder-test.js b/test/server/video-recorder-test.js deleted file mode 100644 index 5582fc2f5a3..00000000000 --- a/test/server/video-recorder-test.js +++ /dev/null @@ -1,323 +0,0 @@ -const { expect } = require('chai'); -const { noop } = require('lodash'); -const TestRun = require('../../lib/test-run/index'); -const VideoRecorder = require('../../lib/video-recorder/recorder'); -const Videos = require('../../lib/video-recorder/videos'); -const TestRunVideoRecorder = require('../../lib/video-recorder/test-run-video-recorder'); -const AsyncEmitter = require('../../lib/utils/async-event-emitter'); -const WarningLog = require('../../lib/notifications/warning-log'); -const COMMAND_TYPE = require('../../lib/test-run/commands/type'); -const renderTemplate = require('../../lib/utils/render-template'); - -const VIDEOS_BASE_PATH = '__videos__'; - -class VideoRecorderProcessMock { - constructor () { - } - - init () { - } - - startCapturing () { - } - - finishCapturing () { - } -} - -class TestRunVideoRecorderMock extends TestRunVideoRecorder { - constructor (testRunInfo, recordingOptions, warningLog, testLog) { - super(testRunInfo, recordingOptions, warningLog); - - this.log = testLog; - } - - _generateTempNames () { - const result = super._generateTempNames(); - - this.log.push('generate-names'); - - return result; - } - - _createVideoRecorderProcess () { - return new VideoRecorderProcessMock(); - } - - _addTimeCode () { - this.timecodes.push(10); - } -} - -class VideoRecorderMock extends VideoRecorder { - constructor (basePath, ffmpegPath, connection, customOptions) { - super(basePath, ffmpegPath, connection, customOptions); - - this.log = []; - - this.warningLog = { - addWarning: (message, ...args) => { - message = typeof message === 'string' ? message : message.message; - - const msg = renderTemplate(message, ...args); - - this.log.push(msg); - }, - }; - } - - _createTestRunVideoRecorder (testRunInfo, recordingOptions) { - return new TestRunVideoRecorderMock(testRunInfo, recordingOptions, this.warningLog, this.log); - } - - _onBrowserJobStart () { - this.log.push('job-start'); - - return super._onBrowserJobStart() - .then(() => { - this.log.push('temp-dir-initialized'); - }); - } - - _onTestRunCreate (options) { - this.log.push('test-created'); - - return super._onTestRunCreate(options); - } - - _getTargetVideoPath (testRunRecorder) { - return `path-${testRunRecorder.testRun.id}`; - } - - _saveFiles () { - } -} - -class VideosMock extends Videos { - constructor (browserJobs, options, warningLog, timeStamp) { - super(browserJobs, options, warningLog, timeStamp); - } - - _createVideoRecorder (browserJob, videoPath, options, videoEncodingOptions, warningLog) { - return new VideoRecorderMock(browserJob, videoPath, options, videoEncodingOptions, warningLog); - } -} - -function createTestRunMock (warningLog) { - const testRun = Object.create(TestRun.prototype); - - Object.assign(testRun, { - test: { name: 'Test', id: 'test-id' }, - debugLog: { command: noop }, - _enqueueCommand: noop, - browserManipulationQueue: [], - warningLog: warningLog, - - opts: { videoPath: 'path' }, - - browserConnection: { - id: 'connectionId', - browserInfo: {}, - provider: { - hasCustomActionForBrowser: () => { - return { - hasGetVideoFrameData: true, - }; - }, - }, - }, - }); - - return { - testRun, - test: { skip: false, fixture: { name: 'Fixture' } }, - index: 0, - }; -} - -describe('Video Recorder', () => { - it('Should not start video recording for legacy tests', () => { - const browserJobMock = new AsyncEmitter(); - const videoRecorder = new VideoRecorder(browserJobMock, VIDEOS_BASE_PATH, {}, {}); - - const testRunCreateEventDataMock = { - testRun: {}, - legacy: true, - index: 1, - test: {}, - quarantine: null, - }; - - return browserJobMock - .emit('start') - .then(() => browserJobMock.emit('test-run-created', testRunCreateEventDataMock)) - .then(() => { - expect(videoRecorder.testRunVideoRecorders).to.be.empty; - }); - }); - - it('Should correctly format the warning message about no suitable path pattern placeholders', () => { - const browserJobMock = new AsyncEmitter(); - const warningLog = new WarningLog(); - const videoRecorder = new VideoRecorder(browserJobMock, VIDEOS_BASE_PATH, {}, {}, warningLog); - - videoRecorder._addProblematicPlaceholdersWarning(['${TEST_INDEX}']); - expect(warningLog.messages).eql([ - 'TestCafe could not apply the following video recording save path pattern: "${TEST_INDEX}".\n' + - 'You may encounter this behavior when you enable the "singleFile" video recording option and use test-specific path patterns.' + - '\n\n' + - 'The placeholder was replaced with an empty string.', - ]); - warningLog.messageInfos = []; - - videoRecorder._addProblematicPlaceholdersWarning(['${TEST_INDEX}', '${FIXTURE}']); - expect(warningLog.messages).eql([ - 'TestCafe could not apply the following video recording save path patterns: "${TEST_INDEX}" and "${FIXTURE}".\n' + - 'You may encounter this behavior when you enable the "singleFile" video recording option and use test-specific path patterns.' + - '\n\n' + - 'The placeholders were replaced with an empty string.', - ]); - }); - - it('Should wait for Temp directory is initialized', () => { - const browserJobMock = new AsyncEmitter(); - const warningLog = new WarningLog(); - const videoRecorder = new VideoRecorderMock(browserJobMock, VIDEOS_BASE_PATH, {}, {}, warningLog); - - browserJobMock.emit('start'); - - const testRunCreatePromise = browserJobMock.emit('test-run-create', createTestRunMock()); - - browserJobMock.emit('done'); - - return testRunCreatePromise.then(() => { - expect(videoRecorder.log).eql([ - 'job-start', - 'test-created', - 'temp-dir-initialized', - 'generate-names', - ]); - }); - }); - - it('Should emit a warning on resize action', () => { - const browserJobMock = new AsyncEmitter(); - const videoRecorder = new VideoRecorderMock(browserJobMock, VIDEOS_BASE_PATH, {}, {}); - - const testRunMock = createTestRunMock(videoRecorder.warningLog); - - return browserJobMock.emit('start') - .then(() => browserJobMock.emit('test-run-create', testRunMock)) - .then(() => browserJobMock.emit('test-run-before-done', testRunMock)) - .then(() => testRunMock.testRun.executeCommand({ type: COMMAND_TYPE.resizeWindow })) - .then(() => { - expect(videoRecorder.log.includes('The browser window was resized during the "Test" test while TestCafe recorded a video. TestCafe cannot adjust the video resolution during recording. As a result, the video content may appear broken. Do not resize the browser window when TestCafe records a video.')).to.be.true; - }); - }); - - it('Should build correct video info object', () => { - const browserJobMock = new AsyncEmitter(); - - const videos1 = new VideosMock([browserJobMock], { videoPath: VIDEOS_BASE_PATH, videoOptions: { singleFile: true } }); - const videos2 = new VideosMock([browserJobMock], { videoPath: VIDEOS_BASE_PATH, videoOptions: { singleFile: false } }); - - const testRunMock1 = createTestRunMock(); - const testRunMock2 = createTestRunMock(); - const testRunMock3 = createTestRunMock(); - const testRunMock4 = createTestRunMock(); - - const test1 = { name: 'Test1', id: 'test-1' }; - const test2 = { name: 'Test2', id: 'test-2' }; - - Object.assign(testRunMock1.testRun, { session: { id: 'test-run-1' }, test: test1 }); - Object.assign(testRunMock2.testRun, { session: { id: 'test-run-2' }, test: test1 }); - Object.assign(testRunMock3.testRun, { session: { id: 'test-run-3' }, test: test2 }); - Object.assign(testRunMock4.testRun, { session: { id: 'test-run-4' }, test: test2 }); - - testRunMock1.index = 0; - testRunMock2.index = 1; - testRunMock3.index = 2; - testRunMock4.index = 3; - - const expectedLog1 = { - testVideoInfos: { - 'test-1': { - recordings: [{ - testRunId: 'test-run-1', - videoPath: 'path-test-run-1', - singleFile: true, - }, { - testRunId: 'test-run-2', - videoPath: 'path-test-run-2', - singleFile: true, - }], - }, - 'test-2': { - recordings: [{ - testRunId: 'test-run-3', - videoPath: 'path-test-run-3', - singleFile: true, - }, { - testRunId: 'test-run-4', - videoPath: 'path-test-run-4', - singleFile: true, - }], - }, - }, - }; - - const expectedLog2 = { - testVideoInfos: { - 'test-1': { - recordings: [{ - testRunId: 'test-run-1', - videoPath: 'path-test-run-1', - timecodes: [0, 10], - singleFile: false, - }, { - testRunId: 'test-run-2', - videoPath: 'path-test-run-2', - timecodes: [0, 10], - singleFile: false, - }], - }, - 'test-2': { - recordings: [{ - testRunId: 'test-run-3', - videoPath: 'path-test-run-3', - timecodes: [0, 10], - singleFile: false, - }, { - testRunId: 'test-run-4', - videoPath: 'path-test-run-4', - timecodes: [0, 10], - singleFile: false, - }], - }, - }, - }; - - - return browserJobMock.emit('start') - .then(() => browserJobMock.emit('test-run-create', testRunMock1)) - .then(() => browserJobMock.emit('test-run-ready', testRunMock1)) - .then(() => browserJobMock.emit('test-run-restart', testRunMock1)) - .then(() => browserJobMock.emit('test-run-before-done', testRunMock1)) - .then(() => browserJobMock.emit('test-run-create', testRunMock2)) - .then(() => browserJobMock.emit('test-run-ready', testRunMock2)) - .then(() => browserJobMock.emit('test-run-restart', testRunMock2)) - .then(() => browserJobMock.emit('test-run-before-done', testRunMock2)) - .then(() => browserJobMock.emit('test-run-create', testRunMock3)) - .then(() => browserJobMock.emit('test-run-ready', testRunMock3)) - .then(() => browserJobMock.emit('test-run-restart', testRunMock3)) - .then(() => browserJobMock.emit('test-run-before-done', testRunMock3)) - .then(() => browserJobMock.emit('test-run-create', testRunMock4)) - .then(() => browserJobMock.emit('test-run-ready', testRunMock4)) - .then(() => browserJobMock.emit('test-run-restart', testRunMock4)) - .then(() => browserJobMock.emit('test-run-before-done', testRunMock4)) - .then(() => { - expect(videos1).eql(expectedLog1); - expect(videos2).eql(expectedLog2); - }); - }); -}); diff --git a/test/server/warning-log-test.js b/test/server/warning-log-test.js deleted file mode 100644 index c2ba6b34aaf..00000000000 --- a/test/server/warning-log-test.js +++ /dev/null @@ -1,79 +0,0 @@ -const expect = require('chai').expect; -const WarningLog = require('../../lib/notifications/warning-log'); -const WARNINGS = require('../../lib/notifications/warning-message'); - - -const TYPE_ERROR_TEXT = 'TypeError'; -const SYNTAX_ERROR_TEXT = 'SyntaxError'; - - -describe('Warning log', () => { - it('Should render and store warnings', () => { - const log = new WarningLog(); - - log.addWarning(WARNINGS.screenshotError, TYPE_ERROR_TEXT); - log.addWarning(WARNINGS.screenshotError, 'SyntaxError'); - - expect(log.messages).eql([ - 'Was unable to take a screenshot due to an error.\n\n' + TYPE_ERROR_TEXT, - 'Was unable to take a screenshot due to an error.\n\n' + SYNTAX_ERROR_TEXT, - ]); - }); - - it('Should remove duplicates', () => { - const log = new WarningLog(); - - log.addWarning(WARNINGS.screenshotError, TYPE_ERROR_TEXT); - log.addWarning(WARNINGS.screenshotError, TYPE_ERROR_TEXT); - - expect(log.messages).eql([ - 'Was unable to take a screenshot due to an error.\n\n' + TYPE_ERROR_TEXT, - ]); - }); - - it('Should add messages to the parent log', () => { - const globalLog = new WarningLog(); - const log = new WarningLog(globalLog); - - - log.addWarning(WARNINGS.screenshotError, TYPE_ERROR_TEXT); - - expect(log.messages).eql([ - 'Was unable to take a screenshot due to an error.\n\n' + TYPE_ERROR_TEXT, - ]); - - expect(globalLog.messages).eql([ - 'Was unable to take a screenshot due to an error.\n\n' + TYPE_ERROR_TEXT, - ]); - }); - - it('Should clear warning messages', () => { - const globalLog = new WarningLog(); - const log = new WarningLog(globalLog); - - log.addWarning(WARNINGS.screenshotError, TYPE_ERROR_TEXT); - log.clear(); - - expect(log.messages).eql([]); - - expect(globalLog.messages).eql([ - 'Was unable to take a screenshot due to an error.\n\n' + TYPE_ERROR_TEXT, - ]); - }); - - it('Should copy messages to another instance', () => { - const firstLog = new WarningLog(); - const secondLog = new WarningLog(); - - firstLog.addWarning(WARNINGS.screenshotError, TYPE_ERROR_TEXT); - secondLog.copyFrom(firstLog); - - expect(firstLog.messages).eql([ - 'Was unable to take a screenshot due to an error.\n\n' + TYPE_ERROR_TEXT, - ]); - - expect(secondLog.messages).eql([ - 'Was unable to take a screenshot due to an error.\n\n' + TYPE_ERROR_TEXT, - ]); - }); -}); From 79f51c00ade3094dd4c87e310c5dab11f53c25a2 Mon Sep 17 00:00:00 2001 From: Alex Kamaev Date: Mon, 16 Oct 2023 16:39:42 +0400 Subject: [PATCH 4/7] ==44 --- src/compiler/index.js | 4 ++++ src/compiler/test-file/api-based.js | 16 +++++++++++++++- src/compiler/test-file/base.js | 5 ++++- src/configuration/configuration-base.ts | 21 ++++++++++++++++++++- src/runner/bootstrapper.ts | 12 ++++++------ 5 files changed, 49 insertions(+), 9 deletions(-) diff --git a/src/compiler/index.js b/src/compiler/index.js index 984d1acdb54..9b4dbadb186 100644 --- a/src/compiler/index.js +++ b/src/compiler/index.js @@ -87,6 +87,8 @@ export default class Compiler { } async _getTests ({ compiler, filename, code, compiledCode }) { + debugger; + if (compiledCode || this.esm && compiler.canCompileInEsm) return await compiler.execute(compiledCode, filename); @@ -94,6 +96,8 @@ export default class Compiler { } async _compileTestFiles (filenames) { + + const testFilesInfo = await this._createTestFilesInfo(filenames); const compilerTasks = this._getCompilerTasks(testFilesInfo); diff --git a/src/compiler/test-file/api-based.js b/src/compiler/test-file/api-based.js index f921b0ae2b6..8037ee94a7b 100644 --- a/src/compiler/test-file/api-based.js +++ b/src/compiler/test-file/api-based.js @@ -82,7 +82,15 @@ export default class APIBasedTestFileCompilerBase extends TestFileCompilerBase { mod._compile(code, filename); + debugger; + + Module._cache[filename] = mod; + cacheProxy.stopExternalCaching(); + + this.emit('module-compiled', mod); + + Module._cache[filename] = mod; } } @@ -129,6 +137,12 @@ export default class APIBasedTestFileCompilerBase extends TestFileCompilerBase { this.origRequireExtensions[ext] = origExt; require.extensions[ext] = (mod, filename) => { + console.log('require:', ext, filename); + + if (ext === '.ts') { + debugger; + } + const hadGlobalAPI = this._hasGlobalAPI(); // NOTE: remove global API so that it will be unavailable for the dependencies @@ -247,6 +261,6 @@ export default class APIBasedTestFileCompilerBase extends TestFileCompilerBase { } cleanUp () { - this.cache = {}; + // this.cache = {}; } } diff --git a/src/compiler/test-file/base.js b/src/compiler/test-file/base.js index e1d9c3ffade..d97dbf4fc14 100644 --- a/src/compiler/test-file/base.js +++ b/src/compiler/test-file/base.js @@ -1,9 +1,12 @@ import { escapeRegExp as escapeRe, flatten } from 'lodash'; import { assertBaseUrl, getUrl } from '../../api/test-page-url'; import { assertType, is } from '../../errors/runtime/type-assertions'; +import { EventEmitter } from 'events'; -export default class TestFileCompilerBase { +export default class TestFileCompilerBase extends EventEmitter { constructor ({ baseUrl }) { + super(); + const escapedExt = flatten([this.getSupportedExtension()]) .map(ext => escapeRe(ext)) .join('|'); diff --git a/src/configuration/configuration-base.ts b/src/configuration/configuration-base.ts index 847efb1fea0..04b94706b67 100644 --- a/src/configuration/configuration-base.ts +++ b/src/configuration/configuration-base.ts @@ -250,9 +250,28 @@ export default class Configuration { const precompiledCode = await compiler.precompile([{ filename: filePath }]); + debugger; + + + + debugger; + + const waitUntilCompiled = new Promise((resolve, reject) => { + compiler.on('module-compiled', (mod:any) => { + console.log('!!!!!!!!!!!!!'); + resolve(mod.exports); + }); + }); + await compiler.compile(precompiledCode?.[0], filePath); - const options = require(filePath); + // @ts-ignore + return waitUntilCompiled; + + const options = require(filePath as string); + + + // return {}; return options; } diff --git a/src/runner/bootstrapper.ts b/src/runner/bootstrapper.ts index 9291b9a445e..e7bd8def470 100644 --- a/src/runner/bootstrapper.ts +++ b/src/runner/bootstrapper.ts @@ -304,8 +304,8 @@ export default class Bootstrapper { const cwd = process.cwd(); const sourceList = await parseFileList(this.sources, cwd); - if (!sourceList.length) - throw new GeneralError(RUNTIME_ERRORS.testFilesNotFound, cwd, getConcatenatedValuesString(this.sources, '\n', '')); + // if (!sourceList.length) + // throw new GeneralError(RUNTIME_ERRORS.testFilesNotFound, cwd, getConcatenatedValuesString(this.sources, '\n', '')); let tests = await guardTimeExecution( async () => await this._compileTests({ sourceList, compilerOptions: this.compilerOptions, runnableConfigurationId: id }), @@ -324,14 +324,14 @@ export default class Bootstrapper { if (testsWithOnlyFlag.length) tests = testsWithOnlyFlag; - if (!tests.length) - throw new GeneralError(RUNTIME_ERRORS.noTestsToRun); + // if (!tests.length) + // throw new GeneralError(RUNTIME_ERRORS.noTestsToRun); if (this.filter) tests = await this._filterTests(tests, this.filter); - if (!tests.length) - throw new GeneralError(RUNTIME_ERRORS.noTestsToRunDueFiltering); + // if (!tests.length) + // throw new GeneralError(RUNTIME_ERRORS.noTestsToRunDueFiltering); this._setGlobalHooksToTests(tests); From c4cefbd388e932ac0a0c9e4828f44592d6234bf5 Mon Sep 17 00:00:00 2001 From: Alex Kamaev Date: Mon, 16 Oct 2023 17:25:20 +0400 Subject: [PATCH 5/7] test --- src/compiler/test-file/api-based.js | 4 +++- src/configuration/configuration-base.ts | 10 ++++------ test/server/configuration-test.js | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/compiler/test-file/api-based.js b/src/compiler/test-file/api-based.js index 8037ee94a7b..c07527ed976 100644 --- a/src/compiler/test-file/api-based.js +++ b/src/compiler/test-file/api-based.js @@ -73,6 +73,8 @@ export default class APIBasedTestFileCompilerBase extends TestFileCompilerBase { await eval(`import('${fileUrl}?${PREVENT_MODULE_CACHING_SUFFIX}=${Date.now()}')`); } else { + debugger; + const mod = new Module(filename, module.parent); mod.filename = filename; @@ -88,7 +90,7 @@ export default class APIBasedTestFileCompilerBase extends TestFileCompilerBase { cacheProxy.stopExternalCaching(); - this.emit('module-compiled', mod); + this.emit('module-compiled', mod.exports); Module._cache[filename] = mod; } diff --git a/src/configuration/configuration-base.ts b/src/configuration/configuration-base.ts index 04b94706b67..8a47fefff87 100644 --- a/src/configuration/configuration-base.ts +++ b/src/configuration/configuration-base.ts @@ -254,12 +254,10 @@ export default class Configuration { - debugger; - const waitUntilCompiled = new Promise((resolve, reject) => { - compiler.on('module-compiled', (mod:any) => { + compiler.on('module-compiled', (options) => { console.log('!!!!!!!!!!!!!'); - resolve(mod.exports); + resolve(options); }); }); @@ -268,11 +266,11 @@ export default class Configuration { // @ts-ignore return waitUntilCompiled; - const options = require(filePath as string); + // const options = require(filePath as string); // return {}; - return options; + // return options; } return null; diff --git a/test/server/configuration-test.js b/test/server/configuration-test.js index e2b5e8a3690..109a57708bb 100644 --- a/test/server/configuration-test.js +++ b/test/server/configuration-test.js @@ -800,7 +800,7 @@ describe('TypeScriptConfiguration', function () { expect(configuration.getOption('browser')).eql(options.browser); }); - it('Custom ts config path is used', async () => { + it.only('Custom ts config path is used', async () => { const customConfigFile = 'custom11.testcaferc.ts'; const options = { From 992abea19f1d7eaaecdf63e6c4b4ac12364b7eaf Mon Sep 17 00:00:00 2001 From: Alex Kamaev Date: Thu, 19 Oct 2023 15:39:19 +0400 Subject: [PATCH 6/7] setset --- src/compiler/compilers.js | 2 +- src/compiler/test-file/api-based.js | 40 +++++++++++++----- .../test-file/formats/typescript/compiler.ts | 41 +++++++++++++++---- src/configuration/configuration-base.ts | 26 ++++++------ test/server/configuration-test.js | 2 +- 5 files changed, 78 insertions(+), 33 deletions(-) diff --git a/src/compiler/compilers.js b/src/compiler/compilers.js index b625e7afb2c..15f9bf8f0ab 100644 --- a/src/compiler/compilers.js +++ b/src/compiler/compilers.js @@ -1,7 +1,7 @@ import hammerhead from 'testcafe-hammerhead'; import { Compiler as LegacyTestFileCompiler } from 'testcafe-legacy-api'; import EsNextTestFileCompiler from './test-file/formats/es-next/compiler'; -import TypeScriptTestFileCompiler from './test-file/formats/typescript/compiler'; +import { TypeScriptTestFileCompiler } from './test-file/formats/typescript/compiler'; import CoffeeScriptTestFileCompiler from './test-file/formats/coffeescript/compiler'; import RawTestFileCompiler from './test-file/formats/raw/compiler'; import DevToolsTestFileCompiler from './test-file/formats/dev-tools/compiler'; diff --git a/src/compiler/test-file/api-based.js b/src/compiler/test-file/api-based.js index c07527ed976..65b4a93f5d9 100644 --- a/src/compiler/test-file/api-based.js +++ b/src/compiler/test-file/api-based.js @@ -93,6 +93,8 @@ export default class APIBasedTestFileCompilerBase extends TestFileCompilerBase { this.emit('module-compiled', mod.exports); Module._cache[filename] = mod; + + return mod; } } @@ -145,16 +147,16 @@ export default class APIBasedTestFileCompilerBase extends TestFileCompilerBase { debugger; } - const hadGlobalAPI = this._hasGlobalAPI(); + // const hadGlobalAPI = this._hasGlobalAPI(); // NOTE: remove global API so that it will be unavailable for the dependencies - if (APIBasedTestFileCompilerBase._isNodeModulesDep(filename) && hadGlobalAPI) - this._removeGlobalAPI(); + // if (APIBasedTestFileCompilerBase._isNodeModulesDep(filename) && hadGlobalAPI) + // this._removeGlobalAPI(); this._compileExternalModule(mod, filename, requireCompilers[ext], origExt); - if (hadGlobalAPI && !this._hasGlobalAPI()) - this._addGlobalAPI(testFile); + // if (hadGlobalAPI && !this._hasGlobalAPI()) + // this._addGlobalAPI(testFile); }; }); } @@ -207,8 +209,8 @@ export default class APIBasedTestFileCompilerBase extends TestFileCompilerBase { return global.fixture && global.test; } - async _runCompiledCode (compiledCode, filename) { - const testFile = new TestFile(filename); + async _runCompiledCode (testFile, compiledCode, filename) { + let compiledModule = null; this._addGlobalAPI(testFile); this._addExportAPI(testFile); @@ -218,7 +220,7 @@ export default class APIBasedTestFileCompilerBase extends TestFileCompilerBase { this._setupRequireHook(testFile); try { - await this._execAsModule(compiledCode, filename); + compiledModule = await this._execAsModule(compiledCode, filename); } catch (err) { if (err.code === errRequireEsmErrorCode) @@ -237,7 +239,7 @@ export default class APIBasedTestFileCompilerBase extends TestFileCompilerBase { this._removeGlobalAPI(); } - return testFile.getTests(); + return compiledModule; } @@ -246,7 +248,11 @@ export default class APIBasedTestFileCompilerBase extends TestFileCompilerBase { } execute (compiledCode, filename) { - return this._runCompiledCode(compiledCode, filename); + const testFile = new TestFile(filename); + + this._runCompiledCode(testFile, compiledCode, filename); + + return testFile.getTests(); } async compile (code, filename) { @@ -258,6 +264,20 @@ export default class APIBasedTestFileCompilerBase extends TestFileCompilerBase { return Promise.resolve(); } + // async compileConfiguration (filename) { + // const [compiledCode] = await this.precompile([{ code: '', filename }]); + // + // if (compiledCode) { + // debugger; + // const compiledConfigurationModule = await this._runCompiledCode({}, compiledCode, filename); + // debugger; + // + // return compiledConfigurationModule.exports; + // } + // + // return Promise.resolve(); + // } + _hasTests (code) { return FIXTURE_RE.test(code) && TEST_RE.test(code); } diff --git a/src/compiler/test-file/formats/typescript/compiler.ts b/src/compiler/test-file/formats/typescript/compiler.ts index 9d4b7361c4e..39bc811a846 100644 --- a/src/compiler/test-file/formats/typescript/compiler.ts +++ b/src/compiler/test-file/formats/typescript/compiler.ts @@ -88,8 +88,8 @@ const RENAMED_DEPENDENCIES_MAP = new Map([['testcafe', getExportableLibPath()]]) const DEFAULT_TYPESCRIPT_COMPILER_PATH = 'typescript'; -export default class TypeScriptTestFileCompiler extends APIBasedTestFileCompilerBase { - private static tsDefsPath = TypeScriptTestFileCompiler._getTSDefsPath(); +export class TypeScriptFileCompilerBase extends APIBasedTestFileCompilerBase { + private static tsDefsPath = TypeScriptFileCompilerBase._getTSDefsPath(); private readonly _tsConfig: TypescriptConfiguration; private readonly _compilerPath: string; @@ -98,7 +98,7 @@ export default class TypeScriptTestFileCompiler extends APIBasedTestFileCompiler public constructor (compilerOptions?: TypeScriptCompilerOptions, { baseUrl, esm }: OptionalCompilerArguments = {}) { super({ baseUrl, esm }); - // NOTE: At present, it's necessary create an instance TypeScriptTestFileCompiler + // NOTE: At present, it's necessary create an instance TypeScriptFileCompilerBase // to collect a list of supported test file extensions. // So all compilers creates 2 times: first time - for collecting all supported file extensions, // second one - for compiling tests. @@ -108,7 +108,7 @@ export default class TypeScriptTestFileCompiler extends APIBasedTestFileCompiler this._customCompilerOptions = compilerOptions && compilerOptions.options; this._tsConfig = new TypescriptConfiguration(configPath, esm); - this._compilerPath = TypeScriptTestFileCompiler._getCompilerPath(compilerOptions); + this._compilerPath = TypeScriptFileCompilerBase._getCompilerPath(compilerOptions); } private static _getCompilerPath (compilerOptions?: TypeScriptCompilerOptions): string { @@ -147,7 +147,7 @@ export default class TypeScriptTestFileCompiler extends APIBasedTestFileCompiler } private static _getTSDefsPath (): string { - return TypeScriptTestFileCompiler._normalizeFilename(path.resolve(__dirname, '../../../../../ts-defs/index.d.ts')); + return TypeScriptFileCompilerBase._normalizeFilename(path.resolve(__dirname, '../../../../../ts-defs/index.d.ts')); } private _reportErrors (diagnostics: Readonly): void { @@ -180,7 +180,7 @@ export default class TypeScriptTestFileCompiler extends APIBasedTestFileCompiler private _compileFilesToCache (ts: TypeScriptInstance, filenames: string[]): void { const opts = this._tsConfig.getOptions() as Dictionary; - const program = ts.createProgram([TypeScriptTestFileCompiler.tsDefsPath, ...filenames], opts); + const program = ts.createProgram([TypeScriptFileCompilerBase.tsDefsPath, ...filenames], opts); DEBUG_LOGGER('version: %s', ts.version); DEBUG_LOGGER('options: %O', opts); @@ -202,7 +202,7 @@ export default class TypeScriptTestFileCompiler extends APIBasedTestFileCompiler if (!sources) return; - const sourcePath = TypeScriptTestFileCompiler._normalizeFilename(sources[0].fileName); + const sourcePath = TypeScriptFileCompilerBase._normalizeFilename(sources[0].fileName); this.cache[sourcePath] = result; }, void 0, void 0, { @@ -225,11 +225,11 @@ export default class TypeScriptTestFileCompiler extends APIBasedTestFileCompiler // NOTE: lazy load the compiler const ts: TypeScriptInstance = this._loadTypeScriptCompiler(); const filenames = testFilesInfo.map(({ filename }) => filename); - const normalizedFilenames = filenames.map(filename => TypeScriptTestFileCompiler._normalizeFilename(filename)); + const normalizedFilenames = filenames.map(filename => TypeScriptFileCompilerBase._normalizeFilename(filename)); const normalizedFilenamesMap = zipObject(normalizedFilenames, filenames); const uncachedFiles = normalizedFilenames - .filter(filename => filename !== TypeScriptTestFileCompiler.tsDefsPath && !this.cache[filename]) + .filter(filename => filename !== TypeScriptFileCompilerBase.tsDefsPath && !this.cache[filename]) .map(filename => normalizedFilenamesMap[filename]); if (uncachedFiles.length) @@ -265,3 +265,26 @@ export default class TypeScriptTestFileCompiler extends APIBasedTestFileCompiler return [Extensions.ts, Extensions.tsx]; } } + +export class TypeScriptTestFileCompiler extends TypeScriptFileCompilerBase { + // +} + +export class TypeScriptConfigurationFileCompiler extends TypeScriptFileCompilerBase { + _addGlobalAPI () { + } + + async compileConfiguration (filename: string) { + const [compiledCode] = await this.precompile([{ code: '', filename }]); + + if (compiledCode) { + debugger; + const compiledConfigurationModule = await this._runCompiledCode({}, compiledCode, filename); + debugger; + + return compiledConfigurationModule.exports; + } + + return Promise.resolve(); + } +} diff --git a/src/configuration/configuration-base.ts b/src/configuration/configuration-base.ts index 8a47fefff87..00fe9a51e0a 100644 --- a/src/configuration/configuration-base.ts +++ b/src/configuration/configuration-base.ts @@ -24,6 +24,7 @@ import { Dictionary } from './interfaces'; import Extensions from './formats'; import { ReadConfigFileError } from '../errors/runtime'; import { RUNTIME_ERRORS } from '../errors/types'; +import { TypeScriptConfigurationFileCompiler } from '../compiler/test-file/formats/typescript/compiler'; const DEBUG_LOGGER = debug('testcafe:configuration'); @@ -245,26 +246,27 @@ export default class Configuration { public async _readTsConfigurationFileContent (filePath = this.filePath): Promise { if (filePath) { delete require.cache[filePath]; - const TypeScriptTestFileCompiler = require('../compiler/test-file/formats/typescript/compiler'); - const compiler = new TypeScriptTestFileCompiler(); - const precompiledCode = await compiler.precompile([{ filename: filePath }]); + // TODO: change require to import + const { TypeScriptConfigurationFileCompiler } = require('../compiler/test-file/formats/typescript/compiler'); - debugger; + const compiler = new TypeScriptConfigurationFileCompiler(); + // const waitUntilCompiled = new Promise((resolve, reject) => { + // compiler.on('module-compiled', (options:any) => { + // console.log('!!!!!!!!!!!!!'); + // resolve(options); + // }); + // }); + debugger; - const waitUntilCompiled = new Promise((resolve, reject) => { - compiler.on('module-compiled', (options) => { - console.log('!!!!!!!!!!!!!'); - resolve(options); - }); - }); + const options = await compiler.compileConfiguration(filePath); - await compiler.compile(precompiledCode?.[0], filePath); + debugger; // @ts-ignore - return waitUntilCompiled; + return options; // const options = require(filePath as string); diff --git a/test/server/configuration-test.js b/test/server/configuration-test.js index 109a57708bb..e2b5e8a3690 100644 --- a/test/server/configuration-test.js +++ b/test/server/configuration-test.js @@ -800,7 +800,7 @@ describe('TypeScriptConfiguration', function () { expect(configuration.getOption('browser')).eql(options.browser); }); - it.only('Custom ts config path is used', async () => { + it('Custom ts config path is used', async () => { const customConfigFile = 'custom11.testcaferc.ts'; const options = { From 55d5dd711da36e43091d9e48e0db000b10a7c863 Mon Sep 17 00:00:00 2001 From: Alex Kamaev Date: Thu, 19 Oct 2023 16:16:34 +0400 Subject: [PATCH 7/7] test --- src/compiler/compilers.js | 2 +- src/compiler/test-file/api-based.js | 70 +++++++++-------- .../test-file/formats/typescript/compiler.ts | 76 ++++++++++++++----- src/configuration/configuration-base.ts | 5 +- test/server/compiler-test.js | 6 +- 5 files changed, 99 insertions(+), 60 deletions(-) diff --git a/src/compiler/compilers.js b/src/compiler/compilers.js index 15f9bf8f0ab..b625e7afb2c 100644 --- a/src/compiler/compilers.js +++ b/src/compiler/compilers.js @@ -1,7 +1,7 @@ import hammerhead from 'testcafe-hammerhead'; import { Compiler as LegacyTestFileCompiler } from 'testcafe-legacy-api'; import EsNextTestFileCompiler from './test-file/formats/es-next/compiler'; -import { TypeScriptTestFileCompiler } from './test-file/formats/typescript/compiler'; +import TypeScriptTestFileCompiler from './test-file/formats/typescript/compiler'; import CoffeeScriptTestFileCompiler from './test-file/formats/coffeescript/compiler'; import RawTestFileCompiler from './test-file/formats/raw/compiler'; import DevToolsTestFileCompiler from './test-file/formats/dev-tools/compiler'; diff --git a/src/compiler/test-file/api-based.js b/src/compiler/test-file/api-based.js index 65b4a93f5d9..1a7ac9cd39f 100644 --- a/src/compiler/test-file/api-based.js +++ b/src/compiler/test-file/api-based.js @@ -84,16 +84,8 @@ export default class APIBasedTestFileCompilerBase extends TestFileCompilerBase { mod._compile(code, filename); - debugger; - - Module._cache[filename] = mod; - cacheProxy.stopExternalCaching(); - this.emit('module-compiled', mod.exports); - - Module._cache[filename] = mod; - return mod; } } @@ -147,16 +139,16 @@ export default class APIBasedTestFileCompilerBase extends TestFileCompilerBase { debugger; } - // const hadGlobalAPI = this._hasGlobalAPI(); + const hadGlobalAPI = this._hasGlobalAPI(); // NOTE: remove global API so that it will be unavailable for the dependencies - // if (APIBasedTestFileCompilerBase._isNodeModulesDep(filename) && hadGlobalAPI) - // this._removeGlobalAPI(); + if (APIBasedTestFileCompilerBase._isNodeModulesDep(filename) && hadGlobalAPI) + this._removeGlobalAPI(); this._compileExternalModule(mod, filename, requireCompilers[ext], origExt); - // if (hadGlobalAPI && !this._hasGlobalAPI()) - // this._addGlobalAPI(testFile); + if (hadGlobalAPI && !this._hasGlobalAPI()) + this._addGlobalAPI(testFile); }; }); } @@ -209,48 +201,54 @@ export default class APIBasedTestFileCompilerBase extends TestFileCompilerBase { return global.fixture && global.test; } - async _runCompiledCode (testFile, compiledCode, filename) { - let compiledModule = null; + _runCompiledCode (testFile, compiledCode, filename) { + return this._execAsModule(compiledCode, filename); + } + + precompile (testFilesInfo) { + return this._compileCodeForTestFiles(testFilesInfo); + } + + execute (compiledCode, filename) { + return this._runCompiledTestCode(compiledCode, filename); + } + + async _runCompiledTestCode (compiledCode, filename) { + const testFile = new TestFile(filename); + // override in child this._addGlobalAPI(testFile); this._addExportAPI(testFile); + // TODO research and extract/override if needed stackCleaningHook.enabled = true; this._setupRequireHook(testFile); try { - compiledModule = await this._execAsModule(compiledCode, filename); - } - catch (err) { - if (err.code === errRequireEsmErrorCode) + await this._runCompiledCode(testFile, compiledCode, filename); + } catch (err) { + // TODO extract as method and override in child + if (err.code === errRequireEsmErrorCode) { throw new ImportESMInCommonJSError(err, filename); + } - if (!(err instanceof APIError)) + if (!(err instanceof APIError)) { throw new TestCompilationError(stackCleaningHook.cleanError(err)); + } throw err; - } - finally { + } finally { this._removeRequireHook(); - stackCleaningHook.enabled = false; - - if (!this.esm) - this._removeGlobalAPI(); } - return compiledModule; - } + // research + stackCleaningHook.enabled = false; - precompile (testFilesInfo) { - return this._compileCodeForTestFiles(testFilesInfo); - } - - execute (compiledCode, filename) { - const testFile = new TestFile(filename); - - this._runCompiledCode(testFile, compiledCode, filename); + if (!this.esm) { + this._removeGlobalAPI(); + } return testFile.getTests(); } diff --git a/src/compiler/test-file/formats/typescript/compiler.ts b/src/compiler/test-file/formats/typescript/compiler.ts index 39bc811a846..7443160c1ee 100644 --- a/src/compiler/test-file/formats/typescript/compiler.ts +++ b/src/compiler/test-file/formats/typescript/compiler.ts @@ -88,8 +88,8 @@ const RENAMED_DEPENDENCIES_MAP = new Map([['testcafe', getExportableLibPath()]]) const DEFAULT_TYPESCRIPT_COMPILER_PATH = 'typescript'; -export class TypeScriptFileCompilerBase extends APIBasedTestFileCompilerBase { - private static tsDefsPath = TypeScriptFileCompilerBase._getTSDefsPath(); +export default class TypeScriptTestFileCompiler extends APIBasedTestFileCompilerBase { + private static tsDefsPath = TypeScriptTestFileCompiler._getTSDefsPath(); private readonly _tsConfig: TypescriptConfiguration; private readonly _compilerPath: string; @@ -98,7 +98,7 @@ export class TypeScriptFileCompilerBase extends APIBasedTestFileCompilerBase { public constructor (compilerOptions?: TypeScriptCompilerOptions, { baseUrl, esm }: OptionalCompilerArguments = {}) { super({ baseUrl, esm }); - // NOTE: At present, it's necessary create an instance TypeScriptFileCompilerBase + // NOTE: At present, it's necessary create an instance TypeScriptTestFileCompiler // to collect a list of supported test file extensions. // So all compilers creates 2 times: first time - for collecting all supported file extensions, // second one - for compiling tests. @@ -108,7 +108,7 @@ export class TypeScriptFileCompilerBase extends APIBasedTestFileCompilerBase { this._customCompilerOptions = compilerOptions && compilerOptions.options; this._tsConfig = new TypescriptConfiguration(configPath, esm); - this._compilerPath = TypeScriptFileCompilerBase._getCompilerPath(compilerOptions); + this._compilerPath = TypeScriptTestFileCompiler._getCompilerPath(compilerOptions); } private static _getCompilerPath (compilerOptions?: TypeScriptCompilerOptions): string { @@ -147,7 +147,7 @@ export class TypeScriptFileCompilerBase extends APIBasedTestFileCompilerBase { } private static _getTSDefsPath (): string { - return TypeScriptFileCompilerBase._normalizeFilename(path.resolve(__dirname, '../../../../../ts-defs/index.d.ts')); + return TypeScriptTestFileCompiler._normalizeFilename(path.resolve(__dirname, '../../../../../ts-defs/index.d.ts')); } private _reportErrors (diagnostics: Readonly): void { @@ -180,7 +180,7 @@ export class TypeScriptFileCompilerBase extends APIBasedTestFileCompilerBase { private _compileFilesToCache (ts: TypeScriptInstance, filenames: string[]): void { const opts = this._tsConfig.getOptions() as Dictionary; - const program = ts.createProgram([TypeScriptFileCompilerBase.tsDefsPath, ...filenames], opts); + const program = ts.createProgram([TypeScriptTestFileCompiler.tsDefsPath, ...filenames], opts); DEBUG_LOGGER('version: %s', ts.version); DEBUG_LOGGER('options: %O', opts); @@ -202,7 +202,7 @@ export class TypeScriptFileCompilerBase extends APIBasedTestFileCompilerBase { if (!sources) return; - const sourcePath = TypeScriptFileCompilerBase._normalizeFilename(sources[0].fileName); + const sourcePath = TypeScriptTestFileCompiler._normalizeFilename(sources[0].fileName); this.cache[sourcePath] = result; }, void 0, void 0, { @@ -225,11 +225,11 @@ export class TypeScriptFileCompilerBase extends APIBasedTestFileCompilerBase { // NOTE: lazy load the compiler const ts: TypeScriptInstance = this._loadTypeScriptCompiler(); const filenames = testFilesInfo.map(({ filename }) => filename); - const normalizedFilenames = filenames.map(filename => TypeScriptFileCompilerBase._normalizeFilename(filename)); + const normalizedFilenames = filenames.map(filename => TypeScriptTestFileCompiler._normalizeFilename(filename)); const normalizedFilenamesMap = zipObject(normalizedFilenames, filenames); const uncachedFiles = normalizedFilenames - .filter(filename => filename !== TypeScriptFileCompilerBase.tsDefsPath && !this.cache[filename]) + .filter(filename => filename !== TypeScriptTestFileCompiler.tsDefsPath && !this.cache[filename]) .map(filename => normalizedFilenamesMap[filename]); if (uncachedFiles.length) @@ -264,22 +264,27 @@ export class TypeScriptFileCompilerBase extends APIBasedTestFileCompilerBase { public getSupportedExtension (): string[] { return [Extensions.ts, Extensions.tsx]; } -} -export class TypeScriptTestFileCompiler extends TypeScriptFileCompilerBase { - // -} + async compileConfiguration (filename: string) { + let compiledConfigurationModule = null; -export class TypeScriptConfigurationFileCompiler extends TypeScriptFileCompilerBase { - _addGlobalAPI () { - } + debugger; - async compileConfiguration (filename: string) { const [compiledCode] = await this.precompile([{ code: '', filename }]); if (compiledCode) { - debugger; - const compiledConfigurationModule = await this._runCompiledCode({}, compiledCode, filename); + this._setupRequireHook({ }); + + try { + compiledConfigurationModule = await this._runCompiledCode({}, compiledCode, filename); + } + catch (err) { + + } + finally { + this._removeRequireHook(); + } + debugger; return compiledConfigurationModule.exports; @@ -288,3 +293,36 @@ export class TypeScriptConfigurationFileCompiler extends TypeScriptFileCompilerB return Promise.resolve(); } } + +// export class TypeScriptTestFileCompiler extends TypeScriptTestFileCompiler { +// // +// } +// +// export class TypeScriptConfigurationFileCompiler extends TypeScriptTestFileCompiler { +// +// // async compileConfiguration (filename: string) { +// // let compiledConfigurationModule = null; +// // +// // const [compiledCode] = await this.precompile([{ code: '', filename }]); +// // +// // if (compiledCode) { +// // this._setupRequireHook({ }); +// // +// // try { +// // compiledConfigurationModule = await this._runCompiledCode({}, compiledCode, filename); +// // } +// // catch (err) { +// // +// // } +// // finally { +// // this._removeRequireHook(); +// // } +// // +// // return compiledConfigurationModule.exports; +// // } +// // +// // return Promise.resolve(); +// // } +// } +// +// diff --git a/src/configuration/configuration-base.ts b/src/configuration/configuration-base.ts index 00fe9a51e0a..8532bfcf72f 100644 --- a/src/configuration/configuration-base.ts +++ b/src/configuration/configuration-base.ts @@ -24,7 +24,6 @@ import { Dictionary } from './interfaces'; import Extensions from './formats'; import { ReadConfigFileError } from '../errors/runtime'; import { RUNTIME_ERRORS } from '../errors/types'; -import { TypeScriptConfigurationFileCompiler } from '../compiler/test-file/formats/typescript/compiler'; const DEBUG_LOGGER = debug('testcafe:configuration'); @@ -248,9 +247,9 @@ export default class Configuration { delete require.cache[filePath]; // TODO: change require to import - const { TypeScriptConfigurationFileCompiler } = require('../compiler/test-file/formats/typescript/compiler'); + const TypeScriptFileCompiler = require('../compiler/test-file/formats/typescript/compiler'); - const compiler = new TypeScriptConfigurationFileCompiler(); + const compiler = new TypeScriptFileCompiler(); // const waitUntilCompiled = new Promise((resolve, reject) => { // compiler.on('module-compiled', (options:any) => { diff --git a/test/server/compiler-test.js b/test/server/compiler-test.js index 8a522c4c047..d809610e849 100644 --- a/test/server/compiler-test.js +++ b/test/server/compiler-test.js @@ -1039,7 +1039,9 @@ describe('Compiler', function () { }); }); - it('Incorrect callsite stack in error report if "import" is used (GH-1226)', function () { + it.only('Incorrect callsite stack in error report if "import" is used (GH-1226)', function () { + debugger; + return compile('test/server/data/test-suites/regression-gh-1226/testfile.js') .then(compiled => { return compiled.tests[0].fn(testRunMock); @@ -1052,6 +1054,8 @@ describe('Compiler', function () { const err = errList.items[0]; const stack = err.callsite.stackFrames.filter(createStackFilter(stackTraceLimit)); + debugger; + expect(stack.length).eql(8); const lastStackItem = stack.pop();