diff --git a/packages/side-runtime/src/__tests__/__snapshots__/playback.spec.js.snap b/packages/side-runtime/src/__tests__/__snapshots__/playback.spec.js.snap deleted file mode 100644 index 2227627a3..000000000 --- a/packages/side-runtime/src/__tests__/__snapshots__/playback.spec.js.snap +++ /dev/null @@ -1,567 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Playback Event emitting Control Flow forEach 1`] = ` -Array [ - Object { - "collection": Array [ - "a", - "b", - "c", - ], - "commandId": "asdf0", - "index": 0, - "iterator": "a", - "type": "loop", - }, - Object { - "collection": Array [ - "a", - "b", - "c", - ], - "commandId": "asdf0", - "index": 1, - "iterator": "b", - "type": "loop", - }, - Object { - "collection": Array [ - "a", - "b", - "c", - ], - "commandId": "asdf0", - "index": 2, - "iterator": "c", - "type": "loop", - }, - Object { - "commandId": "asdf0", - "end": true, - "type": "loop", - }, -] -`; - -exports[`Playback Playback test queue should play a nested test case 1`] = ` -Array [ - Object { - "callstackIndex": 0, - "id": 1, - "message": undefined, - "state": "executing", - }, - Object { - "callstackIndex": 0, - "id": 1, - "message": undefined, - "state": "passed", - }, - Object { - "callstackIndex": 0, - "id": 2, - "message": undefined, - "state": "executing", - }, - Object { - "callstackIndex": 0, - "id": 2, - "message": undefined, - "state": "passed", - }, - Object { - "callstackIndex": 1, - "id": 4, - "message": undefined, - "state": "executing", - }, - Object { - "callstackIndex": 1, - "id": 4, - "message": undefined, - "state": "passed", - }, - Object { - "callstackIndex": 1, - "id": 5, - "message": undefined, - "state": "executing", - }, - Object { - "callstackIndex": 1, - "id": 5, - "message": undefined, - "state": "passed", - }, - Object { - "callstackIndex": 1, - "id": 6, - "message": undefined, - "state": "executing", - }, - Object { - "callstackIndex": 1, - "id": 6, - "message": undefined, - "state": "passed", - }, - Object { - "callstackIndex": 0, - "id": 3, - "message": undefined, - "state": "executing", - }, - Object { - "callstackIndex": 0, - "id": 3, - "message": undefined, - "state": "passed", - }, -] -`; - -exports[`Playback abort should abort a paused test 1`] = ` -Array [ - Object { - "callstackIndex": 0, - "id": 1, - "message": undefined, - "state": "executing", - }, - Object { - "callstackIndex": 0, - "id": 1, - "message": undefined, - "state": "passed", - }, - Object { - "callstackIndex": 0, - "id": 2, - "message": undefined, - "state": "executing", - }, - Object { - "callstackIndex": 0, - "id": 2, - "message": undefined, - "state": "passed", - }, - Object { - "callstackIndex": 0, - "id": 3, - "message": undefined, - "state": "executing", - }, - Object { - "callstackIndex": 0, - "id": 3, - "message": undefined, - "state": "executing", - }, - Object { - "callstackIndex": 0, - "id": 3, - "message": "playback is dead", - "state": "errored", - }, -] -`; - -exports[`Playback abort should abort a test 1`] = ` -Array [ - Object { - "callstackIndex": 0, - "id": 1, - "message": undefined, - "state": "executing", - }, - Object { - "callstackIndex": 0, - "id": 1, - "message": undefined, - "state": "passed", - }, - Object { - "callstackIndex": 0, - "id": 2, - "message": undefined, - "state": "executing", - }, - Object { - "callstackIndex": 0, - "id": 2, - "message": "playback is dead", - "state": "errored", - }, -] -`; - -exports[`Playback abort should abort a test after attempting to stop 1`] = ` -Array [ - Object { - "callstackIndex": 0, - "id": 1, - "message": undefined, - "state": "executing", - }, - Object { - "callstackIndex": 0, - "id": 1, - "message": undefined, - "state": "passed", - }, - Object { - "callstackIndex": 0, - "id": 2, - "message": undefined, - "state": "executing", - }, - Object { - "callstackIndex": 0, - "id": 2, - "message": "playback is dead", - "state": "errored", - }, -] -`; - -exports[`Playback ignore breakpoints should ignore breakpoints 1`] = ` -Array [ - Object { - "callstackIndex": 0, - "id": 1, - "message": undefined, - "state": "executing", - }, - Object { - "callstackIndex": 0, - "id": 1, - "message": undefined, - "state": "passed", - }, - Object { - "callstackIndex": 0, - "id": 2, - "message": undefined, - "state": "executing", - }, - Object { - "callstackIndex": 0, - "id": 2, - "message": undefined, - "state": "passed", - }, - Object { - "callstackIndex": 0, - "id": 3, - "message": undefined, - "state": "executing", - }, - Object { - "callstackIndex": 0, - "id": 3, - "message": undefined, - "state": "passed", - }, -] -`; - -exports[`Playback pause on exceptions should pause for every type of error 1`] = ` -Array [ - Object { - "callstackIndex": 0, - "id": 1, - "message": undefined, - "state": "executing", - }, - Object { - "callstackIndex": 0, - "id": 1, - "message": "error", - "state": "errored", - }, - Object { - "callstackIndex": 0, - "id": 1, - "message": undefined, - "state": "executing", - }, - Object { - "callstackIndex": 0, - "id": 1, - "message": undefined, - "state": "passed", - }, - Object { - "callstackIndex": 0, - "id": 2, - "message": undefined, - "state": "executing", - }, - Object { - "callstackIndex": 0, - "id": 2, - "message": "error in verify", - "state": "failed", - }, - Object { - "callstackIndex": 0, - "id": 2, - "message": undefined, - "state": "executing", - }, - Object { - "callstackIndex": 0, - "id": 2, - "message": undefined, - "state": "passed", - }, - Object { - "callstackIndex": 0, - "id": 3, - "message": undefined, - "state": "executing", - }, - Object { - "callstackIndex": 0, - "id": 3, - "message": "error in assert", - "state": "failed", - }, - Object { - "callstackIndex": 0, - "id": 3, - "message": undefined, - "state": "executing", - }, - Object { - "callstackIndex": 0, - "id": 3, - "message": undefined, - "state": "passed", - }, -] -`; - -exports[`Playback pause on exceptions should pause until the command is fixed 1`] = ` -Array [ - Object { - "callstackIndex": 0, - "id": 1, - "message": undefined, - "state": "executing", - }, - Object { - "callstackIndex": 0, - "id": 1, - "message": "error", - "state": "errored", - }, - Object { - "callstackIndex": 0, - "id": 1, - "message": undefined, - "state": "executing", - }, - Object { - "callstackIndex": 0, - "id": 1, - "message": "error", - "state": "errored", - }, - Object { - "callstackIndex": 0, - "id": 1, - "message": undefined, - "state": "executing", - }, - Object { - "callstackIndex": 0, - "id": 1, - "message": undefined, - "state": "passed", - }, -] -`; - -exports[`Playback resume resume after hitting a breakpoint 1`] = ` -Array [ - Object { - "callstackIndex": 0, - "id": 1, - "message": undefined, - "state": "executing", - }, - Object { - "callstackIndex": 0, - "id": 1, - "message": undefined, - "state": "passed", - }, - Object { - "callstackIndex": 0, - "id": 2, - "message": undefined, - "state": "executing", - }, - Object { - "callstackIndex": 0, - "id": 2, - "message": undefined, - "state": "executing", - }, - Object { - "callstackIndex": 0, - "id": 2, - "message": undefined, - "state": "passed", - }, - Object { - "callstackIndex": 0, - "id": 3, - "message": undefined, - "state": "executing", - }, - Object { - "callstackIndex": 0, - "id": 3, - "message": undefined, - "state": "passed", - }, -] -`; - -exports[`Playback resume should resume a paused test 1`] = ` -Array [ - Object { - "callstackIndex": 0, - "id": 1, - "message": undefined, - "state": "executing", - }, - Object { - "callstackIndex": 0, - "id": 1, - "message": undefined, - "state": "passed", - }, - Object { - "callstackIndex": 0, - "id": 2, - "message": undefined, - "state": "executing", - }, - Object { - "callstackIndex": 0, - "id": 2, - "message": undefined, - "state": "passed", - }, - Object { - "callstackIndex": 0, - "id": 3, - "message": undefined, - "state": "executing", - }, - Object { - "callstackIndex": 0, - "id": 3, - "message": undefined, - "state": "executing", - }, - Object { - "callstackIndex": 0, - "id": 3, - "message": undefined, - "state": "passed", - }, -] -`; - -exports[`Playback stop should stop a paused test 1`] = ` -Array [ - Object { - "callstackIndex": 0, - "id": 1, - "message": undefined, - "state": "executing", - }, - Object { - "callstackIndex": 0, - "id": 1, - "message": undefined, - "state": "passed", - }, - Object { - "callstackIndex": 0, - "id": 2, - "message": undefined, - "state": "executing", - }, - Object { - "callstackIndex": 0, - "id": 2, - "message": undefined, - "state": "passed", - }, - Object { - "callstackIndex": 0, - "id": 3, - "message": undefined, - "state": "executing", - }, - Object { - "callstackIndex": 0, - "id": 3, - "message": undefined, - "state": "executing", - }, - Object { - "callstackIndex": 0, - "id": 3, - "message": "Playback stopped", - "state": "errored", - }, -] -`; - -exports[`Playback stop should stop a test 1`] = ` -Array [ - Object { - "callstackIndex": 0, - "id": 1, - "message": undefined, - "state": "executing", - }, - Object { - "callstackIndex": 0, - "id": 1, - "message": undefined, - "state": "passed", - }, - Object { - "callstackIndex": 0, - "id": 2, - "message": undefined, - "state": "executing", - }, - Object { - "callstackIndex": 0, - "id": 2, - "message": undefined, - "state": "passed", - }, - Object { - "callstackIndex": 0, - "id": 3, - "message": undefined, - "state": "executing", - }, - Object { - "callstackIndex": 0, - "id": 3, - "message": "Playback stopped", - "state": "errored", - }, -] -`; diff --git a/packages/side-runtime/src/__tests__/__snapshots__/recording-syncronizer.spec.js.snap b/packages/side-runtime/src/__tests__/__snapshots__/recording-syncronizer.spec.js.snap deleted file mode 100644 index 5f6ce879f..000000000 --- a/packages/side-runtime/src/__tests__/__snapshots__/recording-syncronizer.spec.js.snap +++ /dev/null @@ -1,11 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`recording syncronizer should log if tried to switch to a window that has no handle 1`] = `"Tried to switch to window handle 1 without it appearing first (onWindowAppeared was not called for it)"`; - -exports[`recording syncronizer should sync a new window when called if onWindowSwitched was not called for it 1`] = `"return window.__side.setWindowHandle(\\"first\\", \\"default\\")"`; - -exports[`recording syncronizer should sync a new window when switching to it 1`] = `"return window.__side.setWindowHandle(\\"first\\", \\"default\\")"`; - -exports[`recording syncronizer should sync the active context 1`] = `"return window.__side.setActiveContext(\\"default\\")"`; - -exports[`recording syncronizer should sync the current window 1`] = `"return window.__side.setWindowHandle(\\"first\\", \\"default\\")"`; diff --git a/packages/side-runtime/src/__tests__/playback.spec.ts b/packages/side-runtime/src/__tests__/playback.spec.ts index 1d2b92b2e..423a676a9 100644 --- a/packages/side-runtime/src/__tests__/playback.spec.ts +++ b/packages/side-runtime/src/__tests__/playback.spec.ts @@ -25,8 +25,7 @@ import Playback, { import { AssertionError, VerificationError } from '../errors' import Variables from '../variables' import { TestShape } from '@seleniumhq/side-model' - -import FakeExecutor from './util/FakeExecutor' +import FakeExecutor from './util/JestFakeExecutor' describe('Playback', () => { describe('Event emitting', () => { diff --git a/packages/side-runtime/src/__tests__/util/FakeExecutor.ts b/packages/side-runtime/src/__tests__/util/FakeExecutor.ts index a464adc47..f470130ad 100644 --- a/packages/side-runtime/src/__tests__/util/FakeExecutor.ts +++ b/packages/side-runtime/src/__tests__/util/FakeExecutor.ts @@ -18,7 +18,7 @@ import { CommandShape } from '@seleniumhq/side-model' import Variables from '../../variables' -export default class FakeExecutor { +class FakeExecutor { customCommands: { [key: string]: () => void } = {} implicitWait = 50 initialized: boolean = false @@ -29,15 +29,15 @@ export default class FakeExecutor { return this } - init = jest.fn(({ variables }: { variables: Variables }) => { + init({ variables }: { variables: Variables }) { // this can be async this.variables = variables this.initialized = true - }) + } - executeHook = jest.fn() + executeHook() {} - name = jest.fn((command: string) => { + name(command: string) { if (!command) { return 'skip' } @@ -49,35 +49,33 @@ export default class FakeExecutor { throw new Error(`Unknown command ${command}`) } return func - }) + } - cancel = jest.fn() - cleanup = jest.fn() - kill = jest.fn(async () => { + cancel() {} + cleanup() {} + async kill() { this.killed = true - }) - - beforeCommand = jest.fn(async (_commandObject: CommandShape) => { + } + async beforeCommand(_commandObject: CommandShape) { if (!this.initialized) throw new Error('executor is dead') if (this.killed) throw new Error('playback is dead') - }) - - afterCommand = jest.fn((_commandObject: CommandShape) => { + } + afterCommand(_commandObject: CommandShape) { if (!this.initialized) throw new Error('executor is dead') if (this.killed) throw new Error('playback is dead') - }) - - doAssert = jest.fn() - doAssertText = jest.fn() - doPause = jest.fn( - (timeout = 0) => - new Promise((res) => { - setTimeout(res, Number(timeout)) - }) - ) - doOpen = jest.fn() - doVerify = jest.fn() - doVerifyText = jest.fn() - doFake = jest.fn() - evaluateConditional = jest.fn() + } + doAssert() {} + doAssertText() {} + doPause(timeout = 0) { + return new Promise((res) => { + setTimeout(res, Number(timeout)) + }) + } + doOpen() {} + doVerify() {} + doVerifyText() {} + doFake(..._args: any[]) {} + evaluateConditional() {} } + +export default FakeExecutor diff --git a/packages/side-runtime/src/__tests__/util/JestFakeExecutor.ts b/packages/side-runtime/src/__tests__/util/JestFakeExecutor.ts new file mode 100644 index 000000000..a464adc47 --- /dev/null +++ b/packages/side-runtime/src/__tests__/util/JestFakeExecutor.ts @@ -0,0 +1,83 @@ +// Licensed to the Software Freedom Conservancy (SFC) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The SFC licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +import { CommandShape } from '@seleniumhq/side-model' +import Variables from '../../variables' + +export default class FakeExecutor { + customCommands: { [key: string]: () => void } = {} + implicitWait = 50 + initialized: boolean = false + killed: boolean = false + variables: Variables = new Variables() + + constructor(..._args: any[]) { + return this + } + + init = jest.fn(({ variables }: { variables: Variables }) => { + // this can be async + this.variables = variables + this.initialized = true + }) + + executeHook = jest.fn() + + name = jest.fn((command: string) => { + if (!command) { + return 'skip' + } + + const upperCase = command.charAt(0).toUpperCase() + command.slice(1) + const func = 'do' + upperCase + // @ts-expect-error idk what to do here + if (!this[func]) { + throw new Error(`Unknown command ${command}`) + } + return func + }) + + cancel = jest.fn() + cleanup = jest.fn() + kill = jest.fn(async () => { + this.killed = true + }) + + beforeCommand = jest.fn(async (_commandObject: CommandShape) => { + if (!this.initialized) throw new Error('executor is dead') + if (this.killed) throw new Error('playback is dead') + }) + + afterCommand = jest.fn((_commandObject: CommandShape) => { + if (!this.initialized) throw new Error('executor is dead') + if (this.killed) throw new Error('playback is dead') + }) + + doAssert = jest.fn() + doAssertText = jest.fn() + doPause = jest.fn( + (timeout = 0) => + new Promise((res) => { + setTimeout(res, Number(timeout)) + }) + ) + doOpen = jest.fn() + doVerify = jest.fn() + doVerifyText = jest.fn() + doFake = jest.fn() + evaluateConditional = jest.fn() +} diff --git a/packages/side-runtime/src/preprocessors.ts b/packages/side-runtime/src/preprocessors.ts index 8af35dff0..2fb4c4b42 100644 --- a/packages/side-runtime/src/preprocessors.ts +++ b/packages/side-runtime/src/preprocessors.ts @@ -17,6 +17,7 @@ import { Fn } from '@seleniumhq/side-commons' import Variables from './variables' +import type WebDriverExecutor from './webdriver' const nbsp = String.fromCharCode(160) @@ -30,41 +31,49 @@ export function composePreprocessors(...args: any[]) { if (params.length === 0) { return func } else if (params.length === 1) { - return function preprocess(target: any) { - // @ts-expect-error - return func.call(this, runPreprocessor(params[0], target, this.variables)) + return function preprocess( + this: WebDriverExecutor, + target: any, + ...args: any[] + ) { + return func.call( + this, + runPreprocessor(params[0], target, this.variables), + ...args + ) } } else if (params.length === 2) { - return function preprocess(target: any, value: any) { + return function preprocess( + this: WebDriverExecutor, + target: any, + value: any, + ...args: any[] + ) { return func.call( - // @ts-expect-error this, - // @ts-expect-error runPreprocessor(params[0], target, this.variables), - // @ts-expect-error - runPreprocessor(params[1], value, this.variables) + runPreprocessor(params[1], value, this.variables), + ...args ) } } else { - return function preprocess(target: any, value: any, options: any) { + return function preprocess( + this: WebDriverExecutor, + target: any, + value: any, + options: any + ) { if (!options) { return func.call( - // @ts-expect-error this, - // @ts-expect-error runPreprocessor(params[0], target, this.variables), - // @ts-expect-error runPreprocessor(params[1], value, this.variables) ) } return func.call( - // @ts-expect-error this, - // @ts-expect-error runPreprocessor(params[0], target, this.variables), - // @ts-expect-error runPreprocessor(params[1], value, this.variables), - // @ts-expect-error preprocessObject(params[2], options, this.variables) ) }