From 4dd47ec8ef3bb044340c0ab77bd895a33c586562 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Sat, 22 Nov 2025 12:34:09 +0100 Subject: [PATCH] test: Migrate tests to typescript --- package.json | 4 +- ...text-e2e-specs.js => context-e2e-specs.ts} | 24 ++++---- ...2e-specs.js => file-movement-e2e-specs.ts} | 35 +++++------ .../{log-e2e-specs.js => log-e2e-specs.ts} | 22 ++++--- ...inapi-e2e-specs.js => winapi-e2e-specs.ts} | 42 +++++++------ ...river-e2e-specs.js => driver-e2e-specs.ts} | 19 +++--- test/e2e/{helpers.js => helpers.ts} | 14 +++-- .../unit/{driver-specs.js => driver-specs.ts} | 59 +++++++++---------- .../{registry-specs.js => registry-specs.ts} | 15 ++--- tsconfig.json | 5 +- 10 files changed, 110 insertions(+), 129 deletions(-) rename test/e2e/commands/{context-e2e-specs.js => context-e2e-specs.ts} (50%) rename test/e2e/commands/{file-movement-e2e-specs.js => file-movement-e2e-specs.ts} (66%) rename test/e2e/commands/{log-e2e-specs.js => log-e2e-specs.ts} (58%) rename test/e2e/commands/{winapi-e2e-specs.js => winapi-e2e-specs.ts} (79%) rename test/e2e/{driver-e2e-specs.js => driver-e2e-specs.ts} (67%) rename test/e2e/{helpers.js => helpers.ts} (58%) rename test/unit/{driver-specs.js => driver-specs.ts} (60%) rename test/unit/{registry-specs.js => registry-specs.ts} (95%) diff --git a/package.json b/package.json index 2cc2ed8e..7215a9b0 100644 --- a/package.json +++ b/package.json @@ -67,8 +67,8 @@ "lint": "eslint .", "lint:fix": "npm run lint -- --fix", "prepare": "npm run build", - "test": "mocha --exit --timeout 1m \"./test/unit/**/*-specs.js\"", - "e2e-test": "mocha --exit --timeout 10m \"./test/e2e/**/*-specs.js\"" + "test": "mocha --exit --timeout 1m \"./test/unit/**/*-specs.ts\"", + "e2e-test": "mocha --exit --timeout 10m \"./test/e2e/**/*-specs.ts\"" }, "peerDependencies": { "appium": "^3.0.0-rc.2" diff --git a/test/e2e/commands/context-e2e-specs.js b/test/e2e/commands/context-e2e-specs.ts similarity index 50% rename from test/e2e/commands/context-e2e-specs.js rename to test/e2e/commands/context-e2e-specs.ts index 48300e6b..acca2589 100644 --- a/test/e2e/commands/context-e2e-specs.js +++ b/test/e2e/commands/context-e2e-specs.ts @@ -1,18 +1,16 @@ import { buildWdIoOptions } from '../helpers'; import { remote as wdio } from 'webdriverio'; +import type { Browser } from 'webdriverio'; +import { expect } from 'chai'; +import * as chai from 'chai'; +import * as chaiAsPromised from 'chai-as-promised'; + +chai.use(chaiAsPromised.default); describe('context', function () { - let chai; - /** @type {import('webdriverio').Browser} */ - let driver; + let driver: Browser | null = null; before(async function () { - chai = await import('chai'); - const chaiAsPromised = await import('chai-as-promised'); - - chai.should(); - chai.use(chaiAsPromised.default); - driver = await wdio(buildWdIoOptions('Root')); }); @@ -27,13 +25,13 @@ describe('context', function () { }); it('should support context api', async function () { - (await driver.getAppiumContext()).should.equal('NATIVE_APP'); - (await driver.getAppiumContexts()).should.eql(['NATIVE_APP']); - await driver.switchAppiumContext('NATIVE_APP'); + expect(await driver!.getAppiumContext()).to.equal('NATIVE_APP'); + expect(await driver!.getAppiumContexts()).to.eql(['NATIVE_APP']); + await driver!.switchAppiumContext('NATIVE_APP'); }); it('should throw an error if invalid context', async function () { - await driver.switchAppiumContext('INVALID_CONTEXT').should.rejected; + await expect(driver!.switchAppiumContext('INVALID_CONTEXT')).to.be.rejected; }); }); diff --git a/test/e2e/commands/file-movement-e2e-specs.js b/test/e2e/commands/file-movement-e2e-specs.ts similarity index 66% rename from test/e2e/commands/file-movement-e2e-specs.js rename to test/e2e/commands/file-movement-e2e-specs.ts index 7fede081..9e924e9f 100644 --- a/test/e2e/commands/file-movement-e2e-specs.js +++ b/test/e2e/commands/file-movement-e2e-specs.ts @@ -1,21 +1,18 @@ import { remote as wdio } from 'webdriverio'; +import type { Browser } from 'webdriverio'; import path from 'path'; import { tempDir, fs } from 'appium/support'; import { isAdmin } from '../../../lib/installer'; import { buildWdIoOptions } from '../helpers'; +import { expect } from 'chai'; +import * as chai from 'chai'; +import * as chaiAsPromised from 'chai-as-promised'; -describe('file movement', function () { - let driver; - let remotePath; - let chai; - - before(async function () { - chai = await import('chai'); - const chaiAsPromised = await import('chai-as-promised'); +chai.use(chaiAsPromised.default); - chai.should(); - chai.use(chaiAsPromised.default); - }); +describe('file movement', function () { + let driver: Browser | null = null; + let remotePath: string | null = null; beforeEach(async function () { if (process.env.CI || !await isAdmin()) { @@ -46,12 +43,12 @@ describe('file movement', function () { const base64Data = Buffer.from(stringData).toString('base64'); remotePath = await tempDir.path({ prefix: 'appium', suffix: '.tmp' }); - await driver.pushFile(remotePath, base64Data); + await driver!.pushFile(remotePath, base64Data); // get the file and its contents, to check - const remoteData64 = await driver.pullFile(remotePath); + const remoteData64 = await driver!.pullFile(remotePath); const remoteData = Buffer.from(remoteData64, 'base64').toString(); - remoteData.should.equal(stringData); + expect(remoteData).to.equal(stringData); }); it('should be able to delete a file', async function () { @@ -59,14 +56,14 @@ describe('file movement', function () { const base64Data = Buffer.from(stringData).toString('base64'); remotePath = await tempDir.path({ prefix: 'appium', suffix: '.tmp' }); - await driver.pushFile(remotePath, base64Data); + await driver!.pushFile(remotePath, base64Data); - const remoteData64 = await driver.pullFile(remotePath); + const remoteData64 = await driver!.pullFile(remotePath); const remoteData = Buffer.from(remoteData64, 'base64').toString(); - remoteData.should.equal(stringData); + expect(remoteData).to.equal(stringData); - await driver.execute('windows: deleteFile', { remotePath }); + await driver!.execute('windows: deleteFile', { remotePath }); - await driver.pullFile(remotePath).should.eventually.be.rejectedWith(/does not exist/); + await expect(driver!.pullFile(remotePath)).to.eventually.be.rejectedWith(/does not exist/); }); }); diff --git a/test/e2e/commands/log-e2e-specs.js b/test/e2e/commands/log-e2e-specs.ts similarity index 58% rename from test/e2e/commands/log-e2e-specs.js rename to test/e2e/commands/log-e2e-specs.ts index 350856a6..f56073bb 100644 --- a/test/e2e/commands/log-e2e-specs.js +++ b/test/e2e/commands/log-e2e-specs.ts @@ -1,18 +1,16 @@ import { buildWdIoOptions } from '../helpers'; import { remote as wdio } from 'webdriverio'; +import type { Browser } from 'webdriverio'; +import { expect } from 'chai'; +import * as chai from 'chai'; +import * as chaiAsPromised from 'chai-as-promised'; + +chai.use(chaiAsPromised.default); describe('log', function () { - let chai; - /** @type {import('webdriverio').Browser} */ - let driver; + let driver: Browser | null = null; before(async function () { - chai = await import('chai'); - const chaiAsPromised = await import('chai-as-promised'); - - chai.should(); - chai.use(chaiAsPromised.default); - driver = await wdio(buildWdIoOptions('Root')); }); @@ -27,14 +25,14 @@ describe('log', function () { }); it('should get the list of available logs', async function () { - (await driver.getLogTypes()).should.eql(['server']); + expect(await driver!.getLogTypes()).to.eql(['server']); }); it('should throw an error when an invalid type is given', async function () { - await driver.getLogs('INVALID_LOG_TYPE').should.be.rejected; + await expect(driver!.getLogs('INVALID_LOG_TYPE')).to.be.rejected; }); it('should get server logs', async function () { - (await driver.getLogs('server')).should.be.an('array'); + expect(await driver!.getLogs('server')).to.be.an('array'); }); }); diff --git a/test/e2e/commands/winapi-e2e-specs.js b/test/e2e/commands/winapi-e2e-specs.ts similarity index 79% rename from test/e2e/commands/winapi-e2e-specs.js rename to test/e2e/commands/winapi-e2e-specs.ts index 0ded6844..a49a2bdc 100644 --- a/test/e2e/commands/winapi-e2e-specs.js +++ b/test/e2e/commands/winapi-e2e-specs.ts @@ -1,18 +1,16 @@ import { buildWdIoOptions } from '../helpers'; import { remote as wdio } from 'webdriverio'; +import type { Browser } from 'webdriverio'; +import { expect } from 'chai'; +import * as chai from 'chai'; +import * as chaiAsPromised from 'chai-as-promised'; + +chai.use(chaiAsPromised.default); describe('winapi', function () { - let chai; - /** @type {import('webdriverio').Browser} */ - let driver; + let driver: Browser | null = null; before(async function () { - chai = await import('chai'); - const chaiAsPromised = await import('chai-as-promised'); - - chai.should(); - chai.use(chaiAsPromised.default); - driver = await wdio(buildWdIoOptions('Root')); }); @@ -28,7 +26,7 @@ describe('winapi', function () { describe('mouseClick', function () { it('performs single click with Shift+Ctrl', async function () { - await driver.execute('windows: click', { + await driver!.execute('windows: click', { x: 100, y: 100, modifierKeys: ['shift', 'ctrl'], @@ -36,7 +34,7 @@ describe('winapi', function () { }); it('performs long click', async function () { - await driver.execute('windows: click', { + await driver!.execute('windows: click', { x: 100, y: 100, durationMs: 500, @@ -44,7 +42,7 @@ describe('winapi', function () { }); it('performs double click', async function () { - await driver.execute('windows: click', { + await driver!.execute('windows: click', { x: 100, y: 100, times: 2, @@ -52,7 +50,7 @@ describe('winapi', function () { }); it('performs context click', async function () { - await driver.execute('windows: click', { + await driver!.execute('windows: click', { x: 100, y: 100, button: 'right', @@ -92,14 +90,14 @@ describe('winapi', function () { ]; for (const errData of errDatas) { - await driver.execute('windows: click', errData).should.be.rejected; + await expect(driver!.execute('windows: click', errData)).to.be.rejected; } }); }); describe('mouseScroll', function () { it('performs vertical scroll gesture with Ctrl+Alt depressed', async function () { - await driver.execute('windows: scroll', { + await driver!.execute('windows: scroll', { x: 600, y: 300, deltaY: 200, @@ -108,7 +106,7 @@ describe('winapi', function () { }); it('performs horizontal scroll gesture', async function () { - await driver.execute('windows: scroll', { + await driver!.execute('windows: scroll', { x: 600, y: 300, deltaX: -200, @@ -116,7 +114,7 @@ describe('winapi', function () { }); it('does nothing if zero delta is provided', async function () { - await driver.execute('windows: scroll', { + await driver!.execute('windows: scroll', { x: 100, y: 100, deltaY: 0, @@ -144,14 +142,14 @@ describe('winapi', function () { ]; for (const errData of errDatas) { - await driver.execute('windows: scroll', errData).should.be.rejected; + await expect(driver!.execute('windows: scroll', errData)).to.be.rejected; } }); }); describe('mouseClickAndDrag', function () { it('performs drag gesture with Ctrl+Shift depressed', async function () { - await driver.execute('windows: clickAndDrag', { + await driver!.execute('windows: clickAndDrag', { startX: 600, startY: 300, endX: 500, @@ -163,7 +161,7 @@ describe('winapi', function () { describe('windowsHover', function () { it('performs hover gesture with Ctrl+Shift depressed', async function () { - await driver.execute('windows: clickAndDrag', { + await driver!.execute('windows: clickAndDrag', { startX: 600, startY: 300, endX: 500, @@ -175,7 +173,7 @@ describe('winapi', function () { describe('keys', function () { it('performs complex key input', async function () { - await driver.execute('windows: keys', { + await driver!.execute('windows: keys', { actions: [ {virtualKeyCode: 0x10, down: true}, {pause: 100}, @@ -207,7 +205,7 @@ describe('winapi', function () { ]; for (const errData of errDatas) { - await driver.execute('windows: keys', {actions: [errData]}).should.be.rejected; + await expect(driver!.execute('windows: keys', {actions: [errData]})).to.be.rejected; } }); }); diff --git a/test/e2e/driver-e2e-specs.js b/test/e2e/driver-e2e-specs.ts similarity index 67% rename from test/e2e/driver-e2e-specs.js rename to test/e2e/driver-e2e-specs.ts index d2500a14..0b1c736e 100644 --- a/test/e2e/driver-e2e-specs.js +++ b/test/e2e/driver-e2e-specs.ts @@ -1,18 +1,15 @@ import { remote as wdio } from 'webdriverio'; +import type { Browser } from 'webdriverio'; import { isAdmin } from '../../lib/installer'; import { buildWdIoOptions } from './helpers'; +import { expect } from 'chai'; +import * as chai from 'chai'; +import * as chaiAsPromised from 'chai-as-promised'; -describe('Driver', function () { - let driver; - let chai; - - before(async function () { - chai = await import('chai'); - const chaiAsPromised = await import('chai-as-promised'); +chai.use(chaiAsPromised.default); - chai.should(); - chai.use(chaiAsPromised.default); - }); +describe('Driver', function () { + let driver: Browser | null = null; beforeEach(async function () { if (process.env.CI || !await isAdmin()) { @@ -33,6 +30,6 @@ describe('Driver', function () { }); it('should run a basic session using a real client', async function () { - await driver.source().should.eventually.be.not.empty; + await expect((driver as any).source()).to.eventually.be.not.empty; }); }); diff --git a/test/e2e/helpers.js b/test/e2e/helpers.ts similarity index 58% rename from test/e2e/helpers.js rename to test/e2e/helpers.ts index e5b670ed..2111260c 100644 --- a/test/e2e/helpers.js +++ b/test/e2e/helpers.ts @@ -1,13 +1,14 @@ -export const TEST_PORT = parseInt(process.env.APPIUM_TEST_SERVER_PORT || 4788, 10); -export const TEST_HOST = process.env.APPIUM_TEST_SERVER_HOST || '127.0.0.1'; +import type { remote } from 'webdriverio'; +export const TEST_PORT = parseInt(process.env.APPIUM_TEST_SERVER_PORT || '4788', 10); +export const TEST_HOST = process.env.APPIUM_TEST_SERVER_HOST || '127.0.0.1'; /** - * - * @param {string} app - * @returns {Record} + * Build WebdriverIO options for testing + * @param app - The app identifier + * @returns WebdriverIO options object */ -export function buildWdIoOptions(app) { +export function buildWdIoOptions(app: string): Parameters[0] { return { hostname: TEST_HOST, port: TEST_PORT, @@ -19,3 +20,4 @@ export function buildWdIoOptions(app) { } }; } + diff --git a/test/unit/driver-specs.js b/test/unit/driver-specs.ts similarity index 60% rename from test/unit/driver-specs.js rename to test/unit/driver-specs.ts index 10aa63a2..0d588e5f 100644 --- a/test/unit/driver-specs.js +++ b/test/unit/driver-specs.ts @@ -4,19 +4,16 @@ import { WindowsDriver } from '../../lib/driver'; import sinon from 'sinon'; import B from 'bluebird'; import { system } from 'appium/support'; +import { expect } from 'chai'; +import * as chai from 'chai'; +import * as chaiAsPromised from 'chai-as-promised'; +chai.use(chaiAsPromised.default); describe('driver.js', function () { - let isWindowsStub; - let chai; + let isWindowsStub: sinon.SinonStub; before(async function () { - chai = await import('chai'); - const chaiAsPromised = await import('chai-as-promised'); - - chai.should(); - chai.use(chaiAsPromised.default); - isWindowsStub = sinon.stub(system, 'isWindows').returns(true); }); after(function () { @@ -25,33 +22,33 @@ describe('driver.js', function () { describe('constructor', function () { it('calls BaseDriver constructor with opts', function () { - let driver = new WindowsDriver({ foo: 'bar' }); - driver.should.exist; - driver.opts.foo.should.equal('bar'); + const driver = new WindowsDriver({ foo: 'bar' } as any); + expect(driver).to.exist; + expect((driver.opts as any).foo).to.equal('bar'); }); }); describe('createSession', function () { it('should set sessionId', async function () { - let driver = new WindowsDriver({ app: 'myapp'}, false); + const driver = new WindowsDriver({ app: 'myapp'}, false); sinon.mock(driver).expects('startWinAppDriverSession') .once() .returns(B.resolve()); await driver.createSession(null, null, { alwaysMatch: { 'appium:cap': 'foo' }}); - driver.sessionId.should.exist; - driver.caps.cap.should.equal('foo'); + expect(driver.sessionId).to.exist; + expect((driver.caps as any).cap).to.equal('foo'); }); describe('context simulation', function () { it('should support context commands', async function () { - let driver = new WindowsDriver({ app: 'myapp'}, false); - (await driver.getCurrentContext()).should.equal('NATIVE_APP'); - (await driver.getContexts()).should.eql(['NATIVE_APP']); + const driver = new WindowsDriver({ app: 'myapp'}, false); + expect(await driver.getCurrentContext()).to.equal('NATIVE_APP'); + expect(await driver.getContexts()).to.eql(['NATIVE_APP']); await driver.setContext('NATIVE_APP'); }); it('should throw an error if invalid context', async function () { - let driver = new WindowsDriver({ app: 'myapp'}, false); - await driver.setContext('INVALID_CONTEXT').should.rejected; + const driver = new WindowsDriver({ app: 'myapp'}, false); + await expect(driver.setContext('INVALID_CONTEXT')).to.be.rejected; }); }); @@ -68,46 +65,46 @@ describe('driver.js', function () { }); describe('proxying', function () { - let driver; + let driver: WindowsDriver; before(function () { driver = new WindowsDriver({}, false); driver.sessionId = 'abc'; }); describe('#proxyActive', function () { it('should exist', function () { - driver.proxyActive.should.be.an.instanceof(Function); + expect(driver.proxyActive).to.be.an.instanceof(Function); }); it('should return false by default', function () { - driver.proxyActive('abc').should.be.false; + expect(driver.proxyActive('abc')).to.be.false; }); it('should throw an error if session id is wrong', function () { - (() => { driver.proxyActive('aaa'); }).should.throw; + expect(() => { driver.proxyActive('aaa'); }).to.throw; }); }); describe('#getProxyAvoidList', function () { it('should exist', function () { - driver.getProxyAvoidList.should.be.an.instanceof(Function); + expect(driver.getProxyAvoidList).to.be.an.instanceof(Function); }); it('should return jwpProxyAvoid array', function () { - let avoidList = driver.getProxyAvoidList('abc'); - avoidList.should.be.an.instanceof(Array); - avoidList.should.eql(driver.jwpProxyAvoid); + const avoidList = (driver.getProxyAvoidList as any)('abc'); + expect(avoidList).to.be.an.instanceof(Array); + expect(avoidList).to.eql(driver.jwpProxyAvoid); }); it('should throw an error if session id is wrong', function () { - (() => { driver.getProxyAvoidList('aaa'); }).should.throw; + expect(() => { (driver.getProxyAvoidList as any)('aaa'); }).to.throw; }); }); describe('#canProxy', function () { it('should exist', function () { - driver.canProxy.should.be.an.instanceof(Function); + expect(driver.canProxy).to.be.an.instanceof(Function); }); it('should return true', function () { - driver.canProxy('abc').should.be.true; + expect((driver.canProxy as any)('abc')).to.be.true; }); it('should throw an error if session id is wrong', function () { - (() => { driver.canProxy('aaa'); }).should.throw; + expect(() => { (driver.canProxy as any)('aaa'); }).to.throw; }); }); }); diff --git a/test/unit/registry-specs.js b/test/unit/registry-specs.ts similarity index 95% rename from test/unit/registry-specs.js rename to test/unit/registry-specs.ts index 9b336bd9..4b1a0d15 100644 --- a/test/unit/registry-specs.js +++ b/test/unit/registry-specs.ts @@ -1,14 +1,7 @@ import { parseRegQueryOutput } from '../../lib/registry'; +import { expect } from 'chai'; describe('registry', function () { - let chai; - - before(async function () { - chai = await import('chai'); - - chai.should(); - }); - it('should parse reg query output', function () { const output = ` HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\AddressBook @@ -94,10 +87,10 @@ HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{29 `; const result = parseRegQueryOutput(output); - Boolean(result.find( + expect(Boolean(result.find( ({root, key, type, value}) => root === 'HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{29DA7679-80B6-452A-B264-349BAEE7CC0E}' && key === 'DisplayName' && type === 'REG_SZ' && value === 'Windows Application Driver' - )).should.be.true; + ))).to.be.true; }); it('should return empty array if no matches found', function () { const output = ` @@ -106,6 +99,6 @@ HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Add HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\DirectDrawEx `; const result = parseRegQueryOutput(output); - result.length.should.be.eql(0); + expect(result.length).to.eql(0); }); }); diff --git a/tsconfig.json b/tsconfig.json index 33d83ef4..f02a04d2 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,11 +4,12 @@ "compilerOptions": { "strict": false, // TODO: make this flag true "outDir": "build", - "types": ["node"], + "types": ["node", "mocha"], "checkJs": true }, "include": [ "index.js", - "lib" + "lib", + "test" ] }