From 3e1ada27f156e71b9a7c38fda11b3ac1c59183f9 Mon Sep 17 00:00:00 2001 From: Anuj Vishwakarma Date: Tue, 25 Aug 2026 17:01:33 +0530 Subject: [PATCH] Revert "ESM update and Vitest switchover (#98)" This reverts commit f0a6d9ebb6a12c0cdf7c1aa8308885c79436adfd. --- .gitignore | 1 - bin/{run.js => run} | 8 +- eslint.config.js | 16 +--- package.json | 25 ++++-- src/certificate.js | 14 +-- src/commands/certificate/fingerprint.js | 11 ++- src/commands/certificate/generate.js | 11 ++- src/commands/certificate/index.js | 4 +- src/commands/certificate/verify.js | 11 ++- test/commands/certificate/fingerprint.test.js | 85 +++++++------------ test/commands/certificate/generate.test.js | 14 +-- test/commands/certificate/index.test.js | 37 -------- test/commands/certificate/verify.test.js | 29 +++---- test/jest.setup.js | 9 ++ test/vitest.setup.js | 20 ----- vitest.config.js | 28 ------ 16 files changed, 112 insertions(+), 211 deletions(-) rename bin/{run.js => run} (82%) delete mode 100644 test/commands/certificate/index.test.js create mode 100644 test/jest.setup.js delete mode 100644 test/vitest.setup.js delete mode 100644 vitest.config.js diff --git a/.gitignore b/.gitignore index 4efe13f..379644b 100644 --- a/.gitignore +++ b/.gitignore @@ -13,4 +13,3 @@ coverage/ junit.xml package-lock.json .claude -.cursor/ diff --git a/bin/run.js b/bin/run similarity index 82% rename from bin/run.js rename to bin/run index 1d416d6..d4ea366 100755 --- a/bin/run.js +++ b/bin/run @@ -11,8 +11,8 @@ OF ANY KIND, either express or implied. See the License for the specific languag governing permissions and limitations under the License. */ -import { run, handle, flush } from '@oclif/core' +const oclif = require('@oclif/core') -await run() - .then(flush) - .catch(handle) +oclif.run() + .then(require('@oclif/core/flush')) + .catch(require('@oclif/core/handle')) diff --git a/eslint.config.js b/eslint.config.js index 088dcf0..e30b081 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -10,20 +10,12 @@ OF ANY KIND, either express or implied. See the License for the specific languag governing permissions and limitations under the License. */ -import aioLibConfig from '@adobe/eslint-config-aio-lib-config' -import vitest from '@vitest/eslint-plugin' +const aioLibConfig = require('@adobe/eslint-config-aio-lib-config') +const pluginJest = require('eslint-plugin-jest') -export default [ +module.exports = [ ...aioLibConfig, - { - files: ['test/**'], - ...vitest.configs.recommended, - languageOptions: { - globals: { - ...vitest.environments.env.globals - } - } - }, + pluginJest.configs['flat/recommended'], { rules: { 'jsdoc/no-defaults': 'off' diff --git a/package.json b/package.json index d73265e..8407543 100644 --- a/package.json +++ b/package.json @@ -4,23 +4,21 @@ "description": "Generate and validate private certificates, and public key pairs for use with Adobe IO Console", "repository": "adobe/aio-cli-plugin-certificate", "homepage": "https://github.com/adobe/aio-cli-plugin-certificate", - "type": "module", "dependencies": { "@oclif/core": "^4.9.0", "debug": "^4.3.3", - "fs-extra": "^11.3.5", + "fs-extra": "^9.0.0", "node-forge": "^1.3.0" }, "devDependencies": { "@adobe/eslint-config-aio-lib-config": "^5.0.0", "eslint": "^9", - "@vitest/coverage-v8": "^4.1.8", - "@vitest/eslint-plugin": "^1", + "eslint-plugin-jest": "^29", "eslint-plugin-jsdoc": "^48", + "jest": "^29", "neostandard": "^0", "oclif": "^4.0.0", - "stdout-stderr": "^0.1.9", - "vitest": "^4.1.8" + "stdout-stderr": "^0.1.9" }, "engines": { "node": ">=20" @@ -45,9 +43,22 @@ "scripts": { "posttest": "eslint src test", "test": "npm run unit-tests", - "unit-tests": "vitest run", + "unit-tests": "jest --ci", "prepack": "oclif manifest && oclif readme --no-aliases", "postpack": "rm -f oclif.manifest.json", "version": "oclif readme && git add README.md" + }, + "jest": { + "collectCoverage": true, + "testPathIgnorePatterns": [ + "/tests/fixtures/" + ], + "coveragePathIgnorePatterns": [ + "/tests/fixtures/" + ], + "testEnvironment": "node", + "setupFilesAfterEnv": [ + "./test/jest.setup.js" + ] } } diff --git a/src/certificate.js b/src/certificate.js index a8de2f4..fb476f3 100644 --- a/src/certificate.js +++ b/src/certificate.js @@ -9,10 +9,10 @@ OF ANY KIND, either express or implied. See the License for the specific languag governing permissions and limitations under the License. */ -import logDebug from 'debug' -import forge from 'node-forge' -const { pki, asn1 } = forge -const debug = logDebug('aio-cli-plugin-certificate:helpers') +const debug = require('debug')('aio-cli-plugin-certificate:helpers') +const forge = require('node-forge') +const pki = forge.pki +const asn1 = forge.asn1 /** * Computes the SHA-1 digest of the entire DER-encoded x.509 certificate @@ -164,4 +164,8 @@ function verify (pemCert) { } } -export { fingerprint, generate, verify } +module.exports = { + fingerprint, + generate, + verify +} diff --git a/src/commands/certificate/fingerprint.js b/src/commands/certificate/fingerprint.js index 09dd847..af78d5b 100644 --- a/src/commands/certificate/fingerprint.js +++ b/src/commands/certificate/fingerprint.js @@ -10,12 +10,11 @@ OF ANY KIND, either express or implied. See the License for the specific languag governing permissions and limitations under the License. */ -import { Command, Args } from '@oclif/core' -import fs from 'fs-extra' -import logDebug from 'debug' -import * as cert from '../../certificate.js' +const { Command, Args } = require('@oclif/core') +const fs = require('fs-extra') +const debug = require('debug')('aio-cli-plugin-certificate:fingerprint') -const debug = logDebug('aio-cli-plugin-certificate:fingerprint') +const cert = require('../../certificate') class FingerprintCommand extends Command { async run () { @@ -48,4 +47,4 @@ FingerprintCommand.args = { }) } -export default FingerprintCommand +module.exports = FingerprintCommand diff --git a/src/commands/certificate/generate.js b/src/commands/certificate/generate.js index 5f57eb4..295d18a 100644 --- a/src/commands/certificate/generate.js +++ b/src/commands/certificate/generate.js @@ -10,12 +10,11 @@ OF ANY KIND, either express or implied. See the License for the specific languag governing permissions and limitations under the License. */ -import { Command, Flags } from '@oclif/core' -import fs from 'fs-extra' -import logDebug from 'debug' -import * as cert from '../../certificate.js' +const { Command, Flags } = require('@oclif/core') +const fs = require('fs-extra') +const debug = require('debug')('aio-cli-plugin-certificate:generate') -const debug = logDebug('aio-cli-plugin-certificate:generate') +const cert = require('../../certificate') class GenerateCommand extends Command { async run () { @@ -80,4 +79,4 @@ GenerateCommand.flags = { }) } -export default GenerateCommand +module.exports = GenerateCommand diff --git a/src/commands/certificate/index.js b/src/commands/certificate/index.js index 1fe2518..2e4826c 100644 --- a/src/commands/certificate/index.js +++ b/src/commands/certificate/index.js @@ -10,7 +10,7 @@ OF ANY KIND, either express or implied. See the License for the specific languag governing permissions and limitations under the License. */ -import { Command, Help } from '@oclif/core' +const { Command, Help } = require('@oclif/core') class AIOCommand extends Command { async run () { @@ -21,4 +21,4 @@ class AIOCommand extends Command { AIOCommand.description = 'Generate, fingerprint, or verify a certificate for use with Adobe I/O' -export default AIOCommand +module.exports = AIOCommand diff --git a/src/commands/certificate/verify.js b/src/commands/certificate/verify.js index 524ab5d..baf0cca 100644 --- a/src/commands/certificate/verify.js +++ b/src/commands/certificate/verify.js @@ -10,12 +10,11 @@ OF ANY KIND, either express or implied. See the License for the specific languag governing permissions and limitations under the License. */ -import { Command, Flags, Args } from '@oclif/core' -import fs from 'fs-extra' -import logDebug from 'debug' -import * as cert from '../../certificate.js' +const { Command, Flags, Args } = require('@oclif/core') +const fs = require('fs-extra') +const debug = require('debug')('aio-cli-plugin-certificate:verify') -const debug = logDebug('aio-cli-plugin-certificate:verify') +const cert = require('../../certificate') class VerifyCommand extends Command { async run () { @@ -78,4 +77,4 @@ VerifyCommand.args = { }) } -export default VerifyCommand +module.exports = VerifyCommand diff --git a/test/commands/certificate/fingerprint.test.js b/test/commands/certificate/fingerprint.test.js index 65eb449..01762e3 100644 --- a/test/commands/certificate/fingerprint.test.js +++ b/test/commands/certificate/fingerprint.test.js @@ -10,12 +10,12 @@ governing permissions and limitations under the License. */ // const { stdout } = require('stdout-stderr') -import { vi } from 'vitest' -import mockFS from 'fs-extra' +const commandPath = '../../../src/commands/certificate/fingerprint' +let TheCommand +jest.isolateModules(() => { + TheCommand = require(commandPath) +}) -// we don't import the command up here to allow for some tests to run with isolated mocks -// since vitest doesn't support isolateModules -const commandPath = '../../../src/commands/certificate/fingerprint.js' const validCertPem = ` -----BEGIN CERTIFICATE----- MIIDMTCCAhmgAwIBAgIHAWVCcDJVYDANBgkqhkiG9w0BAQsFADAdMRswGQYDVQQD @@ -40,60 +40,36 @@ B9+DCYg= ` const validCertFingerprint = '38f65e26bd3869ec3ca029cc0b3df98de29172b9' -describe('basic functionality', () => { - let TheCommand - - beforeAll(async () => { - vi.resetModules() - TheCommand = (await import(commandPath)).default - }) - - test('exports', async () => { - expect(typeof TheCommand).toEqual('function') - }) +test('exports', async () => { + expect(typeof TheCommand).toEqual('function') +}) - test('description', async () => { - expect(TheCommand.description).toBeDefined() - }) +test('description', async () => { + expect(TheCommand.description).toBeDefined() +}) - test('args', async () => { - expect(Object.keys(TheCommand.args)[0]).toBeDefined() - }) +test('args', async () => { + expect(Object.keys(TheCommand.args)[0]).toBeDefined() }) -const mockConfig = { runHook: vi.fn().mockResolvedValue({ successes: [], failures: [] }) } +const mockConfig = { runHook: jest.fn().mockResolvedValue({ successes: [], failures: [] }) } describe('instance methods - mock forge', () => { - let CommandUnderTest, command, handleError, mockForge - - beforeAll(async () => { - vi.resetModules() - // vitest does not support isolateModules, so we have to build our own sandbox mock here - vi.doMock('node-forge', async (importOriginal) => { - const mod = await importOriginal() - const forge = mod.default ?? mod - return { - ...mod, - default: { - ...forge, - pki: { - ...forge.pki, - certificateFromPem: vi.fn() - } - } - } - }) - CommandUnderTest = (await import(commandPath)).default - mockForge = (await import('node-forge')).default + let CommandUnderTest, command, handleError, mockFS, mockForge + jest.isolateModules(() => { + CommandUnderTest = require(commandPath) + mockFS = require('fs-extra') + mockForge = require('node-forge') + jest.mock('node-forge') }) beforeEach(() => { command = new CommandUnderTest([], mockConfig) - handleError = vi.spyOn(command, 'error') + handleError = jest.spyOn(command, 'error') }) afterEach(() => { - vi.clearAllMocks() + jest.clearAllMocks() }) test('run missing args', async () => { @@ -120,28 +96,27 @@ describe('instance methods - mock forge', () => { }) describe('instance methods - real forge', () => { - let CommandUnderTest, command, handleError - - beforeAll(async () => { - vi.resetModules() - vi.doUnmock('node-forge') - CommandUnderTest = (await import(commandPath)).default + let CommandUnderTest, command, handleError, mockFS + jest.isolateModules(() => { + mockFS = require('fs-extra') + jest.unmock('node-forge') + CommandUnderTest = require(commandPath) }) beforeEach(() => { command = new CommandUnderTest([], mockConfig) - handleError = vi.spyOn(command, 'error') + handleError = jest.spyOn(command, 'error') }) afterEach(() => { - vi.clearAllMocks() + jest.clearAllMocks() }) test('run with valid cert pem', async () => { mockFS.existsSync.mockReturnValue(true) mockFS.readFileSync.mockReturnValue(Buffer.from(validCertPem)) command.argv = ['file'] - const logSpy = vi.spyOn(command, 'log') + const logSpy = jest.spyOn(command, 'log') await expect(command.run()).resolves.toBeUndefined() expect(logSpy).toHaveBeenCalledWith(validCertFingerprint) expect(handleError).not.toHaveBeenCalled() diff --git a/test/commands/certificate/generate.test.js b/test/commands/certificate/generate.test.js index 1320907..53d548b 100644 --- a/test/commands/certificate/generate.test.js +++ b/test/commands/certificate/generate.test.js @@ -10,10 +10,10 @@ governing permissions and limitations under the License. */ // const { stdout } = require('stdout-stderr') -import { vi } from 'vitest' -import TheCommand from '../../../src/commands/certificate/generate.js' -import mockFS from 'fs-extra' -import forge from 'node-forge' +const TheCommand = require('../../../src/commands/certificate/generate') + +const mockFS = require('fs-extra') +const forge = require('node-forge') test('exports', async () => { expect(typeof TheCommand).toEqual('function') @@ -23,18 +23,18 @@ test('description', async () => { expect(TheCommand.description).toBeDefined() }) -const mockConfig = { runHook: vi.fn().mockResolvedValue({ successes: [], failures: [] }) } +const mockConfig = { runHook: jest.fn().mockResolvedValue({ successes: [], failures: [] }) } describe('instance methods', () => { let command, handleError beforeEach(() => { command = new TheCommand([], mockConfig) - handleError = vi.spyOn(command, 'error') + handleError = jest.spyOn(command, 'error') }) afterEach(() => { - vi.clearAllMocks() + jest.clearAllMocks() }) test('run -- no flags', async () => { diff --git a/test/commands/certificate/index.test.js b/test/commands/certificate/index.test.js deleted file mode 100644 index 7f522bf..0000000 --- a/test/commands/certificate/index.test.js +++ /dev/null @@ -1,37 +0,0 @@ -/* -Copyright 2026 Adobe. All rights reserved. -This file is licensed 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 REPRESENTATIONS -OF ANY KIND, either express or implied. See the License for the specific language -governing permissions and limitations under the License. -*/ - -import { vi } from 'vitest' -import TheCommand from '../../../src/commands/certificate/index.js' -import { Help } from '@oclif/core' - -describe('index', () => { - let showHelpSpy - - beforeEach(() => { - showHelpSpy = vi.spyOn(Help.prototype, 'showHelp').mockResolvedValue(undefined) - }) - - afterEach(() => { - showHelpSpy.mockRestore() - }) - - test('description', async () => { - expect(TheCommand.description).toEqual('Generate, fingerprint, or verify a certificate for use with Adobe I/O') - }) - - test('run Help command', async () => { - const command = new TheCommand([], { runHook: vi.fn().mockResolvedValue({ successes: [], failures: [] }) }) - await command.run() - expect(showHelpSpy).toHaveBeenCalledWith(['certificate', '--help']) - }) -}) diff --git a/test/commands/certificate/verify.test.js b/test/commands/certificate/verify.test.js index c69ff9a..81bb0d7 100644 --- a/test/commands/certificate/verify.test.js +++ b/test/commands/certificate/verify.test.js @@ -9,13 +9,12 @@ OF ANY KIND, either express or implied. See the License for the specific languag governing permissions and limitations under the License. */ -import { vi } from 'vitest' +// const { stdout } = require('stdout-stderr') +const TheCommand = require('../../../src/commands/certificate/verify') -vi.mock('node-forge') - -import TheCommand from '../../../src/commands/certificate/verify.js' -import mockFS from 'fs-extra' -import mockForge from 'node-forge' +const mockFS = require('fs-extra') +const mockForge = require('node-forge') +jest.mock('node-forge') const distantFuture = new Date() distantFuture.setFullYear(distantFuture.getFullYear() + 1) @@ -35,18 +34,18 @@ test('args', async () => { expect(Object.keys(TheCommand.args)[0]).toBeDefined() }) -const mockConfig = { runHook: vi.fn().mockResolvedValue({ successes: [], failures: [] }) } +const mockConfig = { runHook: jest.fn().mockResolvedValue({ successes: [], failures: [] }) } describe('instance methods', () => { let command, handleError beforeEach(() => { command = new TheCommand([], mockConfig) - handleError = vi.spyOn(command, 'error') + handleError = jest.spyOn(command, 'error') }) afterEach(() => { - vi.clearAllMocks() + jest.clearAllMocks() }) test('run missing args', async () => { @@ -76,7 +75,7 @@ describe('instance methods', () => { test('run with invalid file ( false & true )', async () => { mockFS.existsSync.mockReturnValue(true) - mockForge.pki.certificateFromPem.mockReturnValue({ verify: vi.fn(() => true), validity: {} }) + mockForge.pki.certificateFromPem.mockReturnValue({ verify: jest.fn(() => true), validity: {} }) mockForge.pki.verifyCertificateChain.mockReturnValue(true) command.argv = ['file'] await expect(command.run()).resolves.toBe(true) @@ -85,7 +84,7 @@ describe('instance methods', () => { test('run with invalid file ( true & false )', async () => { mockFS.existsSync.mockReturnValue(true) - mockForge.pki.certificateFromPem.mockReturnValue({ verify: vi.fn(() => true), validity: {} }) + mockForge.pki.certificateFromPem.mockReturnValue({ verify: jest.fn(() => true), validity: {} }) mockForge.pki.verifyCertificateChain.mockReturnValue(false) command.argv = ['file'] await expect(command.run()).resolves.toBe(false) @@ -96,7 +95,7 @@ describe('instance methods', () => { mockFS.existsSync.mockReturnValue(true) mockForge.pki.certificateFromPem.mockReturnValue({ - verify: vi.fn(() => true), + verify: jest.fn(() => true), validity: { notAfter: now, notBefore: distantPast @@ -111,7 +110,7 @@ describe('instance methods', () => { mockFS.existsSync.mockReturnValue(true) mockForge.pki.certificateFromPem.mockReturnValue({ - verify: vi.fn(() => true), + verify: jest.fn(() => true), validity: { notAfter: distantFuture, notBefore: now @@ -126,7 +125,7 @@ describe('instance methods', () => { mockFS.existsSync.mockReturnValue(true) mockForge.pki.certificateFromPem.mockReturnValue({ - verify: vi.fn(() => true), + verify: jest.fn(() => true), validity: { notAfter: distantFuture, notBefore: now @@ -141,7 +140,7 @@ describe('instance methods', () => { mockFS.existsSync.mockReturnValue(true) mockForge.pki.certificateFromPem.mockReturnValue({ - verify: vi.fn(() => true), + verify: jest.fn(() => true), validity: { notAfter: now, notBefore: distantPast diff --git a/test/jest.setup.js b/test/jest.setup.js new file mode 100644 index 0000000..737b267 --- /dev/null +++ b/test/jest.setup.js @@ -0,0 +1,9 @@ +const { stdout } = require('stdout-stderr') + +beforeAll(() => stdout.start()) +afterAll(() => stdout.stop()) + +jest.setTimeout(30000) + +// dont touch the real fs +jest.mock('fs-extra') diff --git a/test/vitest.setup.js b/test/vitest.setup.js deleted file mode 100644 index e01c3bd..0000000 --- a/test/vitest.setup.js +++ /dev/null @@ -1,20 +0,0 @@ -/* -Copyright 2026 Adobe. All rights reserved. -This file is licensed 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 REPRESENTATIONS -OF ANY KIND, either express or implied. See the License for the specific language -governing permissions and limitations under the License. -*/ - -import { stdout } from 'stdout-stderr' -import { beforeAll, afterAll, vi } from 'vitest' - -beforeAll(() => stdout.start()) -afterAll(() => stdout.stop()) - -// don't touch the real fs -vi.mock('fs-extra') diff --git a/vitest.config.js b/vitest.config.js deleted file mode 100644 index 8796074..0000000 --- a/vitest.config.js +++ /dev/null @@ -1,28 +0,0 @@ -/* -Copyright 2026 Adobe. All rights reserved. -This file is licensed 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 REPRESENTATIONS -OF ANY KIND, either express or implied. See the License for the specific language -governing permissions and limitations under the License. -*/ - -import { defineConfig } from 'vitest/config' - -export default defineConfig({ - test: { - globals: true, - environment: 'node', - testTimeout: 30000, - setupFiles: ['./test/vitest.setup.js'], - include: ['test/**/*.test.js'], - exclude: ['**/node_modules/**'], - coverage: { - enabled: true, - include: ['src/**'] - } - } -})