From 2090a45742797aa926d989a978ea4d931be5fad8 Mon Sep 17 00:00:00 2001 From: Michael Date: Fri, 2 Aug 2024 15:04:22 +0200 Subject: [PATCH 01/13] feat(nx-plugin): extend config generator --- packages/nx-plugin/package.json | 3 +- ...ode-pushup-config.integration.test.ts.snap | 20 ++ .../code-pushup-config.unit.test.ts.snap | 20 ++ .../code-pushup-config.integration.test.ts | 42 +++ .../configuration/code-pushup-config.ts | 71 +++++ .../code-pushup-config.unit.test.ts | 279 ++++++++++++++++++ .../files/code-pushup.config.ts.template | 15 +- .../generator.integration.test.ts | 115 ++------ .../src/generators/configuration/generator.ts | 40 +-- .../src/generators/configuration/types.ts | 6 + .../src/generators/configuration/utils.ts | 62 ++++ .../configuration/utils.unit.test.ts | 47 +++ packages/utils/src/index.ts | 7 +- packages/utils/src/lib/types.ts | 8 + 14 files changed, 598 insertions(+), 137 deletions(-) create mode 100644 packages/nx-plugin/src/generators/configuration/__snapshots__/code-pushup-config.integration.test.ts.snap create mode 100644 packages/nx-plugin/src/generators/configuration/__snapshots__/code-pushup-config.unit.test.ts.snap create mode 100644 packages/nx-plugin/src/generators/configuration/code-pushup-config.integration.test.ts create mode 100644 packages/nx-plugin/src/generators/configuration/code-pushup-config.ts create mode 100644 packages/nx-plugin/src/generators/configuration/code-pushup-config.unit.test.ts create mode 100644 packages/nx-plugin/src/generators/configuration/types.ts create mode 100644 packages/nx-plugin/src/generators/configuration/utils.ts create mode 100644 packages/nx-plugin/src/generators/configuration/utils.unit.test.ts diff --git a/packages/nx-plugin/package.json b/packages/nx-plugin/package.json index 09a2a1a48..aca7ecf07 100644 --- a/packages/nx-plugin/package.json +++ b/packages/nx-plugin/package.json @@ -7,7 +7,8 @@ "tslib": "2.6.2", "nx": "^17.1.3", "@code-pushup/models": "*", - "zod": "^3.22.4" + "zod": "^3.22.4", + "@code-pushup/utils": "*" }, "type": "commonjs", "main": "./src/index.js", diff --git a/packages/nx-plugin/src/generators/configuration/__snapshots__/code-pushup-config.integration.test.ts.snap b/packages/nx-plugin/src/generators/configuration/__snapshots__/code-pushup-config.integration.test.ts.snap new file mode 100644 index 000000000..29dd9a2c9 --- /dev/null +++ b/packages/nx-plugin/src/generators/configuration/__snapshots__/code-pushup-config.integration.test.ts.snap @@ -0,0 +1,20 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`generateCodePushupConfig options > should create code-pushup.config.ts with options in tree 1`] = ` +"import type { CoreConfig } from '../dist/packages/models; +import * as myPlugin from my-plugin"; +import {myPluginCategory} from "my-plugin"; + +// see: https://github.com/code-pushup/cli/blob/main/packages/models/docs/models-reference.md#coreconfig +export default { + persist: { + filename: "report-123" +}, + update: { + apiKey: "123" +}, + plugins: [myPlugin({ timeout: 42})], + categories: [myPluginCategory()] +} satisfies CoreConfig; +" +`; diff --git a/packages/nx-plugin/src/generators/configuration/__snapshots__/code-pushup-config.unit.test.ts.snap b/packages/nx-plugin/src/generators/configuration/__snapshots__/code-pushup-config.unit.test.ts.snap new file mode 100644 index 000000000..68580cf7f --- /dev/null +++ b/packages/nx-plugin/src/generators/configuration/__snapshots__/code-pushup-config.unit.test.ts.snap @@ -0,0 +1,20 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`generateCodePushupConfig options > should create code-pushup.config.ts with options 1`] = ` +{ + "options": { + "categories": "[myPluginCategory()]", + "fileImports": "import type { CoreConfig } from 'dist/packages/models'; +import * as myPlugin from 'my-plugin'; +import {myPluginCategory} from 'my-plugin';", + "persist": "{ + filename: "report-123" +}", + "plugins": "[myPlugin({ timeout: 42})]", + "upload": "{ + apiKey: "123" +}", + }, + "target": "test-app", +} +`; diff --git a/packages/nx-plugin/src/generators/configuration/code-pushup-config.integration.test.ts b/packages/nx-plugin/src/generators/configuration/code-pushup-config.integration.test.ts new file mode 100644 index 000000000..c28add6a3 --- /dev/null +++ b/packages/nx-plugin/src/generators/configuration/code-pushup-config.integration.test.ts @@ -0,0 +1,42 @@ +import * as devKit from '@nx/devkit'; +import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; +import { join } from 'node:path'; +import { describe, expect, it } from 'vitest'; +import { generateCodePushupConfig } from './code-pushup-config'; + +describe('generateCodePushupConfig options', () => { + let tree: devKit.Tree; + const project = 'test-app'; + const projectRoot = join('libs', project); + + beforeEach(() => { + tree = createTreeWithEmptyWorkspace(); + devKit.addProjectConfiguration(tree, project, { + root: 'test-app', + }); + }); + + it('should create code-pushup.config.ts with options in tree', () => { + generateCodePushupConfig(tree, projectRoot, { + fileImports: "import type { CoreConfig } from '../dist/packages/models;", + persist: { filename: 'report-123' }, + upload: { apiKey: '123' }, + plugins: [ + { + fileImports: 'import * as myPlugin from "my-plugin";', + codeStrings: 'myPlugin({ timeout: 42})', + }, + ], + categories: [ + { + fileImports: 'import {myPluginCategory} from "my-plugin";', + codeStrings: 'myPluginCategory()', + }, + ], + }); + + expect( + tree.read(join(projectRoot, 'code-pushup.config.ts'))?.toString(), + ).toMatchSnapshot(); + }); +}); diff --git a/packages/nx-plugin/src/generators/configuration/code-pushup-config.ts b/packages/nx-plugin/src/generators/configuration/code-pushup-config.ts new file mode 100644 index 000000000..f62a5a323 --- /dev/null +++ b/packages/nx-plugin/src/generators/configuration/code-pushup-config.ts @@ -0,0 +1,71 @@ +import { Tree, generateFiles } from '@nx/devkit'; +import { join } from 'node:path'; +import type { PersistConfig, UploadConfig } from '@code-pushup/models'; +import type { ItemOrArray } from '@code-pushup/utils'; +import { ExecutableCode } from './types'; +import { + formatArrayToJSArray, + formatArrayToLinesOfJsString, + formatObjectToFormattedJsString, + normalizeExecutableCode, + normalizeItemOrArray, +} from './utils'; + +export const DEFAULT_IMPORTS = [ + "import type { CoreConfig } from '@code-pushup/models;'", +]; + +export type GenerateCodePushupConfigOptions = { + fileImports?: ItemOrArray; + persist?: Partial; + upload?: Partial; + plugins?: ExecutableCode[]; + categories?: ExecutableCode[]; +}; + +export function generateCodePushupConfig( + tree: Tree, + root: string, + options?: GenerateCodePushupConfigOptions, +) { + const supportedFormats = ['ts', 'mjs', 'js']; + const firstExistingFormat = supportedFormats.find(ext => + tree.exists(join(root, `code-pushup.config.${ext}`)), + ); + if (firstExistingFormat) { + console.warn( + `NOTE: No config file created as code-pushup.config.${firstExistingFormat} file already exists.`, + ); + } else { + const { + fileImports: rawImports, + persist, + upload, + plugins: rawPlugins = [], // plugins are required + categories: rawCategories, + } = options ?? {}; + + const plugins = rawPlugins.map(normalizeExecutableCode); + const categories = rawCategories?.map(normalizeExecutableCode); + const configFileImports = [ + ...(normalizeItemOrArray(rawImports) ?? DEFAULT_IMPORTS), + ...plugins.flatMap(({ fileImports }) => fileImports), + ...(categories ?? []).flatMap(({ fileImports }) => fileImports), + ]; + + generateFiles(tree, join(__dirname, 'files'), root, { + ...options, + fileImports: formatArrayToLinesOfJsString(configFileImports), + persist: formatObjectToFormattedJsString(persist), + upload: formatObjectToFormattedJsString(upload), + plugins: formatArrayToJSArray( + plugins.flatMap(({ codeStrings }) => codeStrings), + ), + categories: + categories && + formatArrayToJSArray( + categories.flatMap(({ codeStrings }) => codeStrings), + ), + }); + } +} diff --git a/packages/nx-plugin/src/generators/configuration/code-pushup-config.unit.test.ts b/packages/nx-plugin/src/generators/configuration/code-pushup-config.unit.test.ts new file mode 100644 index 000000000..3c75d40c5 --- /dev/null +++ b/packages/nx-plugin/src/generators/configuration/code-pushup-config.unit.test.ts @@ -0,0 +1,279 @@ +import * as devKit from '@nx/devkit'; +import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; +import { join } from 'node:path'; +import { afterEach, describe, expect, it } from 'vitest'; +import { + DEFAULT_IMPORTS, + generateCodePushupConfig, +} from './code-pushup-config'; +import { + formatArrayToJSArray, + formatArrayToLinesOfJsString, + formatObjectToFormattedJsString, + normalizeExecutableCode, +} from './utils'; + +describe('generateCodePushupConfig options', () => { + let tree: devKit.Tree; + const testProjectName = 'test-app'; + const generateFilesSpy = vi.spyOn(devKit, 'generateFiles'); + + beforeEach(() => { + tree = createTreeWithEmptyWorkspace(); + devKit.addProjectConfiguration(tree, testProjectName, { + root: 'test-app', + }); + }); + + afterEach(() => { + generateFilesSpy.mockReset(); + }); + + it('should create code-pushup.config.ts with options', () => { + generateFilesSpy.mockImplementation((...[_, __, target, options]) => { + expect({ target, options }).toMatchSnapshot(); + }); + + generateCodePushupConfig(tree, testProjectName, { + fileImports: ["import type { CoreConfig } from 'dist/packages/models';"], + persist: { filename: 'report-123' }, + upload: { apiKey: '123' }, + plugins: [ + { + fileImports: "import * as myPlugin from 'my-plugin';", + codeStrings: 'myPlugin({ timeout: 42})', + }, + ], + categories: [ + { + fileImports: "import {myPluginCategory} from 'my-plugin';", + codeStrings: 'myPluginCategory()', + }, + ], + }); + + expect(generateFilesSpy).toHaveBeenCalledWith( + expect.anything(), + expect.any(String), + expect.any(String), + expect.objectContaining({ + fileImports: formatArrayToLinesOfJsString([ + "import type { CoreConfig } from 'dist/packages/models';", + "import * as myPlugin from 'my-plugin';", + "import {myPluginCategory} from 'my-plugin';", + ]), + persist: formatObjectToFormattedJsString({ filename: 'report-123' }), + upload: formatObjectToFormattedJsString({ apiKey: '123' }), + plugins: formatArrayToJSArray(['myPlugin({ timeout: 42})']), + categories: formatArrayToJSArray(['myPluginCategory()']), + }), + ); + }); + + it('should call generateFilesSpy', () => { + generateCodePushupConfig(tree, testProjectName); + expect(generateFilesSpy).toHaveBeenCalledTimes(1); + }); + + it('should use correct templates', () => { + generateCodePushupConfig(tree, testProjectName); + expect(generateFilesSpy).toHaveBeenCalledWith( + expect.anything(), + expect.stringContaining( + join('nx-plugin', 'src', 'generators', 'configuration', 'files'), + ), + expect.any(String), + expect.any(Object), + ); + }); + + it('should use correct testProjectName', () => { + generateCodePushupConfig(tree, testProjectName); + expect(generateFilesSpy).toHaveBeenCalledWith( + expect.anything(), + expect.any(String), + testProjectName, + expect.any(Object), + ); + }); + + it('should use default options', () => { + generateCodePushupConfig(tree, testProjectName); + expect(generateFilesSpy).toHaveBeenCalledWith( + expect.anything(), + expect.any(String), + expect.any(String), + { + categories: undefined, + fileImports: formatArrayToLinesOfJsString(DEFAULT_IMPORTS), + persist: undefined, + plugins: formatArrayToJSArray([]), + upload: undefined, + }, + ); + }); + + it('should use fileImports options', () => { + generateCodePushupConfig(tree, testProjectName, { + fileImports: [ + "import type { CoreConfig } from '../../dist/packages/models';", + ], + }); + expect(generateFilesSpy).toHaveBeenCalledWith( + expect.anything(), + expect.any(String), + expect.any(String), + expect.objectContaining({ + fileImports: formatArrayToLinesOfJsString([ + "import type { CoreConfig } from '../../dist/packages/models';", + ]), + }), + ); + }); + + it('should use persist options', () => { + generateCodePushupConfig(tree, testProjectName, { + persist: { + filename: 'test-report', + outputDir: 'tmp/results', + format: ['md'], + }, + }); + expect(generateFilesSpy).toHaveBeenCalledWith( + expect.anything(), + expect.any(String), + expect.any(String), + expect.objectContaining({ + persist: formatObjectToFormattedJsString({ + filename: 'test-report', + outputDir: 'tmp/results', + format: ['md'], + }), + }), + ); + }); + + it('should use upload options', () => { + generateCodePushupConfig(tree, testProjectName, { + upload: { + organization: 'code-pushup', + project: 'cli', + server: 'https://code-pushup.dev/portal', + apiKey: '12345678', + }, + }); + expect(generateFilesSpy).toHaveBeenCalledWith( + expect.anything(), + expect.any(String), + expect.any(String), + expect.objectContaining({ + upload: formatObjectToFormattedJsString({ + organization: 'code-pushup', + project: 'cli', + server: 'https://code-pushup.dev/portal', + apiKey: '12345678', + }), + }), + ); + }); + + it('should use plugins options', () => { + generateCodePushupConfig(tree, testProjectName, { + plugins: [ + { + fileImports: 'import * as myPlugin from "my-import";', + codeStrings: 'myPlugin({ timeout: 42})', + }, + ], + }); + expect(generateFilesSpy).toHaveBeenCalledWith( + expect.anything(), + expect.any(String), + expect.any(String), + expect.objectContaining({ + fileImports: formatArrayToLinesOfJsString([ + ...DEFAULT_IMPORTS, + 'import * as myPlugin from "my-import";', + ]), + plugins: formatArrayToJSArray(['myPlugin({ timeout: 42})']), + }), + ); + }); + + it('should use categories options', () => { + generateCodePushupConfig(tree, testProjectName, { + categories: [ + { + fileImports: 'import {defaultCategory} from "my-plugin";', + codeStrings: 'defaultCategory()', + }, + ], + }); + expect(generateFilesSpy).toHaveBeenCalledWith( + expect.anything(), + expect.any(String), + expect.any(String), + expect.objectContaining({ + fileImports: formatArrayToLinesOfJsString([ + ...DEFAULT_IMPORTS, + 'import {defaultCategory} from "my-plugin";', + ]), + categories: formatArrayToJSArray(['defaultCategory()']), + }), + ); + }); +}); + +describe('normalizeExecutableCode', () => { + it('should normalize fileImports as string', () => { + expect( + normalizeExecutableCode({ + fileImports: 'import * as test from "test"', + codeStrings: 'plugin()', + }), + ).toStrictEqual( + expect.objectContaining({ + fileImports: ['import * as test from "test"'], + }), + ); + }); + + it('should normalize fileImports as array', () => { + expect( + normalizeExecutableCode({ + fileImports: ['import * as test from "test"'], + codeStrings: 'plugin()', + }), + ).toStrictEqual( + expect.objectContaining({ + fileImports: ['import * as test from "test"'], + }), + ); + }); + + it('should normalize codeStrings as string', () => { + expect( + normalizeExecutableCode({ + fileImports: 'import * as test from "test"', + codeStrings: 'plugin()', + }), + ).toStrictEqual( + expect.objectContaining({ + codeStrings: ['plugin()'], + }), + ); + }); + + it('should normalize codeStrings as array', () => { + expect( + normalizeExecutableCode({ + fileImports: 'import * as test from "test"', + codeStrings: ['plugin()'], + }), + ).toStrictEqual( + expect.objectContaining({ + codeStrings: ['plugin()'], + }), + ); + }); +}); diff --git a/packages/nx-plugin/src/generators/configuration/files/code-pushup.config.ts.template b/packages/nx-plugin/src/generators/configuration/files/code-pushup.config.ts.template index 870d05674..42da5a08d 100644 --- a/packages/nx-plugin/src/generators/configuration/files/code-pushup.config.ts.template +++ b/packages/nx-plugin/src/generators/configuration/files/code-pushup.config.ts.template @@ -1,10 +1,9 @@ -import type { CoreConfig } from '@code-pushup/models'; +<%- fileImports %> // see: https://github.com/code-pushup/cli/blob/main/packages/models/docs/models-reference.md#coreconfig -const config: CoreConfig = { - plugins: [ - // ... - ] -}; - -export default config; +export default { + <% if (persist) { %>persist: <%- persist %>,<% } %> + <% if (upload) { %>update: <%- upload %>,<% } %> + <% if (plugins) { %>plugins: <%- plugins %>,<% } %> + <% if (categories) { %>categories: <%- categories %><% } %> +} satisfies CoreConfig; diff --git a/packages/nx-plugin/src/generators/configuration/generator.integration.test.ts b/packages/nx-plugin/src/generators/configuration/generator.integration.test.ts index 66077f1f6..b44f8b06d 100644 --- a/packages/nx-plugin/src/generators/configuration/generator.integration.test.ts +++ b/packages/nx-plugin/src/generators/configuration/generator.integration.test.ts @@ -4,81 +4,9 @@ import { readProjectConfiguration, } from '@nx/devkit'; import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; -import { join } from 'node:path'; import { afterEach, describe, expect, it } from 'vitest'; -import { - addTargetToProject, - configurationGenerator, - generateCodePushupConfig, -} from './generator'; - -describe('generateCodePushupConfig', () => { - let tree: Tree; - const testProjectName = 'test-app'; - beforeEach(() => { - tree = createTreeWithEmptyWorkspace(); - addProjectConfiguration(tree, testProjectName, { - root: 'test-app', - }); - }); - - it('should add code-pushup.config.ts to the project root', () => { - generateCodePushupConfig( - tree, - { - root: testProjectName, - projectType: 'library', - sourceRoot: `${testProjectName}/src`, - targets: {}, - }, - { - project: testProjectName, - }, - ); - - expect(tree.exists('test-app/code-pushup.config.ts')).toBe(true); - expect( - tree.read('test-app/code-pushup.config.ts')?.toString(), - ).toMatchSnapshot(); - }); - - it('should skip code-pushup.config.ts generation if config in ts, mjs or js format already exists', () => { - tree.write(join('code-pushup.config.js'), 'export default {}'); - - generateCodePushupConfig( - tree, - { - root: testProjectName, - projectType: 'library', - sourceRoot: `${testProjectName}/src`, - targets: {}, - }, - { - project: testProjectName, - }, - ); - - expect(tree.exists('code-pushup.config.ts')).toBe(false); - }); - - it('should skip code-pushup.config.ts generation if skipConfig is given', () => { - generateCodePushupConfig( - tree, - { - root: testProjectName, - projectType: 'library', - sourceRoot: `${testProjectName}/src`, - targets: {}, - }, - { - project: testProjectName, - skipConfig: true, - }, - ); - - expect(tree.exists('code-pushup.config.ts')).toBe(false); - }); -}); +import { DEFAULT_TARGET_NAME } from '../../internal/constants'; +import { addTargetToProject, configurationGenerator } from './generator'; describe('addTargetToProject', () => { let tree: Tree; @@ -113,7 +41,7 @@ describe('addTargetToProject', () => { testProjectName, ); - expect(projectConfiguration.targets?.['code-pushup']).toEqual({ + expect(projectConfiguration.targets?.[DEFAULT_TARGET_NAME]).toEqual({ executor: '@code-pushup/nx-plugin:autorun', }); }); @@ -142,28 +70,6 @@ describe('addTargetToProject', () => { executor: '@code-pushup/nx-plugin:autorun', }); }); - - it('should skip target creation if skipTarget is used', () => { - addTargetToProject( - tree, - { - root: testProjectName, - projectType: 'library', - sourceRoot: `${testProjectName}/src`, - targets: {}, - }, - { - project: testProjectName, - skipTarget: true, - }, - ); - - const projectConfiguration = readProjectConfiguration( - tree, - testProjectName, - ); - expect(projectConfiguration.targets).toBeUndefined(); - }); }); describe('configurationGenerator', () => { @@ -190,8 +96,21 @@ describe('configurationGenerator', () => { testProjectName, ); - expect(projectConfiguration.targets?.['code-pushup']).toEqual({ + expect(projectConfiguration.targets?.[DEFAULT_TARGET_NAME]).toEqual({ executor: '@code-pushup/nx-plugin:autorun', }); }); + + it('should skip target creation if skipTarget is used', async () => { + await configurationGenerator(tree, { + project: testProjectName, + skipTarget: true, + }); + + const projectConfiguration = readProjectConfiguration( + tree, + testProjectName, + ); + expect(projectConfiguration.targets).toBeUndefined(); + }); }); diff --git a/packages/nx-plugin/src/generators/configuration/generator.ts b/packages/nx-plugin/src/generators/configuration/generator.ts index 51071b03e..2f7bd3c24 100644 --- a/packages/nx-plugin/src/generators/configuration/generator.ts +++ b/packages/nx-plugin/src/generators/configuration/generator.ts @@ -1,13 +1,12 @@ import { Tree, formatFiles, - generateFiles, readProjectConfiguration, updateProjectConfiguration, } from '@nx/devkit'; -import { join } from 'node:path'; import { ProjectConfiguration } from 'nx/src/config/workspace-json-project-json'; import { DEFAULT_TARGET_NAME } from '../../internal/constants'; +import { generateCodePushupConfig } from './code-pushup-config'; import { ConfigurationGeneratorOptions } from './schema'; export async function configurationGenerator( @@ -16,9 +15,15 @@ export async function configurationGenerator( ) { const projectConfiguration = readProjectConfiguration(tree, options.project); - generateCodePushupConfig(tree, projectConfiguration, options); + const { skipConfig, skipTarget } = options; - addTargetToProject(tree, projectConfiguration, options); + if (skipConfig !== true) { + generateCodePushupConfig(tree, projectConfiguration.root); + } + + if (skipTarget !== true) { + addTargetToProject(tree, projectConfiguration, options); + } await formatFiles(tree); } @@ -29,14 +34,10 @@ export function addTargetToProject( options: ConfigurationGeneratorOptions, ) { const { targets } = projectConfiguration; - const { targetName, project, skipTarget } = options; - - if (skipTarget) { - return; - } + const { targetName, project } = options; const codePushupTargetConfig = { - executor: '@code-pushup/nx-plugin:autorun', + executor: `@code-pushup/nx-plugin:autorun`, }; updateProjectConfiguration(tree, project, { @@ -48,23 +49,4 @@ export function addTargetToProject( }); } -export function generateCodePushupConfig( - tree: Tree, - projectConfiguration: ProjectConfiguration, - options: ConfigurationGeneratorOptions, -) { - const { root } = projectConfiguration; - const supportedFormats = ['ts', 'mjs', 'js']; - const firstExistingFormat = supportedFormats.find(ext => - tree.exists(join(root, `code-pushup.config.${ext}`)), - ); - if (firstExistingFormat) { - console.warn( - `NOTE: No config file created as code-pushup.config.${firstExistingFormat} file already exists.`, - ); - } else { - generateFiles(tree, join(__dirname, 'files'), root, options); - } -} - export default configurationGenerator; diff --git a/packages/nx-plugin/src/generators/configuration/types.ts b/packages/nx-plugin/src/generators/configuration/types.ts new file mode 100644 index 000000000..99451ced8 --- /dev/null +++ b/packages/nx-plugin/src/generators/configuration/types.ts @@ -0,0 +1,6 @@ +import type { ItemOrArray } from '@code-pushup/utils'; + +export type ExecutableCode = { + fileImports: ItemOrArray; + codeStrings: ItemOrArray; +}; diff --git a/packages/nx-plugin/src/generators/configuration/utils.ts b/packages/nx-plugin/src/generators/configuration/utils.ts new file mode 100644 index 000000000..a79055d64 --- /dev/null +++ b/packages/nx-plugin/src/generators/configuration/utils.ts @@ -0,0 +1,62 @@ +import type { ExtractArrays } from '@code-pushup/utils'; +import type { ExecutableCode } from './types'; + +export function normalizeExecutableCode( + executableCode: ExecutableCode, +): ExtractArrays { + const { fileImports: rawFileImports, codeStrings: rawCodeStrings } = + executableCode; + + return { + fileImports: normalizeItemOrArray(rawFileImports) ?? [], + codeStrings: normalizeItemOrArray(rawCodeStrings) ?? [], + }; +} + +export function normalizeItemOrArray( + itemOrArray: T | T[] | undefined, +): T[] | undefined { + if (itemOrArray == null) { + return undefined; + } + if (Array.isArray(itemOrArray)) { + return itemOrArray; + } + return [itemOrArray]; +} + +// Return a formatted JSON in TS object with the same keys as the input object but remove the " for the properties +export function formatObjectToFormattedJsString( + jsonObj?: + | { + [key: string]: unknown; + } + | Array, +): string | undefined { + if (!jsonObj) { + return; + } + // Convert JSON object to a string with indentation + const jsonString = JSON.stringify(jsonObj, null, 2); + + // Remove double quotes around property names + return jsonString.replace(/"(\w+)":/g, '$1:'); +} + +export function formatArrayToLinesOfJsString( + lines?: string[], + separator = '\n', +) { + if (lines == null || lines.length === 0) { + return; + } + return `${lines.join(separator).replace('"', '')}`; +} + +export function formatArrayToJSArray(lines?: string[]) { + if (lines == null) { + return; + } + + return `[${formatArrayToLinesOfJsString(lines, ',\n') ?? ''}]`; +} diff --git a/packages/nx-plugin/src/generators/configuration/utils.unit.test.ts b/packages/nx-plugin/src/generators/configuration/utils.unit.test.ts new file mode 100644 index 000000000..8aefff9ba --- /dev/null +++ b/packages/nx-plugin/src/generators/configuration/utils.unit.test.ts @@ -0,0 +1,47 @@ +import { describe, expect, it } from 'vitest'; +import { formatArrayToJSArray, formatArrayToLinesOfJsString } from './utils'; + +describe('formatArrayToJSArray', () => { + it('should return array as JS', () => { + expect( + formatArrayToJSArray(['plugin1()', 'plugin2()']), + ).toMatchInlineSnapshot( + ` + "[plugin1(), + plugin2()]" + `, + ); + }); + + it('should return empty array as JS for empty items', () => { + expect(formatArrayToJSArray([])).toMatchInlineSnapshot('"[]"'); + }); + + it('should return undefined for nullish values', () => { + expect(formatArrayToJSArray()).toBeUndefined(); + }); +}); + +describe('formatArrayToLinesOfJsString', () => { + it('should return lines as JS', () => { + expect( + formatArrayToLinesOfJsString([ + "import { CoreConfig } from '@code-pushup/models';", + "import plugin from '../mx-plugin';", + ]), + ).toMatchInlineSnapshot( + ` + "import { CoreConfig } from '@code-pushup/models'; + import plugin from '../mx-plugin';" + `, + ); + }); + + it('should return undefined for empty items', () => { + expect(formatArrayToLinesOfJsString([])).toBeUndefined(); + }); + + it('should return undefined for nullish values', () => { + expect(formatArrayToLinesOfJsString()).toBeUndefined(); + }); +}); diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts index 5c5f8f469..34dd2eea8 100644 --- a/packages/utils/src/index.ts +++ b/packages/utils/src/index.ts @@ -102,5 +102,10 @@ export { toUnixNewlines, toUnixPath, } from './lib/transform'; -export { ExcludeNullFromPropertyTypes } from './lib/types'; +export { + ExcludeNullFromPropertyTypes, + ExtractArrays, + ExtractArray, + ItemOrArray, +} from './lib/types'; export { verboseUtils } from './lib/verbose-utils'; diff --git a/packages/utils/src/lib/types.ts b/packages/utils/src/lib/types.ts index 84b76ebd4..6874bebd5 100644 --- a/packages/utils/src/lib/types.ts +++ b/packages/utils/src/lib/types.ts @@ -1,3 +1,11 @@ export type ExcludeNullFromPropertyTypes = { [P in keyof T]: Exclude; }; + +export type ItemOrArray = T | T[]; + +export type ExtractArray = T extends Array ? T : never; + +export type ExtractArrays> = { + [K in keyof T]: ExtractArray; +}; From 3ff2e5ada6fea3b999e81ff9d5cac7520bfde107 Mon Sep 17 00:00:00 2001 From: Michael Hladky <10064416+BioPhoton@users.noreply.github.com> Date: Fri, 2 Aug 2024 15:08:52 +0200 Subject: [PATCH 02/13] Update packages/nx-plugin/src/generators/configuration/generator.ts --- packages/nx-plugin/src/generators/configuration/generator.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nx-plugin/src/generators/configuration/generator.ts b/packages/nx-plugin/src/generators/configuration/generator.ts index 2f7bd3c24..a94f2db95 100644 --- a/packages/nx-plugin/src/generators/configuration/generator.ts +++ b/packages/nx-plugin/src/generators/configuration/generator.ts @@ -37,7 +37,7 @@ export function addTargetToProject( const { targetName, project } = options; const codePushupTargetConfig = { - executor: `@code-pushup/nx-plugin:autorun`, + executor: '@code-pushup/nx-plugin:autorun', }; updateProjectConfiguration(tree, project, { From 65a5106a39bda706b0a55961a0adef8f70e8d1a6 Mon Sep 17 00:00:00 2001 From: Michael Date: Fri, 2 Aug 2024 15:37:31 +0200 Subject: [PATCH 03/13] test(nx-plugin): add tests --- .../configuration/code-pushup-config.ts | 4 +-- .../code-pushup-config.unit.test.ts | 14 ++++++++ .../configuration/utils.unit.test.ts | 32 ++++++++++++++++++- 3 files changed, 47 insertions(+), 3 deletions(-) diff --git a/packages/nx-plugin/src/generators/configuration/code-pushup-config.ts b/packages/nx-plugin/src/generators/configuration/code-pushup-config.ts index f62a5a323..3055425da 100644 --- a/packages/nx-plugin/src/generators/configuration/code-pushup-config.ts +++ b/packages/nx-plugin/src/generators/configuration/code-pushup-config.ts @@ -1,4 +1,4 @@ -import { Tree, generateFiles } from '@nx/devkit'; +import { Tree, generateFiles, logger } from '@nx/devkit'; import { join } from 'node:path'; import type { PersistConfig, UploadConfig } from '@code-pushup/models'; import type { ItemOrArray } from '@code-pushup/utils'; @@ -33,7 +33,7 @@ export function generateCodePushupConfig( tree.exists(join(root, `code-pushup.config.${ext}`)), ); if (firstExistingFormat) { - console.warn( + logger.warn( `NOTE: No config file created as code-pushup.config.${firstExistingFormat} file already exists.`, ); } else { diff --git a/packages/nx-plugin/src/generators/configuration/code-pushup-config.unit.test.ts b/packages/nx-plugin/src/generators/configuration/code-pushup-config.unit.test.ts index 3c75d40c5..be7a917c9 100644 --- a/packages/nx-plugin/src/generators/configuration/code-pushup-config.unit.test.ts +++ b/packages/nx-plugin/src/generators/configuration/code-pushup-config.unit.test.ts @@ -2,6 +2,7 @@ import * as devKit from '@nx/devkit'; import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; import { join } from 'node:path'; import { afterEach, describe, expect, it } from 'vitest'; +import { removeColorCodes } from '@code-pushup/test-utils'; import { DEFAULT_IMPORTS, generateCodePushupConfig, @@ -17,6 +18,7 @@ describe('generateCodePushupConfig options', () => { let tree: devKit.Tree; const testProjectName = 'test-app'; const generateFilesSpy = vi.spyOn(devKit, 'generateFiles'); + const loggerWarnSpy = vi.spyOn(devKit.logger, 'warn'); beforeEach(() => { tree = createTreeWithEmptyWorkspace(); @@ -75,6 +77,18 @@ describe('generateCodePushupConfig options', () => { expect(generateFilesSpy).toHaveBeenCalledTimes(1); }); + it('should skip creation if config already exists', () => { + tree.write(join(testProjectName, 'code-pushup.config.js'), ''); + generateCodePushupConfig(tree, testProjectName); + expect(generateFilesSpy).toHaveBeenCalledTimes(0); + expect(loggerWarnSpy).toHaveBeenCalledTimes(1); + expect(loggerWarnSpy).toHaveBeenCalledWith( + removeColorCodes( + 'NOTE: No config file created as code-pushup.config.js file already exists.', + ), + ); + }); + it('should use correct templates', () => { generateCodePushupConfig(tree, testProjectName); expect(generateFilesSpy).toHaveBeenCalledWith( diff --git a/packages/nx-plugin/src/generators/configuration/utils.unit.test.ts b/packages/nx-plugin/src/generators/configuration/utils.unit.test.ts index 8aefff9ba..ac024df73 100644 --- a/packages/nx-plugin/src/generators/configuration/utils.unit.test.ts +++ b/packages/nx-plugin/src/generators/configuration/utils.unit.test.ts @@ -1,5 +1,9 @@ import { describe, expect, it } from 'vitest'; -import { formatArrayToJSArray, formatArrayToLinesOfJsString } from './utils'; +import { + formatArrayToJSArray, + formatArrayToLinesOfJsString, + normalizeExecutableCode, +} from './utils'; describe('formatArrayToJSArray', () => { it('should return array as JS', () => { @@ -45,3 +49,29 @@ describe('formatArrayToLinesOfJsString', () => { expect(formatArrayToLinesOfJsString()).toBeUndefined(); }); }); + +describe('normalizeExecutableCode', () => { + it('should return turn strings into arrays', () => { + expect( + normalizeExecutableCode({ + fileImports: 'import { CoreConfig } from "@code-pushup/models";', + codeStrings: 'myPlugin()', + }), + ).toStrictEqual({ + fileImports: ['import { CoreConfig } from "@code-pushup/models";'], + codeStrings: ['myPlugin()'], + }); + }); + + it('should keep arrays', () => { + expect( + normalizeExecutableCode({ + fileImports: ['import { CoreConfig } from "@code-pushup/models";'], + codeStrings: ['myPlugin()'], + }), + ).toStrictEqual({ + fileImports: ['import { CoreConfig } from "@code-pushup/models";'], + codeStrings: ['myPlugin()'], + }); + }); +}); From 06783944d4e67f720f2731fc504a920546fbd538 Mon Sep 17 00:00:00 2001 From: Michael Date: Fri, 2 Aug 2024 15:54:51 +0200 Subject: [PATCH 04/13] test(nx-plugin): add tests --- .../src/generators/configuration/code-pushup-config.ts | 2 +- packages/nx-plugin/src/generators/configuration/utils.ts | 7 ++++--- .../src/generators/configuration/utils.unit.test.ts | 4 ++-- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/packages/nx-plugin/src/generators/configuration/code-pushup-config.ts b/packages/nx-plugin/src/generators/configuration/code-pushup-config.ts index 3055425da..9c2f453c0 100644 --- a/packages/nx-plugin/src/generators/configuration/code-pushup-config.ts +++ b/packages/nx-plugin/src/generators/configuration/code-pushup-config.ts @@ -48,7 +48,7 @@ export function generateCodePushupConfig( const plugins = rawPlugins.map(normalizeExecutableCode); const categories = rawCategories?.map(normalizeExecutableCode); const configFileImports = [ - ...(normalizeItemOrArray(rawImports) ?? DEFAULT_IMPORTS), + ...(rawImports ? normalizeItemOrArray(rawImports) : DEFAULT_IMPORTS), ...plugins.flatMap(({ fileImports }) => fileImports), ...(categories ?? []).flatMap(({ fileImports }) => fileImports), ]; diff --git a/packages/nx-plugin/src/generators/configuration/utils.ts b/packages/nx-plugin/src/generators/configuration/utils.ts index a79055d64..8dd74e273 100644 --- a/packages/nx-plugin/src/generators/configuration/utils.ts +++ b/packages/nx-plugin/src/generators/configuration/utils.ts @@ -8,11 +8,12 @@ export function normalizeExecutableCode( executableCode; return { - fileImports: normalizeItemOrArray(rawFileImports) ?? [], - codeStrings: normalizeItemOrArray(rawCodeStrings) ?? [], + fileImports: normalizeItemOrArray(rawFileImports), + codeStrings: normalizeItemOrArray(rawCodeStrings), }; } +export function normalizeItemOrArray(itemOrArray: T | T[]): T[]; export function normalizeItemOrArray( itemOrArray: T | T[] | undefined, ): T[] | undefined { @@ -54,7 +55,7 @@ export function formatArrayToLinesOfJsString( } export function formatArrayToJSArray(lines?: string[]) { - if (lines == null) { + if (!Array.isArray(lines)) { return; } diff --git a/packages/nx-plugin/src/generators/configuration/utils.unit.test.ts b/packages/nx-plugin/src/generators/configuration/utils.unit.test.ts index ac024df73..bc03866f3 100644 --- a/packages/nx-plugin/src/generators/configuration/utils.unit.test.ts +++ b/packages/nx-plugin/src/generators/configuration/utils.unit.test.ts @@ -21,8 +21,8 @@ describe('formatArrayToJSArray', () => { expect(formatArrayToJSArray([])).toMatchInlineSnapshot('"[]"'); }); - it('should return undefined for nullish values', () => { - expect(formatArrayToJSArray()).toBeUndefined(); + it('should return undefined for undefined values', () => { + expect(formatArrayToJSArray(undefined)).toBeUndefined(); }); }); From 5efc3ceec470e3421df179e48956f7cbceb639d4 Mon Sep 17 00:00:00 2001 From: Michael Date: Fri, 2 Aug 2024 16:40:27 +0200 Subject: [PATCH 05/13] test(nx-plugin): add tests --- .../generators/configuration/utils.unit.test.ts | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/packages/nx-plugin/src/generators/configuration/utils.unit.test.ts b/packages/nx-plugin/src/generators/configuration/utils.unit.test.ts index bc03866f3..3d71e0468 100644 --- a/packages/nx-plugin/src/generators/configuration/utils.unit.test.ts +++ b/packages/nx-plugin/src/generators/configuration/utils.unit.test.ts @@ -3,6 +3,7 @@ import { formatArrayToJSArray, formatArrayToLinesOfJsString, normalizeExecutableCode, + normalizeItemOrArray, } from './utils'; describe('formatArrayToJSArray', () => { @@ -51,7 +52,7 @@ describe('formatArrayToLinesOfJsString', () => { }); describe('normalizeExecutableCode', () => { - it('should return turn strings into arrays', () => { + it('should turn strings into arrays', () => { expect( normalizeExecutableCode({ fileImports: 'import { CoreConfig } from "@code-pushup/models";', @@ -75,3 +76,16 @@ describe('normalizeExecutableCode', () => { }); }); }); + +describe('normalizeItemOrArray', () => { + it('should turn string into string array', () => { + expect(normalizeItemOrArray('myPlugin()')).toStrictEqual(['myPlugin()']); + }); + + it('should keep string array', () => { + expect(normalizeItemOrArray('myPlugin()')).toStrictEqual({ + fileImports: ['import { CoreConfig } from "@code-pushup/models";'], + codeStrings: ['myPlugin()'], + }); + }); +}); From a9a0c7b2f779dbd9c54f92a84ee36c7cf58ff3bb Mon Sep 17 00:00:00 2001 From: Michael Date: Fri, 2 Aug 2024 16:50:18 +0200 Subject: [PATCH 06/13] fix test --- .../src/generators/configuration/utils.unit.test.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/packages/nx-plugin/src/generators/configuration/utils.unit.test.ts b/packages/nx-plugin/src/generators/configuration/utils.unit.test.ts index 3d71e0468..eb8468c3c 100644 --- a/packages/nx-plugin/src/generators/configuration/utils.unit.test.ts +++ b/packages/nx-plugin/src/generators/configuration/utils.unit.test.ts @@ -83,9 +83,6 @@ describe('normalizeItemOrArray', () => { }); it('should keep string array', () => { - expect(normalizeItemOrArray('myPlugin()')).toStrictEqual({ - fileImports: ['import { CoreConfig } from "@code-pushup/models";'], - codeStrings: ['myPlugin()'], - }); + expect(normalizeItemOrArray('myPlugin()')).toStrictEqual(['myPlugin()']); }); }); From b0a4660e73a20ffb0aa25f0a5e15f93519e93599 Mon Sep 17 00:00:00 2001 From: Michael Hladky <10064416+BioPhoton@users.noreply.github.com> Date: Mon, 5 Aug 2024 12:52:32 +0200 Subject: [PATCH 07/13] Update packages/nx-plugin/src/generators/configuration/code-pushup-config.ts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Matěj Chalk <34691111+matejchalk@users.noreply.github.com> --- .../src/generators/configuration/code-pushup-config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nx-plugin/src/generators/configuration/code-pushup-config.ts b/packages/nx-plugin/src/generators/configuration/code-pushup-config.ts index 9c2f453c0..66cedd998 100644 --- a/packages/nx-plugin/src/generators/configuration/code-pushup-config.ts +++ b/packages/nx-plugin/src/generators/configuration/code-pushup-config.ts @@ -12,7 +12,7 @@ import { } from './utils'; export const DEFAULT_IMPORTS = [ - "import type { CoreConfig } from '@code-pushup/models;'", + "import type { CoreConfig } from '@code-pushup/models';", ]; export type GenerateCodePushupConfigOptions = { From a482a0a2d0af4de1178c2d01a1eecc0cb04df088 Mon Sep 17 00:00:00 2001 From: Michael Hladky <10064416+BioPhoton@users.noreply.github.com> Date: Mon, 5 Aug 2024 12:53:28 +0200 Subject: [PATCH 08/13] Update packages/nx-plugin/src/generators/configuration/utils.ts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Matěj Chalk <34691111+matejchalk@users.noreply.github.com> --- packages/nx-plugin/src/generators/configuration/utils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nx-plugin/src/generators/configuration/utils.ts b/packages/nx-plugin/src/generators/configuration/utils.ts index 8dd74e273..6bf51a204 100644 --- a/packages/nx-plugin/src/generators/configuration/utils.ts +++ b/packages/nx-plugin/src/generators/configuration/utils.ts @@ -51,7 +51,7 @@ export function formatArrayToLinesOfJsString( if (lines == null || lines.length === 0) { return; } - return `${lines.join(separator).replace('"', '')}`; + return lines.join(separator).replace(/"/g, ''); } export function formatArrayToJSArray(lines?: string[]) { From 5a4cea6d393da26d735856849e76194c84b58c10 Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 5 Aug 2024 13:36:45 +0200 Subject: [PATCH 09/13] refactor(nx-plugin): adjust stringify logic --- .eslintignore | 1 + .../code-pushup-config.unit.test.ts.snap | 6 +++--- .../generator.integration.test.ts.snap | 15 --------------- ...test.ts.snap => root-code-pushup.config.ts} | 9 ++------- .../code-pushup-config.integration.test.ts | 3 ++- .../code-pushup-config.unit.test.ts | 8 ++++---- .../src/generators/configuration/utils.ts | 7 +++++-- .../configuration/utils.unit.test.ts | 18 ++++++++++++++---- packages/nx-plugin/tsconfig.lib.json | 1 + 9 files changed, 32 insertions(+), 36 deletions(-) delete mode 100644 packages/nx-plugin/src/generators/configuration/__snapshots__/generator.integration.test.ts.snap rename packages/nx-plugin/src/generators/configuration/__snapshots__/{code-pushup-config.integration.test.ts.snap => root-code-pushup.config.ts} (55%) diff --git a/.eslintignore b/.eslintignore index be8d6ea41..0c203c742 100644 --- a/.eslintignore +++ b/.eslintignore @@ -2,3 +2,4 @@ node_modules **/*.mock.* **/code-pushup.config.ts **/mocks/fixtures/** +**/__snapshots__/** diff --git a/packages/nx-plugin/src/generators/configuration/__snapshots__/code-pushup-config.unit.test.ts.snap b/packages/nx-plugin/src/generators/configuration/__snapshots__/code-pushup-config.unit.test.ts.snap index 68580cf7f..284ad569d 100644 --- a/packages/nx-plugin/src/generators/configuration/__snapshots__/code-pushup-config.unit.test.ts.snap +++ b/packages/nx-plugin/src/generators/configuration/__snapshots__/code-pushup-config.unit.test.ts.snap @@ -4,9 +4,9 @@ exports[`generateCodePushupConfig options > should create code-pushup.config.ts { "options": { "categories": "[myPluginCategory()]", - "fileImports": "import type { CoreConfig } from 'dist/packages/models'; -import * as myPlugin from 'my-plugin'; -import {myPluginCategory} from 'my-plugin';", + "fileImports": "import type { CoreConfig } from "dist/packages/models"; +import * as myPlugin from "my-plugin"; +import {myPluginCategory} from "my-plugin";", "persist": "{ filename: "report-123" }", diff --git a/packages/nx-plugin/src/generators/configuration/__snapshots__/generator.integration.test.ts.snap b/packages/nx-plugin/src/generators/configuration/__snapshots__/generator.integration.test.ts.snap deleted file mode 100644 index b7f7ed335..000000000 --- a/packages/nx-plugin/src/generators/configuration/__snapshots__/generator.integration.test.ts.snap +++ /dev/null @@ -1,15 +0,0 @@ -// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html - -exports[`generateCodePushupConfig > should add code-pushup.config.ts to the project root 1`] = ` -"import type { CoreConfig } from '@code-pushup/models'; - -// see: https://github.com/code-pushup/cli/blob/main/packages/models/docs/models-reference.md#coreconfig -const config: CoreConfig = { - plugins: [ - // ... - ] -}; - -export default config; -" -`; diff --git a/packages/nx-plugin/src/generators/configuration/__snapshots__/code-pushup-config.integration.test.ts.snap b/packages/nx-plugin/src/generators/configuration/__snapshots__/root-code-pushup.config.ts similarity index 55% rename from packages/nx-plugin/src/generators/configuration/__snapshots__/code-pushup-config.integration.test.ts.snap rename to packages/nx-plugin/src/generators/configuration/__snapshots__/root-code-pushup.config.ts index 29dd9a2c9..ff964db95 100644 --- a/packages/nx-plugin/src/generators/configuration/__snapshots__/code-pushup-config.integration.test.ts.snap +++ b/packages/nx-plugin/src/generators/configuration/__snapshots__/root-code-pushup.config.ts @@ -1,8 +1,5 @@ -// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html - -exports[`generateCodePushupConfig options > should create code-pushup.config.ts with options in tree 1`] = ` -"import type { CoreConfig } from '../dist/packages/models; -import * as myPlugin from my-plugin"; +import type { CoreConfig } from "../dist/packages/models; +import * as myPlugin from "my-plugin"; import {myPluginCategory} from "my-plugin"; // see: https://github.com/code-pushup/cli/blob/main/packages/models/docs/models-reference.md#coreconfig @@ -16,5 +13,3 @@ export default { plugins: [myPlugin({ timeout: 42})], categories: [myPluginCategory()] } satisfies CoreConfig; -" -`; diff --git a/packages/nx-plugin/src/generators/configuration/code-pushup-config.integration.test.ts b/packages/nx-plugin/src/generators/configuration/code-pushup-config.integration.test.ts index c28add6a3..65f6a86d9 100644 --- a/packages/nx-plugin/src/generators/configuration/code-pushup-config.integration.test.ts +++ b/packages/nx-plugin/src/generators/configuration/code-pushup-config.integration.test.ts @@ -35,8 +35,9 @@ describe('generateCodePushupConfig options', () => { ], }); + // eslint-disable-next-line @typescript-eslint/no-floating-promises expect( tree.read(join(projectRoot, 'code-pushup.config.ts'))?.toString(), - ).toMatchSnapshot(); + ).toMatchFileSnapshot('__snapshots__/root-code-pushup.config.ts'); }); }); diff --git a/packages/nx-plugin/src/generators/configuration/code-pushup-config.unit.test.ts b/packages/nx-plugin/src/generators/configuration/code-pushup-config.unit.test.ts index be7a917c9..1fe4de6a6 100644 --- a/packages/nx-plugin/src/generators/configuration/code-pushup-config.unit.test.ts +++ b/packages/nx-plugin/src/generators/configuration/code-pushup-config.unit.test.ts @@ -60,9 +60,9 @@ describe('generateCodePushupConfig options', () => { expect.any(String), expect.objectContaining({ fileImports: formatArrayToLinesOfJsString([ - "import type { CoreConfig } from 'dist/packages/models';", - "import * as myPlugin from 'my-plugin';", - "import {myPluginCategory} from 'my-plugin';", + 'import type { CoreConfig } from "dist/packages/models";', + 'import * as myPlugin from "my-plugin";', + 'import {myPluginCategory} from "my-plugin";', ]), persist: formatObjectToFormattedJsString({ filename: 'report-123' }), upload: formatObjectToFormattedJsString({ apiKey: '123' }), @@ -139,7 +139,7 @@ describe('generateCodePushupConfig options', () => { expect.any(String), expect.objectContaining({ fileImports: formatArrayToLinesOfJsString([ - "import type { CoreConfig } from '../../dist/packages/models';", + 'import type { CoreConfig } from "../../dist/packages/models";', ]), }), ); diff --git a/packages/nx-plugin/src/generators/configuration/utils.ts b/packages/nx-plugin/src/generators/configuration/utils.ts index 6bf51a204..4dc8d5200 100644 --- a/packages/nx-plugin/src/generators/configuration/utils.ts +++ b/packages/nx-plugin/src/generators/configuration/utils.ts @@ -51,7 +51,7 @@ export function formatArrayToLinesOfJsString( if (lines == null || lines.length === 0) { return; } - return lines.join(separator).replace(/"/g, ''); + return lines.join(separator).replace(/'/g, '"'); } export function formatArrayToJSArray(lines?: string[]) { @@ -59,5 +59,8 @@ export function formatArrayToJSArray(lines?: string[]) { return; } - return `[${formatArrayToLinesOfJsString(lines, ',\n') ?? ''}]`; + return `[${formatArrayToLinesOfJsString(lines, ',\n') ?? ''}]`.replace( + /"/g, + '', + ); } diff --git a/packages/nx-plugin/src/generators/configuration/utils.unit.test.ts b/packages/nx-plugin/src/generators/configuration/utils.unit.test.ts index eb8468c3c..eada369b6 100644 --- a/packages/nx-plugin/src/generators/configuration/utils.unit.test.ts +++ b/packages/nx-plugin/src/generators/configuration/utils.unit.test.ts @@ -29,15 +29,25 @@ describe('formatArrayToJSArray', () => { describe('formatArrayToLinesOfJsString', () => { it('should return lines as JS', () => { + expect( + formatArrayToLinesOfJsString([`import plugin from "../mx-plugin";`]), + ).toMatchInlineSnapshot( + ` + "import plugin from "../mx-plugin";" + `, + ); + }); + + it('should return lines as JS with normalized quotes', () => { expect( formatArrayToLinesOfJsString([ - "import { CoreConfig } from '@code-pushup/models';", - "import plugin from '../mx-plugin';", + `import { CoreConfig } from '@code-pushup/models';`, + `import plugin from "../mx-plugin";`, ]), ).toMatchInlineSnapshot( ` - "import { CoreConfig } from '@code-pushup/models'; - import plugin from '../mx-plugin';" + "import { CoreConfig } from "@code-pushup/models"; + import plugin from "../mx-plugin";" `, ); }); diff --git a/packages/nx-plugin/tsconfig.lib.json b/packages/nx-plugin/tsconfig.lib.json index 5bd4eca67..c1c9dc3b7 100644 --- a/packages/nx-plugin/tsconfig.lib.json +++ b/packages/nx-plugin/tsconfig.lib.json @@ -9,6 +9,7 @@ "exclude": [ "vite.config.unit.ts", "vite.config.integration.ts", + "src/**/__snapshots__/*.ts", "src/**/*.test.ts", "src/**/*.mock.ts", "test/**/*.ts" From 85172f3b900d18812fd34407dc1c44456d8e7b24 Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 5 Aug 2024 20:48:42 +0200 Subject: [PATCH 10/13] wip --- .../code-pushup-config.unit.test.ts.snap | 20 ------------------- .../code-pushup-config.unit.test.ts | 4 ---- 2 files changed, 24 deletions(-) delete mode 100644 packages/nx-plugin/src/generators/configuration/__snapshots__/code-pushup-config.unit.test.ts.snap diff --git a/packages/nx-plugin/src/generators/configuration/__snapshots__/code-pushup-config.unit.test.ts.snap b/packages/nx-plugin/src/generators/configuration/__snapshots__/code-pushup-config.unit.test.ts.snap deleted file mode 100644 index 284ad569d..000000000 --- a/packages/nx-plugin/src/generators/configuration/__snapshots__/code-pushup-config.unit.test.ts.snap +++ /dev/null @@ -1,20 +0,0 @@ -// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html - -exports[`generateCodePushupConfig options > should create code-pushup.config.ts with options 1`] = ` -{ - "options": { - "categories": "[myPluginCategory()]", - "fileImports": "import type { CoreConfig } from "dist/packages/models"; -import * as myPlugin from "my-plugin"; -import {myPluginCategory} from "my-plugin";", - "persist": "{ - filename: "report-123" -}", - "plugins": "[myPlugin({ timeout: 42})]", - "upload": "{ - apiKey: "123" -}", - }, - "target": "test-app", -} -`; diff --git a/packages/nx-plugin/src/generators/configuration/code-pushup-config.unit.test.ts b/packages/nx-plugin/src/generators/configuration/code-pushup-config.unit.test.ts index 1fe4de6a6..787a3acdf 100644 --- a/packages/nx-plugin/src/generators/configuration/code-pushup-config.unit.test.ts +++ b/packages/nx-plugin/src/generators/configuration/code-pushup-config.unit.test.ts @@ -32,10 +32,6 @@ describe('generateCodePushupConfig options', () => { }); it('should create code-pushup.config.ts with options', () => { - generateFilesSpy.mockImplementation((...[_, __, target, options]) => { - expect({ target, options }).toMatchSnapshot(); - }); - generateCodePushupConfig(tree, testProjectName, { fileImports: ["import type { CoreConfig } from 'dist/packages/models';"], persist: { filename: 'report-123' }, From 6bd5c1c31f521559faedb3dbbfd6946b8c514a12 Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 5 Aug 2024 20:49:39 +0200 Subject: [PATCH 11/13] wip --- .../configuration/__snapshots__/root-code-pushup.config.ts | 2 +- .../configuration/code-pushup-config.integration.test.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/nx-plugin/src/generators/configuration/__snapshots__/root-code-pushup.config.ts b/packages/nx-plugin/src/generators/configuration/__snapshots__/root-code-pushup.config.ts index ff964db95..763e908b2 100644 --- a/packages/nx-plugin/src/generators/configuration/__snapshots__/root-code-pushup.config.ts +++ b/packages/nx-plugin/src/generators/configuration/__snapshots__/root-code-pushup.config.ts @@ -1,4 +1,4 @@ -import type { CoreConfig } from "../dist/packages/models; +import type { CoreConfig } from "../dist/packages/models"; import * as myPlugin from "my-plugin"; import {myPluginCategory} from "my-plugin"; diff --git a/packages/nx-plugin/src/generators/configuration/code-pushup-config.integration.test.ts b/packages/nx-plugin/src/generators/configuration/code-pushup-config.integration.test.ts index 65f6a86d9..3b03a06c2 100644 --- a/packages/nx-plugin/src/generators/configuration/code-pushup-config.integration.test.ts +++ b/packages/nx-plugin/src/generators/configuration/code-pushup-config.integration.test.ts @@ -18,7 +18,7 @@ describe('generateCodePushupConfig options', () => { it('should create code-pushup.config.ts with options in tree', () => { generateCodePushupConfig(tree, projectRoot, { - fileImports: "import type { CoreConfig } from '../dist/packages/models;", + fileImports: 'import type { CoreConfig } from "../dist/packages/models";', persist: { filename: 'report-123' }, upload: { apiKey: '123' }, plugins: [ From 7b4f501d8300487fa39a1f6c03537dfa9b1549c0 Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 5 Aug 2024 21:15:19 +0200 Subject: [PATCH 12/13] wip --- .../__snapshots__/root-code-pushup.config.ts | 22 +++++++++---------- .../code-pushup-config.integration.test.ts | 4 +++- .../src/generators/configuration/generator.ts | 6 +++-- .../src/generators/configuration/schema.d.ts | 1 + .../src/generators/configuration/schema.json | 5 +++++ 5 files changed, 24 insertions(+), 14 deletions(-) diff --git a/packages/nx-plugin/src/generators/configuration/__snapshots__/root-code-pushup.config.ts b/packages/nx-plugin/src/generators/configuration/__snapshots__/root-code-pushup.config.ts index 763e908b2..5056d9071 100644 --- a/packages/nx-plugin/src/generators/configuration/__snapshots__/root-code-pushup.config.ts +++ b/packages/nx-plugin/src/generators/configuration/__snapshots__/root-code-pushup.config.ts @@ -1,15 +1,15 @@ -import type { CoreConfig } from "../dist/packages/models"; -import * as myPlugin from "my-plugin"; -import {myPluginCategory} from "my-plugin"; +import type { CoreConfig } from '../dist/packages/models'; +import * as myPlugin from 'my-plugin'; +import { myPluginCategory } from 'my-plugin'; // see: https://github.com/code-pushup/cli/blob/main/packages/models/docs/models-reference.md#coreconfig export default { - persist: { - filename: "report-123" -}, - update: { - apiKey: "123" -}, - plugins: [myPlugin({ timeout: 42})], - categories: [myPluginCategory()] + persist: { + filename: 'report-123', + }, + update: { + apiKey: '123', + }, + plugins: [myPlugin({ timeout: 42 })], + categories: [myPluginCategory()], } satisfies CoreConfig; diff --git a/packages/nx-plugin/src/generators/configuration/code-pushup-config.integration.test.ts b/packages/nx-plugin/src/generators/configuration/code-pushup-config.integration.test.ts index 3b03a06c2..e41cb45c8 100644 --- a/packages/nx-plugin/src/generators/configuration/code-pushup-config.integration.test.ts +++ b/packages/nx-plugin/src/generators/configuration/code-pushup-config.integration.test.ts @@ -1,4 +1,5 @@ import * as devKit from '@nx/devkit'; +import { formatFiles } from '@nx/devkit'; import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; import { join } from 'node:path'; import { describe, expect, it } from 'vitest'; @@ -16,7 +17,7 @@ describe('generateCodePushupConfig options', () => { }); }); - it('should create code-pushup.config.ts with options in tree', () => { + it('should create code-pushup.config.ts with options in tree', async () => { generateCodePushupConfig(tree, projectRoot, { fileImports: 'import type { CoreConfig } from "../dist/packages/models";', persist: { filename: 'report-123' }, @@ -35,6 +36,7 @@ describe('generateCodePushupConfig options', () => { ], }); + await formatFiles(tree); // eslint-disable-next-line @typescript-eslint/no-floating-promises expect( tree.read(join(projectRoot, 'code-pushup.config.ts'))?.toString(), diff --git a/packages/nx-plugin/src/generators/configuration/generator.ts b/packages/nx-plugin/src/generators/configuration/generator.ts index a94f2db95..ea9a05427 100644 --- a/packages/nx-plugin/src/generators/configuration/generator.ts +++ b/packages/nx-plugin/src/generators/configuration/generator.ts @@ -15,7 +15,7 @@ export async function configurationGenerator( ) { const projectConfiguration = readProjectConfiguration(tree, options.project); - const { skipConfig, skipTarget } = options; + const { skipConfig, skipTarget, skipFormat } = options; if (skipConfig !== true) { generateCodePushupConfig(tree, projectConfiguration.root); @@ -25,7 +25,9 @@ export async function configurationGenerator( addTargetToProject(tree, projectConfiguration, options); } - await formatFiles(tree); + if (skipFormat !== true) { + await formatFiles(tree); + } } export function addTargetToProject( diff --git a/packages/nx-plugin/src/generators/configuration/schema.d.ts b/packages/nx-plugin/src/generators/configuration/schema.d.ts index 57cf0729f..11df4f6b3 100644 --- a/packages/nx-plugin/src/generators/configuration/schema.d.ts +++ b/packages/nx-plugin/src/generators/configuration/schema.d.ts @@ -4,4 +4,5 @@ export type ConfigurationGeneratorOptions = { project: string; skipTarget?: boolean; skipConfig?: boolean; + skipFormat?: boolean; } & DynamicTargetOptions; diff --git a/packages/nx-plugin/src/generators/configuration/schema.json b/packages/nx-plugin/src/generators/configuration/schema.json index 8f5f6b974..eade41294 100644 --- a/packages/nx-plugin/src/generators/configuration/schema.json +++ b/packages/nx-plugin/src/generators/configuration/schema.json @@ -31,6 +31,11 @@ "type": "boolean", "description": "Skip adding the code-pushup.config.ts to the project root.", "$default": "false" + }, + "skipFormat": { + "type": "boolean", + "description": "Skip formatting of changed files", + "$default": "false" } }, "required": ["project"] From 7d6a05eba387fe8f376d894f926e630d82ee1219 Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 6 Aug 2024 11:48:23 +0200 Subject: [PATCH 13/13] exclude snapshots from testing --- packages/nx-plugin/vite.config.integration.ts | 2 +- packages/nx-plugin/vite.config.unit.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/nx-plugin/vite.config.integration.ts b/packages/nx-plugin/vite.config.integration.ts index 6261e59fd..1ccc8b2d3 100644 --- a/packages/nx-plugin/vite.config.integration.ts +++ b/packages/nx-plugin/vite.config.integration.ts @@ -16,7 +16,7 @@ export default defineConfig({ coverage: { reporter: ['text', 'lcov'], reportsDirectory: '../../coverage/nx-plugin/integration-tests', - exclude: ['mocks/**', '**/types.ts'], + exclude: ['mocks/**', '**/types.ts', '**/__snapshots__/**'], }, environment: 'node', include: ['src/**/*.integration.test.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], diff --git a/packages/nx-plugin/vite.config.unit.ts b/packages/nx-plugin/vite.config.unit.ts index ec4284e03..835b6b7a3 100644 --- a/packages/nx-plugin/vite.config.unit.ts +++ b/packages/nx-plugin/vite.config.unit.ts @@ -16,7 +16,7 @@ export default defineConfig({ coverage: { reporter: ['text', 'lcov'], reportsDirectory: '../../coverage/nx-plugin/unit-tests', - exclude: ['mocks/**', '**/types.ts'], + exclude: ['mocks/**', '**/types.ts', '**/__snapshots__/**'], }, environment: 'node', include: ['src/**/*.unit.test.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],