diff --git a/.mocharc.js b/.mocharc.js deleted file mode 100644 index 3136ed9..0000000 --- a/.mocharc.js +++ /dev/null @@ -1,6 +0,0 @@ -module.exports = { - require: ['ts-node/register'], - timeout: 60000, - exit: true, - recursive: true -}; diff --git a/package.json b/package.json index 30af3e1..278a71f 100644 --- a/package.json +++ b/package.json @@ -47,8 +47,8 @@ "format": "prettier -w ./lib ./test", "format:check": "prettier --check ./lib ./test", "prepare": "npm run build", - "test": "mocha --exit --timeout 1m \"./test/unit/**/*-specs.ts\"", - "e2e-test": "mocha --exit --timeout 5m \"./test/e2e/**/*-specs.ts\"" + "test": "node --test --test-timeout=60000 \"./build/test/unit/**/*.spec.js\"", + "e2e-test": "node --test --test-force-exit --test-concurrency=1 --test-timeout=300000 \"./build/test/e2e/**/*.spec.js\"" }, "prettier": { "bracketSpacing": false, @@ -61,16 +61,10 @@ "@appium/types": "^1.0.0-rc.1", "@semantic-release/changelog": "^6.0.1", "@semantic-release/git": "^10.0.1", - "@types/chai": "^5.2.3", - "@types/mocha": "^10.0.1", "@types/node": "^25.0.3", - "chai": "^6.0.0", - "chai-as-promised": "^8.0.0", "conventional-changelog-conventionalcommits": "^9.0.0", - "mocha": "^11.0.1", "prettier": "^3.0.0", "semantic-release": "^25.0.2", - "ts-node": "^10.9.1", "typescript": "^6.0.2" } } diff --git a/test/e2e/sudo-execution-specs.ts b/test/e2e/sudo-execution.spec.ts similarity index 67% rename from test/e2e/sudo-execution-specs.ts rename to test/e2e/sudo-execution.spec.ts index 8a86b99..522c910 100644 --- a/test/e2e/sudo-execution-specs.ts +++ b/test/e2e/sudo-execution.spec.ts @@ -1,8 +1,9 @@ -import {expect} from 'chai'; +import assert from 'node:assert/strict'; import {Devicectl} from '../../lib/devicectl'; +import {describe, it, type TestContext} from 'node:test'; describe('manual sudo execution e2e', function () { - it('runs devicectl as original non-root user under sudo', async function () { + it('runs devicectl as original non-root user under sudo', async function (ctx: TestContext) { if ( process.env.CI || process.platform !== 'darwin' || @@ -11,8 +12,7 @@ describe('manual sudo execution e2e', function () { !process.env.SUDO_UID || !process.env.SUDO_GID ) { - this.skip(); - return; + return ctx.skip(); } const devicectl = new Devicectl(''); @@ -21,7 +21,7 @@ describe('manual sudo execution e2e', function () { asJson: true, }); - expect(result.stdout).to.be.a('string'); - expect(result.stdout.length).to.be.greaterThan(0); + assert.strictEqual(typeof result.stdout, 'string'); + assert.ok(result.stdout.length > 0); }); }); diff --git a/test/unit/devicectl-specs.ts b/test/unit/devicectl.spec.ts similarity index 63% rename from test/unit/devicectl-specs.ts rename to test/unit/devicectl.spec.ts index b506c10..f5af0d5 100644 --- a/test/unit/devicectl-specs.ts +++ b/test/unit/devicectl.spec.ts @@ -1,6 +1,7 @@ -import {expect} from 'chai'; +import assert from 'node:assert/strict'; import {Devicectl} from '../../lib/devicectl'; import {appUrlToFilesystemPath, escapeProcessFilterValue} from '../../lib/mixins/process'; +import {describe, it, beforeEach} from 'node:test'; describe('Devicectl', function () { let devicectl: Devicectl; @@ -11,25 +12,26 @@ describe('Devicectl', function () { describe('constructor', function () { it('should create a Devicectl instance with the provided UDID and default logger', function () { - expect(devicectl.udid).to.equal('test-device-udid'); + assert.strictEqual(devicectl.udid, 'test-device-udid'); }); it('should allow disabling non-root sudo execution in constructor options', function () { const localDevicectl = new Devicectl('test-device-udid', {preferNonRootWhenSudo: false}); - expect((localDevicectl as any).preferNonRootWhenSudo).to.equal(false); + assert.strictEqual((localDevicectl as any).preferNonRootWhenSudo, false); }); }); describe('sudo behavior', function () { it('should cache sudo user identity when available', function () { const localDevicectl = new Devicectl('test-device-udid'); - expect( + assert.strictEqual( (localDevicectl as any).sudoUser === null || !!(localDevicectl as any).sudoUser, - ).to.equal(true); + true, + ); }); it('should keep constructor default for runAsNonRootWhenSudo behavior', function () { - expect((devicectl as any).preferNonRootWhenSudo).to.equal(true); + assert.strictEqual((devicectl as any).preferNonRootWhenSudo, true); }); }); @@ -37,94 +39,97 @@ describe('Devicectl', function () { it('should throw an error when command execution fails', async function () { // This test would need to be mocked in a real implementation // For now, we'll just test that the method exists - expect(devicectl.execute).to.be.a('function'); + assert.strictEqual(typeof devicectl.execute, 'function'); }); }); describe('sendMemoryWarning', function () { it('should be a function', function () { - expect(devicectl.sendMemoryWarning).to.be.a('function'); + assert.strictEqual(typeof devicectl.sendMemoryWarning, 'function'); }); }); describe('listProcesses', function () { it('should be a function', function () { - expect(devicectl.listProcesses).to.be.a('function'); + assert.strictEqual(typeof devicectl.listProcesses, 'function'); }); }); describe('listFiles', function () { it('should be a function', function () { - expect(devicectl.listFiles).to.be.a('function'); + assert.strictEqual(typeof devicectl.listFiles, 'function'); }); }); describe('pullFile', function () { it('should be a function', function () { - expect(devicectl.pullFile).to.be.a('function'); + assert.strictEqual(typeof devicectl.pullFile, 'function'); }); }); describe('sendSignalToProcess', function () { it('should be a function', function () { - expect(devicectl.sendSignalToProcess).to.be.a('function'); + assert.strictEqual(typeof devicectl.sendSignalToProcess, 'function'); }); }); describe('listApps', function () { it('should be a function', function () { - expect(devicectl.listApps).to.be.a('function'); + assert.strictEqual(typeof devicectl.listApps, 'function'); }); }); describe('launchApp', function () { it('should be a function', function () { - expect(devicectl.launchApp).to.be.a('function'); + assert.strictEqual(typeof devicectl.launchApp, 'function'); }); }); describe('terminateApp', function () { it('should be a function', function () { - expect(devicectl.terminateApp).to.be.a('function'); + assert.strictEqual(typeof devicectl.terminateApp, 'function'); }); describe('appUrlToFilesystemPath', function () { it('should strip the file:// prefix', function () { - expect(appUrlToFilesystemPath('file:///path/to/App.app')).to.equal('/path/to/App.app'); + assert.strictEqual(appUrlToFilesystemPath('file:///path/to/App.app'), '/path/to/App.app'); }); it('should strip a trailing slash', function () { - expect(appUrlToFilesystemPath('/path/to/App.app/')).to.equal('/path/to/App.app'); + assert.strictEqual(appUrlToFilesystemPath('/path/to/App.app/'), '/path/to/App.app'); }); it('should strip both the file:// prefix and trailing slash', function () { - expect(appUrlToFilesystemPath('file:///private/var/App.app/')).to.equal( + assert.strictEqual( + appUrlToFilesystemPath('file:///private/var/App.app/'), '/private/var/App.app', ); }); it('should leave paths without a file:// prefix or trailing slash unchanged', function () { - expect(appUrlToFilesystemPath('/path/to/App.app')).to.equal('/path/to/App.app'); + assert.strictEqual(appUrlToFilesystemPath('/path/to/App.app'), '/path/to/App.app'); }); }); describe('escapeProcessFilterValue', function () { it('should leave values without special characters unchanged', function () { - expect(escapeProcessFilterValue('/path/to/App.app')).to.equal('/path/to/App.app'); + assert.strictEqual(escapeProcessFilterValue('/path/to/App.app'), '/path/to/App.app'); }); it('should escape backslashes', function () { - expect(escapeProcessFilterValue(String.raw`path\with\slashes`)).to.equal( + assert.strictEqual( + escapeProcessFilterValue(String.raw`path\with\slashes`), String.raw`path\\with\\slashes`, ); }); it('should escape double quotes', function () { - expect(escapeProcessFilterValue('path"with"quotes')).to.equal('path\\"with\\"quotes'); + assert.strictEqual(escapeProcessFilterValue('path"with"quotes'), 'path\\"with\\"quotes'); }); it('should escape backslashes and double quotes together', function () { - expect(escapeProcessFilterValue(String.raw`path\"mixed`)).to.equal( + assert.strictEqual( + escapeProcessFilterValue(String.raw`path\"mixed`), String.raw`path\\\"mixed`, ); }); @@ -133,7 +138,7 @@ describe('Devicectl', function () { describe('listDevices', function () { it('should be a function', function () { - expect(devicectl.listDevices).to.be.a('function'); + assert.strictEqual(typeof devicectl.listDevices, 'function'); }); }); }); diff --git a/tsconfig.json b/tsconfig.json index 7f46171..20e6305 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -5,14 +5,8 @@ "outDir": "build", "checkJs": true, "esModuleInterop": true, - "types": ["node", "mocha"], + "types": ["node"], "strict": true }, - "ts-node": { - "transpileOnly": true, - "compilerOptions": { - "rootDir": "." - } - }, "include": ["lib", "test"] }