diff --git a/.eslintrc b/.eslintrc index e2298e2..310446b 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,11 +1,23 @@ { - "plugins": ["jest"], - "extends": ["standard", "plugin:jest/recommended"], - "globals": { - "n": "readonly", - "r": "readonly", - "assertDependencies": "readonly", - "assertNodeEngines": "readonly" - } + "extends": ["standard"], + "parserOptions": { + "ecmaVersion": 2022, + "sourceType": "module" + }, + "globals": { + "n": "readonly", + "r": "readonly", + "assertDependencies": "readonly", + "assertNodeEngines": "readonly", + "basicGeneratorOptions": "readonly", + "vi": "readonly", + "describe": "readonly", + "it": "readonly", + "test": "readonly", + "expect": "readonly", + "beforeEach": "readonly", + "afterEach": "readonly", + "beforeAll": "readonly", + "afterAll": "readonly" } - \ No newline at end of file +} diff --git a/index.js b/index.js index 4d82290..7568e91 100644 --- a/index.js +++ b/index.js @@ -9,13 +9,13 @@ OF ANY KIND, either express or implied. See the License for the specific languag governing permissions and limitations under the License. */ -const utils = require('./lib/utils') -const ActionGenerator = require('./lib/ActionGenerator') -const EventsGenerator = require('./lib/EventsGenerator') -const constants = require('./lib/constants') -const commonTemplates = require('./lib/common-templates') +import * as utils from './lib/utils.js' +import ActionGenerator from './lib/ActionGenerator.js' +import EventsGenerator from './lib/EventsGenerator.js' +import * as constants from './lib/constants.js' +import commonTemplates from './lib/common-templates/index.js' -module.exports = { +export { utils, constants, ActionGenerator, diff --git a/jest.config.js b/jest.config.js deleted file mode 100644 index 264fcd8..0000000 --- a/jest.config.js +++ /dev/null @@ -1,32 +0,0 @@ -/* -Copyright 2019 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. -*/ - -module.exports = { - testEnvironment: 'node', - verbose: true, - setupFilesAfterEnv: ['./test/jest.setup.js'], - collectCoverage: true, - collectCoverageFrom: [ - 'lib/**/*.js', - '!lib/common-templates/*.js' - ], - testPathIgnorePatterns: [ - '/lib/' - ], - coverageThreshold: { - global: { - branches: 100, - lines: 100, - statements: 100 - } - } -} diff --git a/lib/ActionGenerator.js b/lib/ActionGenerator.js index 777c407..a23a8a8 100644 --- a/lib/ActionGenerator.js +++ b/lib/ActionGenerator.js @@ -10,12 +10,12 @@ OF ANY KIND, either express or implied. See the License for the specific languag governing permissions and limitations under the License. */ -const path = require('path') -const upath = require('upath') +import path from 'node:path' +import upath from 'upath' -const Generator = require('yeoman-generator') -const utils = require('./utils') -const { nodeEngines, defaultRuntimeKind } = require('./constants') +import Generator from 'yeoman-generator' +import * as utils from './utils.js' +import { nodeEngines, defaultRuntimeKind } from './constants.js' class ActionGenerator extends Generator { constructor (args, opts) { @@ -242,4 +242,4 @@ Note: characters can only be split by '-'. } } -module.exports = ActionGenerator +export default ActionGenerator diff --git a/lib/EventsGenerator.js b/lib/EventsGenerator.js index 2836142..bfa1541 100644 --- a/lib/EventsGenerator.js +++ b/lib/EventsGenerator.js @@ -9,15 +9,15 @@ OF ANY KIND, either express or implied. See the License for the specific languag governing permissions and limitations under the License. */ -const utils = require('./utils') -const eventsSdk = require('@adobe/aio-lib-events') -const config = require('@adobe/aio-lib-core-config') -const { getToken } = require('@adobe/aio-lib-ims') -const { CLI } = require('@adobe/aio-lib-ims/src/context') +import * as utils from './utils.js' +import eventsSdk from '@adobe/aio-lib-events' +import config from '@adobe/aio-lib-core-config' +import imsLib from '@adobe/aio-lib-ims' +import { CLI } from '@adobe/aio-lib-ims/src/context.js' -const ActionGenerator = require('./ActionGenerator') -const { promptForEventsOfInterest, getProviderMetadataToProvidersExistingMap } = require('./events/EventsOfInterestHelper') -const { promptForRuntimeAction } = require('./events/RuntimeActionForEventsHelper') +import ActionGenerator from './ActionGenerator.js' +import { promptForEventsOfInterest, getProviderMetadataToProvidersExistingMap } from './events/EventsOfInterestHelper.js' +import { promptForRuntimeAction } from './events/RuntimeActionForEventsHelper.js' const eventsProvidermetadataToProviderMapping = 'AIO_EVENTS_PROVIDERMETADATA_TO_PROVIDER_MAPPING' class EventsGenerator extends ActionGenerator { @@ -47,7 +47,7 @@ class EventsGenerator extends ActionGenerator { this.env.error('Incomplete .aio configuration, please import a valid Adobe Developer Console configuration via `aio app use` first.') } const orgCode = this.projectConfig.org.ims_org_id - const accessToken = await getToken(CLI) + const accessToken = await imsLib.getToken(CLI) const X_API_KEY = process.env.SERVICE_API_KEY const eventsClient = await eventsSdk.init(orgCode, X_API_KEY, accessToken) return eventsClient @@ -175,4 +175,4 @@ class EventsGenerator extends ActionGenerator { } } -module.exports = EventsGenerator +export default EventsGenerator diff --git a/lib/common-templates/index.js b/lib/common-templates/index.js index 3c7b777..2bbb110 100644 --- a/lib/common-templates/index.js +++ b/lib/common-templates/index.js @@ -9,9 +9,12 @@ the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTA OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ -const path = require('path') +import path from 'node:path' +import { fileURLToPath } from 'node:url' -module.exports = { +const __dirname = path.dirname(fileURLToPath(import.meta.url)) + +export default { 'stub-action.e2e': path.resolve(__dirname, './stub-action.e2e.js'), 'stub-action': path.resolve(__dirname, './stub-action.js'), utils: path.resolve(__dirname, './utils.js'), diff --git a/lib/constants.js b/lib/constants.js index 50dc090..0f3b866 100644 --- a/lib/constants.js +++ b/lib/constants.js @@ -9,24 +9,22 @@ OF ANY KIND, either express or implied. See the License for the specific languag governing permissions and limitations under the License. */ -module.exports = { - isLoopingPrompts: false, - actionsDirname: 'actions', - dotenvFilename: '.env', - manifestPackagePlaceholder: '__APP_PACKAGE__', - sdkCodes: { - analytics: 'AdobeAnalyticsSDK', - assetCompute: 'AssetComputeSDK', - campaign: 'CampaignSDK', - customerProfile: 'McDataServicesSdk', - target: 'AdobeTargetSDK' - }, - ciDirName: '.github', - commonDependencyVersions: { - '@adobe/aio-sdk': '^6' - }, - appConfigFile: 'app.config.yaml', - runtimeManifestKey: 'runtimeManifest', - nodeEngines: '>=18', - defaultRuntimeKind: 'nodejs:22' +export const isLoopingPrompts = false +export const actionsDirname = 'actions' +export const dotenvFilename = '.env' +export const manifestPackagePlaceholder = '__APP_PACKAGE__' +export const sdkCodes = { + analytics: 'AdobeAnalyticsSDK', + assetCompute: 'AssetComputeSDK', + campaign: 'CampaignSDK', + customerProfile: 'McDataServicesSdk', + target: 'AdobeTargetSDK' } +export const ciDirName = '.github' +export const commonDependencyVersions = { + '@adobe/aio-sdk': '^6' +} +export const appConfigFile = 'app.config.yaml' +export const runtimeManifestKey = 'runtimeManifest' +export const nodeEngines = '>=18' +export const defaultRuntimeKind = 'nodejs:22' diff --git a/lib/events/EventsOfInterestHelper.js b/lib/events/EventsOfInterestHelper.js index ac8ed6c..2f563ee 100644 --- a/lib/events/EventsOfInterestHelper.js +++ b/lib/events/EventsOfInterestHelper.js @@ -9,8 +9,8 @@ OF ANY KIND, either express or implied. See the License for the specific languag governing permissions and limitations under the License. */ -const { getAllEntitledProvidersForOrg, selectEventMetadataForProvider, selectProviderForProviderMetadata } = require('./ProviderHelper') -const { getEntitledProviderMetadataForOrg, getProviderMetadata } = require('./ProviderMetadataHelper') +import { getAllEntitledProvidersForOrg, selectEventMetadataForProvider, selectProviderForProviderMetadata } from './ProviderHelper.js' +import { getEntitledProviderMetadataForOrg, getProviderMetadata } from './ProviderMetadataHelper.js' async function promptForEventsOfInterest (eventsClient, obj, options) { // get all entitled provider metadata for the org @@ -86,7 +86,7 @@ function getProviderMetadataToProvidersExistingMap (providerMetadataToProviderMa return {} } -module.exports = { +export { promptForEventsOfInterest, getProviderMetadataToProvidersExistingMap } diff --git a/lib/events/ProviderHelper.js b/lib/events/ProviderHelper.js index 16c4e5b..c837035 100644 --- a/lib/events/ProviderHelper.js +++ b/lib/events/ProviderHelper.js @@ -68,7 +68,7 @@ async function selectEventMetadataForProvider (providerSelected, eventMetadataCh return eventMetadataSelection } -module.exports = { +export { getAllEntitledProvidersForOrg, selectProviderForProviderMetadata, selectEventMetadataForProvider diff --git a/lib/events/ProviderMetadataHelper.js b/lib/events/ProviderMetadataHelper.js index 3732eec..d8fb880 100644 --- a/lib/events/ProviderMetadataHelper.js +++ b/lib/events/ProviderMetadataHelper.js @@ -54,7 +54,7 @@ async function getProviderMetadata (obj, providerMetadataList, options) { return providerMetadataIds } -module.exports = { +export { getEntitledProviderMetadataForOrg, getProviderMetadata } diff --git a/lib/events/RuntimeActionForEventsHelper.js b/lib/events/RuntimeActionForEventsHelper.js index 14ff85e..f208ca0 100644 --- a/lib/events/RuntimeActionForEventsHelper.js +++ b/lib/events/RuntimeActionForEventsHelper.js @@ -57,6 +57,6 @@ function getExistingActionNames (runtimeManifest, pkgName) { return actionNames } -module.exports = { +export { promptForRuntimeAction } diff --git a/lib/utils.js b/lib/utils.js index 6f2bdbd..f67b80c 100644 --- a/lib/utils.js +++ b/lib/utils.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. */ -const path = require('path') -const yaml = require('js-yaml') -const { EOL } = require('os') -const { appConfigFile, dotenvFilename } = require('./constants') +import path from 'node:path' +import yaml from 'js-yaml' +import { EOL } from 'node:os' +import { appConfigFile, dotenvFilename } from './constants.js' function atLeastOne (input) { if (input.length === 0) { @@ -127,7 +127,7 @@ function appendVarsToDotenv (generator, label, envVariable, value) { generator.fs.append(file, content) } -module.exports = { +export { atLeastOne, guessProjectName, addDependencies, diff --git a/package.json b/package.json index 6e61e22..43257a3 100644 --- a/package.json +++ b/package.json @@ -2,11 +2,13 @@ "name": "@adobe/generator-app-common-lib", "version": "3.0.2", "description": "", + "type": "module", "main": "index.js", "scripts": { "test": "npm run unit-tests && npm run lint", "lint": "eslint .", - "unit-tests": "jest -c ./jest.config.js" + "unit-tests": "vitest run --coverage", + "test:watch": "vitest" }, "author": "Adobe Inc.", "license": "Apache-2.0", @@ -19,18 +21,17 @@ }, "devDependencies": { "@adobe/eslint-config-aio-lib-config": "^4.0.0", - "@types/jest": "^29.5.0", + "@vitest/coverage-v8": "^2.1.0", "eol": "^0.9.1", "eslint": "^8.57.1", "eslint-config-standard": "^17.1.0", "eslint-plugin-import": "^2.31.0", - "eslint-plugin-jest": "^27.9.0", "eslint-plugin-jsdoc": "^48.11.0", "eslint-plugin-n": "^15.7.0", "eslint-plugin-node": "^11.1.0", "eslint-plugin-promise": "^6.6.0", - "jest": "^29", - "stdout-stderr": "^0.1.13" + "stdout-stderr": "^0.1.13", + "vitest": "^2.1.0" }, "dependencies": { "@adobe/aio-lib-core-config": "^5", @@ -42,6 +43,6 @@ "lodash.clonedeep": "^4.5.0", "process": "^0.11.10", "upath": "^2.0.1", - "yeoman-generator": "^5.5.2" + "yeoman-generator": "^8" } } diff --git a/test/lib/ActionGenerator.test.js b/test/lib/ActionGenerator.test.js index e1d13bf..14df440 100644 --- a/test/lib/ActionGenerator.test.js +++ b/test/lib/ActionGenerator.test.js @@ -9,18 +9,17 @@ OF ANY KIND, either express or implied. See the License for the specific languag governing permissions and limitations under the License. */ -const path = require('path') -const cloneDeep = require('lodash.clonedeep') +import path from 'node:path' +import cloneDeep from 'lodash.clonedeep' -const constants = require('../../lib/constants') +import * as constants from '../../lib/constants.js' -jest.mock('yeoman-generator') +import ActionGenerator from '../../lib/ActionGenerator.js' +import Generator from 'yeoman-generator' +import * as utils from '../../lib/utils.js' -const ActionGenerator = require('../../lib/ActionGenerator') -const Generator = require('yeoman-generator') - -jest.mock('../../lib/utils.js') -const utils = require('../../lib/utils.js') +vi.mock('yeoman-generator') +vi.mock('../../lib/utils.js') const generatorOptions = cloneDeep(global.basicGeneratorOptions) @@ -52,7 +51,7 @@ describe('implementation', () => { }) describe('constructor', () => { test('accept options', () => { - const spy = jest.spyOn(ActionGenerator.prototype, 'option') + const spy = vi.spyOn(ActionGenerator.prototype, 'option') // eslint-disable-next-line no-new new ActionGenerator() expect(spy).toHaveBeenCalledWith('skip-prompt', { default: false }) @@ -72,7 +71,7 @@ describe('implementation', () => { let promptSpy let actionGenerator beforeEach(() => { - promptSpy = jest.spyOn(ActionGenerator.prototype, 'prompt') + promptSpy = vi.spyOn(ActionGenerator.prototype, 'prompt') actionGenerator = new ActionGenerator() actionGenerator.options = { 'skip-prompt': false } }) @@ -169,7 +168,7 @@ Note: characters can only be split by '-'. beforeEach(() => { actionGenerator = new ActionGenerator() actionGenerator.options = { 'skip-prompt': false } - actionGenerator.fs = { copyTpl: jest.fn() } + actionGenerator.fs = { copyTpl: vi.fn() } // mock path resolvers actionGenerator.templatePath = p => path.join('/fakeTplDir', p) diff --git a/test/lib/EventGenerator.test.js b/test/lib/EventGenerator.test.js index 776c1ac..a69d1e2 100644 --- a/test/lib/EventGenerator.test.js +++ b/test/lib/EventGenerator.test.js @@ -9,40 +9,35 @@ OF ANY KIND, either express or implied. See the License for the specific languag governing permissions and limitations under the License. */ -const path = require('path') -const mockData = require('./mock') -const cloneDeep = require('lodash.clonedeep') -const eventsSdk = require('@adobe/aio-lib-events') -const { getProviderMetadataToProvidersExistingMap } = require('../../lib/events/EventsOfInterestHelper') +import path from 'node:path' +import mockData from './mock.js' +import cloneDeep from 'lodash.clonedeep' +import eventsSdk from '@adobe/aio-lib-events' +import { getProviderMetadataToProvidersExistingMap } from '../../lib/events/EventsOfInterestHelper.js' +import EventsGenerator from '../../lib/EventsGenerator.js' +import Generator from 'yeoman-generator' +import * as utils from '../../lib/utils.js' const mockEventsSdkInstance = { - createRegistration: jest.fn(), - updateRegistration: jest.fn() + createRegistration: vi.fn(), + updateRegistration: vi.fn() } -jest.mock('@adobe/aio-lib-ims', () => ({ - getToken: jest.fn().mockResolvedValue('token') -})) - -jest.mock('@adobe/aio-lib-ims', () => ({ - getToken: jest.fn().mockResolvedValue('token') -})) - -jest.mock('../../lib/events/EventsOfInterestHelper', () => ({ - promptForEventsOfInterest: jest.fn().mockResolvedValue(mockData.data.selectedProvidersToEventMetadata), - getProviderMetadataToProvidersExistingMap: jest.fn() -})) +const generatorOptions = cloneDeep(global.basicGeneratorOptions) -jest.mock('../../lib/events/RuntimeActionForEventsHelper', () => ({ - promptForRuntimeAction: jest.fn().mockResolvedValue('test-action-name') +vi.mock('@adobe/aio-lib-ims', () => ({ default: { getToken: vi.fn().mockResolvedValue('token') } })) +vi.mock('../../lib/events/EventsOfInterestHelper.js', async () => { + const { default: mockData } = await import('./mock.js') + return { + promptForEventsOfInterest: vi.fn().mockResolvedValue(mockData.data.selectedProvidersToEventMetadata), + getProviderMetadataToProvidersExistingMap: vi.fn() + } +}) +vi.mock('../../lib/events/RuntimeActionForEventsHelper.js', () => ({ + promptForRuntimeAction: vi.fn().mockResolvedValue('test-action-name') })) - -const EventsGenerator = require('../../lib/EventsGenerator') -const Generator = require('yeoman-generator') -const generatorOptions = cloneDeep(global.basicGeneratorOptions) -jest.mock('yeoman-generator') -jest.mock('@adobe/aio-lib-events') -jest.mock('../../lib/utils.js') -const utils = require('../../lib/utils.js') +vi.mock('yeoman-generator') +vi.mock('@adobe/aio-lib-events', () => ({ default: { init: vi.fn() } })) +vi.mock('../../lib/utils.js') const aioEventsMappingEnvVariable = 'AIO_EVENTS_PROVIDERMETADATA_TO_PROVIDER_MAPPING' @@ -73,11 +68,11 @@ describe('implementation', () => { error: (text) => { throw text } } Generator.prototype.options = generatorOptions - EventsGenerator.prototype.addAction = jest.fn() + EventsGenerator.prototype.addAction = vi.fn() }) describe('constructor', () => { test('accept options', () => { - const spy = jest.spyOn(EventsGenerator.prototype, 'option') + const spy = vi.spyOn(EventsGenerator.prototype, 'option') // eslint-disable-next-line no-new new EventsGenerator() expect(spy).toHaveBeenCalledWith('skip-prompt', { default: false }) @@ -101,7 +96,7 @@ describe('implementation', () => { let promptSpy let eventsGenerator beforeEach(() => { - promptSpy = jest.spyOn(EventsGenerator.prototype, 'prompt') + promptSpy = vi.spyOn(EventsGenerator.prototype, 'prompt') eventsGenerator = new EventsGenerator() eventsGenerator.options = { 'skip-prompt': false } EventsGenerator.prototype.env = { @@ -125,7 +120,7 @@ describe('implementation', () => { let promptSpy let eventsGenerator beforeEach(async () => { - promptSpy = jest.spyOn(EventsGenerator.prototype, 'prompt') + promptSpy = vi.spyOn(EventsGenerator.prototype, 'prompt') eventsGenerator = new EventsGenerator() eventsGenerator.options = { 'skip-prompt': false } EventsGenerator.prototype.env = { @@ -167,8 +162,8 @@ describe('implementation', () => { beforeEach(() => { eventsGenerator = new EventsGenerator() eventsGenerator.options = { 'skip-prompt': false } - eventsGenerator.addAction = jest.fn() - eventsGenerator.loadRuntimeManifest = jest.fn() + eventsGenerator.addAction = vi.fn() + eventsGenerator.loadRuntimeManifest = vi.fn() }) test('with no options and manifest does not exist and no regDetails', () => { diff --git a/test/lib/events/EventsOfInterestHelper.test.js b/test/lib/events/EventsOfInterestHelper.test.js index 4afd5d1..f473100 100644 --- a/test/lib/events/EventsOfInterestHelper.test.js +++ b/test/lib/events/EventsOfInterestHelper.test.js @@ -9,25 +9,28 @@ OF ANY KIND, either express or implied. See the License for the specific languag governing permissions and limitations under the License. */ -const eventsSdk = require('@adobe/aio-lib-events') -const mockData = require('../mock') -const { promptForEventsOfInterest, getProviderMetadataToProvidersExistingMap } = require('../../../lib/events/EventsOfInterestHelper') -const { getAllEntitledProvidersForOrg, selectEventMetadataForProvider, selectProviderForProviderMetadata } = require('../../../lib/events/ProviderHelper') -const EventsGenerator = require('../../../lib/EventsGenerator') -const { getProviderMetadata } = require('../../../lib/events/ProviderMetadataHelper') -jest.mock('yeoman-generator') -jest.mock('../../../lib/EventsGenerator') -jest.mock('@adobe/aio-lib-events') -jest.mock('../../../lib/events/ProviderHelper', () => ({ - selectEventMetadataForProvider: jest.fn(), - selectProviderForProviderMetadata: jest.fn(), - getAllEntitledProvidersForOrg: jest.fn() +import eventsSdk from '@adobe/aio-lib-events' +import mockData from '../mock.js' +import { promptForEventsOfInterest, getProviderMetadataToProvidersExistingMap } from '../../../lib/events/EventsOfInterestHelper.js' +import { getAllEntitledProvidersForOrg, selectEventMetadataForProvider, selectProviderForProviderMetadata } from '../../../lib/events/ProviderHelper.js' +import EventsGenerator from '../../../lib/EventsGenerator.js' +import { getProviderMetadata } from '../../../lib/events/ProviderMetadataHelper.js' +vi.mock('yeoman-generator') +vi.mock('../../../lib/EventsGenerator.js') +vi.mock('@adobe/aio-lib-events', () => ({ default: { init: vi.fn() } })) +vi.mock('../../../lib/events/ProviderHelper.js', () => ({ + selectEventMetadataForProvider: vi.fn(), + selectProviderForProviderMetadata: vi.fn(), + getAllEntitledProvidersForOrg: vi.fn() })) -jest.mock('../../../lib/events/ProviderMetadataHelper', () => ({ - getEntitledProviderMetadataForOrg: jest.fn().mockResolvedValue(mockData.data.providerMetadataList), - getProviderMetadata: jest.fn().mockResolvedValue(['provider-metadata-1', 'provider-metadata-2']) -})) +vi.mock('../../../lib/events/ProviderMetadataHelper.js', async () => { + const { default: mockData } = await import('../mock.js') + return { + getEntitledProviderMetadataForOrg: vi.fn().mockResolvedValue(mockData.data.providerMetadataList), + getProviderMetadata: vi.fn().mockResolvedValue(['provider-metadata-1', 'provider-metadata-2']) + } +}) const getTestProvider = (index, numberOfEvents) => { const eventMetadatas = [] diff --git a/test/lib/events/ProviderHelper.test.js b/test/lib/events/ProviderHelper.test.js index 2292052..577114b 100644 --- a/test/lib/events/ProviderHelper.test.js +++ b/test/lib/events/ProviderHelper.test.js @@ -9,25 +9,28 @@ OF ANY KIND, either express or implied. See the License for the specific languag governing permissions and limitations under the License. */ -const mockData = require('../mock') -const { +import mockData from '../mock.js' +import { selectEventMetadataForProvider, selectProviderForProviderMetadata, getAllEntitledProvidersForOrg -} = require('../../../lib/events/ProviderHelper') -const EventsGenerator = require('../../../lib/EventsGenerator') -const eventsSdk = require('@adobe/aio-lib-events') +} from '../../../lib/events/ProviderHelper.js' +import EventsGenerator from '../../../lib/EventsGenerator.js' +import eventsSdk from '@adobe/aio-lib-events' -jest.mock('yeoman-generator') -jest.mock('@adobe/aio-lib-events') -jest.mock('../../../lib/EventsGenerator') +vi.mock('yeoman-generator') +vi.mock('@adobe/aio-lib-events', () => ({ default: { init: vi.fn() } })) +vi.mock('../../../lib/EventsGenerator.js') -jest.mock('../../../lib/events/ProviderMetadataHelper', () => ({ - getEntitledProviderMetadataForOrg: jest.fn().mockResolvedValue(mockData.data.providerMetadataList), - getProviderMetadata: jest.fn().mockResolvedValue(['provider-metadata-1', 'provider-metadata-2']) -})) +vi.mock('../../../lib/events/ProviderMetadataHelper.js', async () => { + const { default: mockData } = await import('../mock.js') + return { + getEntitledProviderMetadataForOrg: vi.fn().mockResolvedValue(mockData.data.providerMetadataList), + getProviderMetadata: vi.fn().mockResolvedValue(['provider-metadata-1', 'provider-metadata-2']) + } +}) const mockEventsSdkInstance = { - getAllProviders: jest.fn().mockResolvedValue({ + getAllProviders: vi.fn().mockResolvedValue({ _embedded: { providers: [{ id: 'provider-id-1', @@ -79,7 +82,7 @@ describe('test provider selection helper', () => { let promptSpy let eventsClient beforeEach(async () => { - promptSpy = jest.spyOn(EventsGenerator.prototype, 'prompt') + promptSpy = vi.spyOn(EventsGenerator.prototype, 'prompt') eventsClient = await eventsSdk.init('orgid', 'api-key', 'token') EventsGenerator.prototype.projectConfig = mockData.data.projectConfig eventsGenerator = new EventsGenerator() diff --git a/test/lib/events/ProviderMetadataHelper.test.js b/test/lib/events/ProviderMetadataHelper.test.js index 274be2f..2006a09 100644 --- a/test/lib/events/ProviderMetadataHelper.test.js +++ b/test/lib/events/ProviderMetadataHelper.test.js @@ -9,16 +9,16 @@ OF ANY KIND, either express or implied. See the License for the specific languag governing permissions and limitations under the License. */ -const eventsSdk = require('@adobe/aio-lib-events') -const mockData = require('../mock') -const { getEntitledProviderMetadataForOrg, getProviderMetadata } = require('../../../lib/events/ProviderMetadataHelper') -const EventsGenerator = require('../../../lib/EventsGenerator') -jest.mock('@adobe/aio-lib-events') -jest.mock('yeoman-generator') -jest.mock('../../../lib/EventsGenerator') +import eventsSdk from '@adobe/aio-lib-events' +import mockData from '../mock.js' +import { getEntitledProviderMetadataForOrg, getProviderMetadata } from '../../../lib/events/ProviderMetadataHelper.js' +import EventsGenerator from '../../../lib/EventsGenerator.js' +vi.mock('@adobe/aio-lib-events', () => ({ default: { init: vi.fn() } })) +vi.mock('yeoman-generator') +vi.mock('../../../lib/EventsGenerator.js') const mockEventsSdkInstance = { - getProviderMetadata: jest.fn().mockResolvedValue(mockData.data.embeddedProviderMetadata) + getProviderMetadata: vi.fn().mockResolvedValue(mockData.data.embeddedProviderMetadata) } beforeEach(() => { @@ -30,7 +30,7 @@ describe('test provider metadata selection helper', () => { let promptSpy let eventsClient beforeEach(async () => { - promptSpy = jest.spyOn(EventsGenerator.prototype, 'prompt') + promptSpy = vi.spyOn(EventsGenerator.prototype, 'prompt') eventsClient = await eventsSdk.init('orgid', 'api-key', 'token') eventsGenerator = new EventsGenerator() }) diff --git a/test/lib/events/RuntimeActionForEventsHelper.test.js b/test/lib/events/RuntimeActionForEventsHelper.test.js index faeb754..161c614 100644 --- a/test/lib/events/RuntimeActionForEventsHelper.test.js +++ b/test/lib/events/RuntimeActionForEventsHelper.test.js @@ -9,22 +9,22 @@ OF ANY KIND, either express or implied. See the License for the specific languag governing permissions and limitations under the License. */ -const mockData = require('../mock') -const { promptForRuntimeAction } = require('../../../lib/events/RuntimeActionForEventsHelper') -const EventsGenerator = require('../../../lib/EventsGenerator') -jest.mock('yeoman-generator') -jest.mock('../../../lib/EventsGenerator') +import mockData from '../mock.js' +import { promptForRuntimeAction } from '../../../lib/events/RuntimeActionForEventsHelper.js' +import EventsGenerator from '../../../lib/EventsGenerator.js' +vi.mock('yeoman-generator') +vi.mock('../../../lib/EventsGenerator.js') describe('test runtime action selection helper', () => { let eventsGenerator let promptSpy beforeEach(() => { - promptSpy = jest.spyOn(EventsGenerator.prototype, 'prompt') - EventsGenerator.prototype.loadRuntimeManifest = jest.fn().mockReturnValue({ + promptSpy = vi.spyOn(EventsGenerator.prototype, 'prompt') + EventsGenerator.prototype.loadRuntimeManifest = vi.fn().mockReturnValue({ runtimeManifest: mockData.data.runtimeManifestWithAvailableNonWebActions, runtimePackageName: 'somepackage' }) - EventsGenerator.prototype.promptForActionName = jest.fn().mockReturnValue('test-runtime-action-name') + EventsGenerator.prototype.promptForActionName = vi.fn().mockReturnValue('test-runtime-action-name') eventsGenerator = new EventsGenerator() eventsGenerator.options = { 'skip-prompt': false } }) @@ -75,14 +75,14 @@ describe('test runtime action selection helper', () => { }) test('skip selection of existing action when no non-web actions available', async () => { - EventsGenerator.prototype.loadRuntimeManifest = jest.fn().mockReturnValue({ + EventsGenerator.prototype.loadRuntimeManifest = vi.fn().mockReturnValue({ runtimeManifest: mockData.data.runtimeManifestWithWebActions, runtimePackageName: 'somepackage' }) promptSpy.mockResolvedValue({ actionSelection: true }) - EventsGenerator.prototype.promptForActionName = jest.fn().mockReturnValue('test-runtime-action-name') + EventsGenerator.prototype.promptForActionName = vi.fn().mockReturnValue('test-runtime-action-name') eventsGenerator = new EventsGenerator() const runtimeActionName = await promptForRuntimeAction(eventsGenerator) diff --git a/test/lib/mock.js b/test/lib/mock.js index 0f0e132..2eecb16 100644 --- a/test/lib/mock.js +++ b/test/lib/mock.js @@ -179,6 +179,6 @@ const data = { runtimeManifestWithAvailableNonWebActions } -module.exports = { +export default { data } diff --git a/test/lib/utils.test.js b/test/lib/utils.test.js index b4ecb85..c8f17aa 100644 --- a/test/lib/utils.test.js +++ b/test/lib/utils.test.js @@ -9,8 +9,8 @@ OF ANY KIND, either express or implied. See the License for the specific languag governing permissions and limitations under the License. */ -const utils = require('../../lib/utils') -const eol = require('eol') +import * as utils from '../../lib/utils.js' +import eol from 'eol' describe('atLeastOne', () => { test('returns true if input.length > 0', () => { @@ -23,7 +23,7 @@ describe('atLeastOne', () => { describe('guessProjectName', () => { test('returns cwd if package.json does not exist', () => { - const spy = jest.spyOn(process, 'cwd') + const spy = vi.spyOn(process, 'cwd') spy.mockReturnValue('FAKECWD') expect(utils.guessProjectName({ destinationPath: () => { }, @@ -35,7 +35,7 @@ describe('guessProjectName', () => { }) test('returns cwd if package.json[name] is not defined', () => { - const spy = jest.spyOn(process, 'cwd') + const spy = vi.spyOn(process, 'cwd') spy.mockReturnValue('FAKECWD') expect(utils.guessProjectName({ destinationPath: () => { }, @@ -60,10 +60,10 @@ describe('guessProjectName', () => { describe('addPkgScript', () => { test('adds scripts to package.json', () => { - const mockRead = jest.fn(() => { + const mockRead = vi.fn(() => { return ({ name: 'bob', scripts: { scripta: 'a' } }) }) - const mockWrite = jest.fn() + const mockWrite = vi.fn() const generator = { destinationPath: () => 'some-path', fs: { @@ -79,10 +79,10 @@ describe('addPkgScript', () => { }) test('overwrites existing scripts package.json', () => { - const mockRead = jest.fn(() => { + const mockRead = vi.fn(() => { return ({ name: 'bob', scripts: { scripta: 'a' } }) }) - const mockWrite = jest.fn() + const mockWrite = vi.fn() const generator = { destinationPath: () => 'some-path', fs: { @@ -98,8 +98,8 @@ describe('addPkgScript', () => { }) test('writes package.json if null', () => { - const mockRead = jest.fn() - const mockWrite = jest.fn() + const mockRead = vi.fn() + const mockWrite = vi.fn() const generator = { destinationPath: () => 'some-path', fs: { @@ -117,11 +117,11 @@ describe('addPkgScript', () => { describe('readPackageJson', () => { test('if package.json is empty', () => { - const mockRead = jest.fn(() => { + const mockRead = vi.fn(() => { return '' }) const generator = { - destinationPath: jest.fn(() => 'some-path'), + destinationPath: vi.fn(() => 'some-path'), fs: { readJSON: mockRead } @@ -132,11 +132,11 @@ describe('readPackageJson', () => { }) test('if package.json is { a: key, scripts: { b: c } }', () => { - const mockRead = jest.fn(() => { + const mockRead = vi.fn(() => { return { a: 'key', scripts: { b: 'c' } } }) const generator = { - destinationPath: jest.fn(() => 'some-path'), + destinationPath: vi.fn(() => 'some-path'), fs: { readJSON: mockRead } @@ -149,11 +149,11 @@ describe('readPackageJson', () => { describe('writePackageJson', () => { test('if content is empty', () => { - const mockWrite = jest.fn(() => { + const mockWrite = vi.fn(() => { return '' }) const generator = { - destinationPath: jest.fn(() => 'some-path'), + destinationPath: vi.fn(() => 'some-path'), fs: { writeJSON: mockWrite } @@ -164,11 +164,11 @@ describe('writePackageJson', () => { }) test('if content is { a: key, scripts: { b: c } }', () => { - const mockWrite = jest.fn(() => { + const mockWrite = vi.fn(() => { return '' }) const generator = { - destinationPath: jest.fn(() => 'some-path'), + destinationPath: vi.fn(() => 'some-path'), fs: { writeJSON: mockWrite } @@ -181,12 +181,12 @@ describe('writePackageJson', () => { describe('addDependencies', () => { test('adds dependencies to package.json with no existing dependencies', () => { - const mockRead = jest.fn(() => { + const mockRead = vi.fn(() => { return undefined }) - const mockWrite = jest.fn() + const mockWrite = vi.fn() const generator = { - destinationPath: jest.fn(() => 'some-path'), + destinationPath: vi.fn(() => 'some-path'), fs: { readJSON: mockRead, writeJSON: mockWrite @@ -201,12 +201,12 @@ describe('addDependencies', () => { expect(mockWrite).toHaveBeenCalledWith('some-path', { dependencies: { a: 'b', c: 'd' } }) }) test('adds devDependencies to package.json with no existing devDependencies', () => { - const mockRead = jest.fn(() => { + const mockRead = vi.fn(() => { return undefined }) - const mockWrite = jest.fn() + const mockWrite = vi.fn() const generator = { - destinationPath: jest.fn(() => 'some-path'), + destinationPath: vi.fn(() => 'some-path'), fs: { readJSON: mockRead, writeJSON: mockWrite @@ -221,12 +221,12 @@ describe('addDependencies', () => { expect(mockWrite).toHaveBeenCalledWith('some-path', { devDependencies: { a: 'b', c: 'd' } }) }) test('adds and overwrites dependencies in package.json', () => { - const mockRead = jest.fn(() => { + const mockRead = vi.fn(() => { return { dependencies: { a: 'fake', e: 'f' }, devDependencies: { g: 'h' } } }) - const mockWrite = jest.fn() + const mockWrite = vi.fn() const generator = { - destinationPath: jest.fn(() => 'some-path'), + destinationPath: vi.fn(() => 'some-path'), fs: { readJSON: mockRead, writeJSON: mockWrite @@ -242,12 +242,12 @@ describe('addDependencies', () => { }) test('adds and overwrites devDependencies in package.json', () => { - const mockRead = jest.fn(() => { + const mockRead = vi.fn(() => { return { devDependencies: { a: 'fake', e: 'f' }, dependencies: { g: 'h' } } }) - const mockWrite = jest.fn() + const mockWrite = vi.fn() const generator = { - destinationPath: jest.fn(() => 'some-path'), + destinationPath: vi.fn(() => 'some-path'), fs: { readJSON: mockRead, writeJSON: mockWrite @@ -263,15 +263,15 @@ describe('addDependencies', () => { }) test('appendStubVarsToDotenv existing label', () => { - const mockRead = jest.fn(() => '# label') - const mockExists = jest.fn(() => { + const mockRead = vi.fn(() => '# label') + const mockExists = vi.fn(() => { return true }) const generator = { - destinationPath: jest.fn(() => 'some-path'), + destinationPath: vi.fn(() => 'some-path'), fs: { read: mockRead, - append: jest.fn(), + append: vi.fn(), exists: mockExists } } @@ -281,15 +281,15 @@ describe('addDependencies', () => { }) test('appendStubVarsToDotenv', () => { - const mockRead = jest.fn(() => '') - const mockExists = jest.fn(() => { + const mockRead = vi.fn(() => '') + const mockExists = vi.fn(() => { return false }) const generator = { - destinationPath: jest.fn(() => 'some-path'), + destinationPath: vi.fn(() => 'some-path'), fs: { read: mockRead, - append: jest.fn(), + append: vi.fn(), exists: mockExists } } @@ -333,11 +333,11 @@ describe('addDependencies', () => { }) test('writeKeyAppConfig', () => { const generator = { - destinationPath: jest.fn(() => 'some-path'), + destinationPath: vi.fn(() => 'some-path'), fs: { - exists: jest.fn().mockImplementationOnce(() => true), - write: jest.fn(), - read: jest.fn() + exists: vi.fn().mockImplementationOnce(() => true), + write: vi.fn(), + read: vi.fn(() => 'existingKey: existingValue') } } utils.writeKeyAppConfig(generator, 'key', 'value') @@ -345,28 +345,28 @@ test('writeKeyAppConfig', () => { }) test('readYAMLConfig, configPath doesnt exists', () => { const generator = { - destinationPath: jest.fn(() => 'some-path'), + destinationPath: vi.fn(() => 'some-path'), fs: { - exists: jest.fn().mockImplementationOnce(() => false), - write: jest.fn(), - read: jest.fn() + exists: vi.fn().mockImplementationOnce(() => false), + write: vi.fn(), + read: vi.fn() } } expect(utils.readYAMLConfig(generator, 'some-path')).toStrictEqual({}) }) test('appendVarsToDotenv without previous content', () => { - const mockRead = jest.fn(() => '') - const mockExists = jest.fn(() => { + const mockRead = vi.fn(() => '') + const mockExists = vi.fn(() => { return false }) const generator = { - destinationPath: jest.fn(() => 'some-path'), + destinationPath: vi.fn(() => 'some-path'), fs: { read: mockRead, - append: jest.fn(), + append: vi.fn(), exists: mockExists, - write: jest.fn() + write: vi.fn() } } @@ -377,17 +377,17 @@ variable-a=value-a }) test('appendVarsToDotenv with previous content', () => { - const mockRead = jest.fn(() => 'variable-a=value-a') - const mockExists = jest.fn(() => { + const mockRead = vi.fn(() => 'variable-a=value-a') + const mockExists = vi.fn(() => { return true }) const generator = { - destinationPath: jest.fn(() => 'some-path'), + destinationPath: vi.fn(() => 'some-path'), fs: { read: mockRead, - append: jest.fn(), + append: vi.fn(), exists: mockExists, - write: jest.fn() + write: vi.fn() } } diff --git a/test/jest.setup.js b/test/vitest.setup.js similarity index 92% rename from test/jest.setup.js rename to test/vitest.setup.js index e95321d..9a5176f 100644 --- a/test/jest.setup.js +++ b/test/vitest.setup.js @@ -9,8 +9,9 @@ OF ANY KIND, either express or implied. See the License for the specific languag governing permissions and limitations under the License. */ -const path = require('path') -const { stdout, stderr } = require('stdout-stderr') +import path from 'node:path' +import { stdout, stderr } from 'stdout-stderr' +import { beforeEach, afterEach, expect } from 'vitest' process.on('unhandledRejection', error => { throw error diff --git a/vitest.config.js b/vitest.config.js new file mode 100644 index 0000000..58b4ca4 --- /dev/null +++ b/vitest.config.js @@ -0,0 +1,38 @@ +/* +Copyright 2024 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', + setupFiles: ['./test/vitest.setup.js'], + // only pick up the real test suites under test/ (lib/ holds template payloads + // like common-templates/utils.test.js that must not run) — mirrors the old + // jest testPathIgnorePatterns: ['/lib/'] + include: ['test/**/*.test.js'], + coverage: { + provider: 'v8', + all: true, + reporter: ['text', 'json-summary', 'html'], + // mirror jest collectCoverageFrom: ['lib/**/*.js', '!lib/common-templates/*.js'] + include: ['lib/**/*.js'], + exclude: ['lib/common-templates/**'], + thresholds: { + branches: 100, + functions: 100, + lines: 100, + statements: 100 + } + } + } +})