From 3e9991b44d9a2bacb09e97a20cc9e4cbf2788dd7 Mon Sep 17 00:00:00 2001 From: Martin Hochel Date: Mon, 24 Apr 2023 14:57:20 +0200 Subject: [PATCH] feat(tools): add conformance setup migration to migrate-converged-pkg generator --- .../migrate-converged-pkg/index.spec.ts | 58 +++++++++++++++++++ .../generators/migrate-converged-pkg/index.ts | 50 ++++++++++++++++ 2 files changed, 108 insertions(+) diff --git a/tools/generators/migrate-converged-pkg/index.spec.ts b/tools/generators/migrate-converged-pkg/index.spec.ts index 791f9259613e9..cb1d270d35a4a 100644 --- a/tools/generators/migrate-converged-pkg/index.spec.ts +++ b/tools/generators/migrate-converged-pkg/index.spec.ts @@ -19,6 +19,7 @@ import { writeJson, WorkspaceConfiguration, ProjectConfiguration, + joinPathFragments, } from '@nrwl/devkit'; import { PackageJson, TsConfig } from '../../types'; @@ -1256,6 +1257,63 @@ describe('migrate-converged-pkg generator', () => { }); }); + describe(`update conformance setup`, () => { + const conformanceSetup = stripIndents` + import { isConformant as baseIsConformant } from '@proj/react-conformance'; + import type { IsConformantOptions, TestObject } from '@proj/react-conformance'; + import griffelTests from '@proj/react-conformance-griffel'; + + export function isConformant( + testInfo: Omit, 'componentPath'> & { componentPath?: string }, + ) { + const defaultOptions: Partial> = { + componentPath: require.main?.filename.replace('.test', ''), + extraTests: griffelTests as TestObject, + testOptions: { + 'make-styles-overrides-win': { + callCount: 2, + }, + // TODO: https://github.com/microsoft/fluentui/issues/19618 + // eslint-disable-next-line @typescript-eslint/no-explicit-any + } as any, + }; + + baseIsConformant(defaultOptions, testInfo); + } + `; + it(`should use tsConfig conformance API`, async () => { + const projectConfig = readProjectConfiguration(tree, options.name); + const conformanceSetupPath = joinPathFragments(projectConfig.root as string, 'src/testing/isConformant.ts'); + tree.write(conformanceSetupPath, conformanceSetup); + await generator(tree, options); + + expect(tree.read(conformanceSetupPath, 'utf-8')).toMatchInlineSnapshot(` + "import { isConformant as baseIsConformant } from '@proj/react-conformance'; + import type { IsConformantOptions, TestObject } from '@proj/react-conformance'; + import griffelTests from '@proj/react-conformance-griffel'; + + export function isConformant( + testInfo: Omit, 'componentPath'> & { componentPath?: string }, + ) { + const defaultOptions: Partial> = { + tsConfig: { configName: 'tsconfig.spec.json' }, + componentPath: require.main?.filename.replace('.test', ''), + extraTests: griffelTests as TestObject, + testOptions: { + 'make-styles-overrides-win': { + callCount: 2, + }, + // TODO: https://github.com/microsoft/fluentui/issues/19618 + // eslint-disable-next-line @typescript-eslint/no-explicit-any + } as any, + }; + + baseIsConformant(defaultOptions, testInfo); + }" + `); + }); + }); + describe(`--stats`, () => { it(`should print project names and count of how many have been migrated`, async () => { const loggerInfoSpy = jest.spyOn(logger, 'info'); diff --git a/tools/generators/migrate-converged-pkg/index.ts b/tools/generators/migrate-converged-pkg/index.ts index bbcbce992dc21..36170162fca0a 100644 --- a/tools/generators/migrate-converged-pkg/index.ts +++ b/tools/generators/migrate-converged-pkg/index.ts @@ -13,9 +13,12 @@ import { updateProjectConfiguration, serializeJson, offsetFromRoot, + applyChangesToString, + ChangeType, } from '@nrwl/devkit'; import * as path from 'path'; import * as os from 'os'; +import * as ts from 'typescript'; import { PackageJson, TsConfig } from '../../types'; import { @@ -144,6 +147,7 @@ function runMigrationOnProject(tree: Tree, schema: AssertedSchema, _userLog: Use setupSwcConfig(tree, options); setupJustConfig(tree, options); + updateConformanceSetup(tree, options); } // ==== helpers ==== @@ -978,6 +982,52 @@ function updateLocalJestConfig(tree: Tree, options: NormalizedSchema) { return tree; } +function updateConformanceSetup(tree: Tree, options: NormalizedSchema) { + if (!tree.exists(options.paths.conformanceSetup)) { + logger.warn('no conformance setup present. skipping...'); + return; + } + + const conformanceSetupContent = tree.read(options.paths.conformanceSetup, 'utf-8') as string; + const sourceFile = ts.createSourceFile('is-conformant.ts', conformanceSetupContent, ts.ScriptTarget.Latest, true); + const addition = `\ntsConfig: { configName: 'tsconfig.spec.json' },`; + + let start: number | undefined; + getConfigObjectFirstPropertyIndex(sourceFile); + + if (!start) { + return; + } + + const updatedContent = applyChangesToString(conformanceSetupContent, [ + { + type: ChangeType.Insert, + index: start, + text: addition, + }, + ]); + + tree.write(options.paths.conformanceSetup, updatedContent); + + function getConfigObjectFirstPropertyIndex(node: ts.Node) { + if (ts.isVariableStatement(node)) { + const defaultOptionsVar = node.declarationList.declarations[0].name.getText(); + if (defaultOptionsVar === 'defaultOptions') { + const initializer = node.declarationList.declarations[0].initializer; + if (initializer && ts.isObjectLiteralExpression(initializer)) { + const firstProp = initializer.properties[0]; + start = firstProp.pos; + return; + } + } + } + + ts.forEachChild(node, getConfigObjectFirstPropertyIndex); + } + + return tree; +} + function updatedLocalTsConfig(tree: Tree, options: NormalizedSchema) { const { configs } = createTsSolutionConfig(tree, options);