diff --git a/modules/testing/builder/src/jasmine-helpers.ts b/modules/testing/builder/src/jasmine-helpers.ts index eb48f8b8dbbc..bd1943ae3ea1 100644 --- a/modules/testing/builder/src/jasmine-helpers.ts +++ b/modules/testing/builder/src/jasmine-helpers.ts @@ -25,6 +25,8 @@ export const BUILD_TIMEOUT = 30_000; const optionSchemaCache = new Map(); +let counter = 0; + export function describeBuilder( builderHandler: BuilderHandlerFn, options: { name?: string; schemaPath: string }, @@ -40,10 +42,8 @@ export function describeBuilder( optionSchema, }); - // This is needed as there are multiple describe calls for the same builder. - jasmine.getEnv().configure({ forbidDuplicateNames: false }); - - describe(options.name || builderHandler.name, () => { + // The counter is needed to avoid duplicate describe names as they are not allowed. + describe((options.name || builderHandler.name) + ` (Suite: ${counter++})`, () => { beforeEach(async () => { harness.resetProjectMetadata(); diff --git a/package.json b/package.json index 788570de87c7..a16aa3936ac4 100644 --- a/package.json +++ b/package.json @@ -74,7 +74,7 @@ "@types/express": "~5.0.1", "@types/http-proxy": "^1.17.4", "@types/ini": "^4.0.0", - "@types/jasmine": "~5.1.0", + "@types/jasmine": "~6.0.0", "@types/jasmine-reporters": "^2", "@types/karma": "^6.3.0", "@types/less": "^3.0.3", @@ -105,8 +105,8 @@ "http-proxy": "^1.18.1", "http-proxy-middleware": "3.0.5", "husky": "9.1.7", - "jasmine": "~5.13.0", - "jasmine-core": "~5.13.0", + "jasmine": "~6.1.0", + "jasmine-core": "~6.1.0", "jasmine-reporters": "^2.5.2", "jasmine-spec-reporter": "~7.0.0", "karma": "~6.4.0", diff --git a/packages/angular/build/src/builders/dev-server/tests/jasmine-helpers.ts b/packages/angular/build/src/builders/dev-server/tests/jasmine-helpers.ts index c5a73446cf5a..966418e16a61 100644 --- a/packages/angular/build/src/builders/dev-server/tests/jasmine-helpers.ts +++ b/packages/angular/build/src/builders/dev-server/tests/jasmine-helpers.ts @@ -12,6 +12,7 @@ import { readFileSync } from 'node:fs'; import { JasmineBuilderHarness, host, setupApplicationTarget } from './setup'; const optionSchemaCache = new Map(); +let counter = 0; export function describeServeBuilder( builderHandler: BuilderHandlerFn, @@ -32,7 +33,8 @@ export function describeServeBuilder( optionSchema, }); - describe(options.name || builderHandler.name, () => { + // The counter is needed to avoid duplicate describe names as they are not allowed. + describe((options.name || builderHandler.name) + ` (${counter++})`, () => { beforeEach(() => host.initialize().toPromise()); afterEach(() => host.restore().toPromise()); diff --git a/packages/angular/build/src/builders/karma/find-tests_spec.ts b/packages/angular/build/src/builders/karma/find-tests_spec.ts deleted file mode 100644 index 88c97c8575fe..000000000000 --- a/packages/angular/build/src/builders/karma/find-tests_spec.ts +++ /dev/null @@ -1,97 +0,0 @@ -/** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.dev/license - */ - -import { getTestEntrypoints } from './find-tests'; - -const UNIX_ENTRYPOINTS_OPTIONS = { - pathSeparator: '/', - workspaceRoot: '/my/workspace/root', - projectSourceRoot: '/my/workspace/root/src-root', -}; - -const WINDOWS_ENTRYPOINTS_OPTIONS = { - pathSeparator: '\\', - workspaceRoot: 'C:\\my\\workspace\\root', - projectSourceRoot: 'C:\\my\\workspace\\root\\src-root', -}; - -describe('getTestEntrypoints', () => { - for (const options of [UNIX_ENTRYPOINTS_OPTIONS, WINDOWS_ENTRYPOINTS_OPTIONS]) { - describe(`with path separator "${options.pathSeparator}"`, () => { - function joinWithSeparator(base: string, rel: string) { - return `${base}${options.pathSeparator}${rel.replace(/\//g, options.pathSeparator)}`; - } - - function getEntrypoints(workspaceRelative: string[], sourceRootRelative: string[] = []) { - return getTestEntrypoints( - [ - ...workspaceRelative.map((p) => joinWithSeparator(options.workspaceRoot, p)), - ...sourceRootRelative.map((p) => joinWithSeparator(options.projectSourceRoot, p)), - ], - options, - ); - } - - it('returns an empty map without test files', () => { - expect(getEntrypoints([])).toEqual(new Map()); - }); - - it('strips workspace root and/or project source root', () => { - expect(getEntrypoints(['a/b.spec.js'], ['c/d.spec.js'])).toEqual( - new Map([ - ['spec-a-b.spec', joinWithSeparator(options.workspaceRoot, 'a/b.spec.js')], - ['spec-c-d.spec', joinWithSeparator(options.projectSourceRoot, 'c/d.spec.js')], - ]), - ); - }); - - it('adds unique prefixes to distinguish between similar names', () => { - expect(getEntrypoints(['a/b/c/d.spec.js', 'a-b/c/d.spec.js'], ['a/b-c/d.spec.js'])).toEqual( - new Map([ - ['spec-a-b-c-d.spec', joinWithSeparator(options.workspaceRoot, 'a/b/c/d.spec.js')], - ['spec-a-b-c-d-2.spec', joinWithSeparator(options.workspaceRoot, 'a-b/c/d.spec.js')], - [ - 'spec-a-b-c-d-3.spec', - joinWithSeparator(options.projectSourceRoot, 'a/b-c/d.spec.js'), - ], - ]), - ); - }); - - describe('with removeTestExtension enabled', () => { - function getEntrypoints(workspaceRelative: string[], sourceRootRelative: string[] = []) { - return getTestEntrypoints( - [ - ...workspaceRelative.map((p) => joinWithSeparator(options.workspaceRoot, p)), - ...sourceRootRelative.map((p) => joinWithSeparator(options.projectSourceRoot, p)), - ], - { ...options, removeTestExtension: true }, - ); - } - - it('removes .spec extension', () => { - expect(getEntrypoints(['a/b.spec.js'], ['c/d.spec.js'])).toEqual( - new Map([ - ['spec-a-b', joinWithSeparator(options.workspaceRoot, 'a/b.spec.js')], - ['spec-c-d', joinWithSeparator(options.projectSourceRoot, 'c/d.spec.js')], - ]), - ); - }); - - it('removes .test extension', () => { - expect(getEntrypoints(['a/b.test.js'], ['c/d.test.js'])).toEqual( - new Map([ - ['spec-a-b', joinWithSeparator(options.workspaceRoot, 'a/b.test.js')], - ['spec-c-d', joinWithSeparator(options.projectSourceRoot, 'c/d.test.js')], - ]), - ); - }); - }); - }); - } -}); diff --git a/packages/angular/build/src/builders/karma/tests/setup.ts b/packages/angular/build/src/builders/karma/tests/setup.ts index e6a013946904..6292074daaf6 100644 --- a/packages/angular/build/src/builders/karma/tests/setup.ts +++ b/packages/angular/build/src/builders/karma/tests/setup.ts @@ -112,6 +112,8 @@ export async function setupApplicationTarget( await harness.appendToFile('src/polyfills.ts', `import '@angular/localize/init';`); } +let counter = 0; + /** Runs the test against both an application- and a browser-builder context. */ export function describeKarmaBuilder( builderHandler: BuilderHandlerFn, @@ -128,7 +130,7 @@ export function describeKarmaBuilder( optionSchema, }); - describe(options.name || builderHandler.name, () => { + describe((options.name || builderHandler.name) + ` (${counter++})`, () => { beforeEach(async () => { await host.initialize().toPromise(); diff --git a/packages/angular/build/src/builders/unit-test/tests/options/code-coverage_spec.ts b/packages/angular/build/src/builders/unit-test/tests/options/code-coverage_spec.ts index f8a8acb60591..d0f51e731de9 100644 --- a/packages/angular/build/src/builders/unit-test/tests/options/code-coverage_spec.ts +++ b/packages/angular/build/src/builders/unit-test/tests/options/code-coverage_spec.ts @@ -42,7 +42,7 @@ describeBuilder(execute, UNIT_TEST_BUILDER_INFO, (harness) => { harness.expectFile('coverage/test/index.html').toExist(); }); - it('should generate a code coverage report when coverage is true', async () => { + it('should generate a code coverage report when coverage is true and coverageReporters is set to json', async () => { harness.useTarget('test', { ...BASE_OPTIONS, coverage: true, diff --git a/packages/angular/build/src/tools/babel/plugins/elide-angular-metadata_spec.ts b/packages/angular/build/src/tools/babel/plugins/elide-angular-metadata_spec.ts index 4705d207a63a..896e1e270af4 100644 --- a/packages/angular/build/src/tools/babel/plugins/elide-angular-metadata_spec.ts +++ b/packages/angular/build/src/tools/babel/plugins/elide-angular-metadata_spec.ts @@ -188,7 +188,7 @@ describe('elide-angular-metadata Babel plugin', () => { ); it( - 'elides arrow-function-based ɵsetClassMetadataAsync', + 'elides ɵsetClassDebugInfo', testCase({ input: ` import { Component } from '@angular/core'; diff --git a/packages/angular/build/src/tools/babel/plugins/pure-toplevel-functions_spec.ts b/packages/angular/build/src/tools/babel/plugins/pure-toplevel-functions_spec.ts index 0966a67d068a..77eb42dc9bbe 100644 --- a/packages/angular/build/src/tools/babel/plugins/pure-toplevel-functions_spec.ts +++ b/packages/angular/build/src/tools/babel/plugins/pure-toplevel-functions_spec.ts @@ -100,7 +100,7 @@ describe('pure-toplevel-functions Babel plugin', () => { ); it( - 'does not annotate call expressions inside function expressions', + 'does not annotate call expressions inside arrow functions', testCaseNoChange('const foo = () => { const result = someFunction(); }'), ); @@ -115,7 +115,7 @@ describe('pure-toplevel-functions Babel plugin', () => { ); it( - 'does not annotate new expressions inside function expressions', + 'does not annotate new expressions inside arrow functions', testCaseNoChange('const foo = () => { const result = new SomeClass(); }'), ); diff --git a/packages/angular/ssr/test/app_spec.ts b/packages/angular/ssr/test/app_spec.ts index a72c4d75fae2..8fb82a10cfb9 100644 --- a/packages/angular/ssr/test/app_spec.ts +++ b/packages/angular/ssr/test/app_spec.ts @@ -309,17 +309,6 @@ describe('AngularServerApp', () => { expect(await conditionalResponse?.text()).toBe(''); }); - it('should return configured headers for pages with specific header settings', async () => { - const response = await app.handle(new Request('http://localhost/home-ssg')); - const headers = response?.headers.entries() ?? []; - expect(Object.fromEntries(headers)).toEqual({ - 'etag': '"f799132d0a09e0fef93c68a12e443527700eb59e6f67fcb7854c3a60ff082fde"', - 'content-length': '28', - 'x-some-header': 'value', - 'content-type': 'text/html;charset=UTF-8', - }); - }); - it('should return null for a non-prerendered page', async () => { const response = await app.handle(new Request('http://localhost/unknown')); expect(response).toBeNull(); diff --git a/packages/angular_devkit/architect/src/api_spec.ts b/packages/angular_devkit/architect/src/api_spec.ts index 55247a59d993..fc1e4c1d7680 100644 --- a/packages/angular_devkit/architect/src/api_spec.ts +++ b/packages/angular_devkit/architect/src/api_spec.ts @@ -40,7 +40,7 @@ describe('Architect API', () => { for (const ts of Object.getOwnPropertyNames(goldens)) { const t: Target = goldens[ts]; - it(`works for ${JSON.stringify(t)}`, () => { + it(`works for ${JSON.stringify(ts)}`, () => { // We have some invalid goldens. Remove everything after the second :. const goldenTs = ts.replace(/(\w+:\w+(:\w*)?).*/, '$1'); expect(targetStringFromTarget(t)).toEqual(goldenTs); diff --git a/packages/angular_devkit/build_angular/src/builders/browser/specs/tsconfig-paths_spec.ts b/packages/angular_devkit/build_angular/src/builders/browser/specs/tsconfig-paths_spec.ts index 754f85e182a9..64be1270ef9a 100644 --- a/packages/angular_devkit/build_angular/src/builders/browser/specs/tsconfig-paths_spec.ts +++ b/packages/angular_devkit/build_angular/src/builders/browser/specs/tsconfig-paths_spec.ts @@ -19,7 +19,7 @@ describe('Browser Builder tsconfig paths', () => { }); afterEach(async () => host.restore().toPromise()); - it('works', async () => { + it('should resolve basic tsconfig paths', async () => { host.replaceInFile('src/app/app.module.ts', './app.component', '@root/app/app.component'); host.replaceInFile( 'tsconfig.json', @@ -37,7 +37,7 @@ describe('Browser Builder tsconfig paths', () => { await browserBuild(architect, host, target); }); - it('works', async () => { + it('should resolve complex tsconfig paths with wildcards', async () => { host.writeMultipleFiles({ 'src/meaning-too.ts': 'export var meaning = 42;', 'src/app/shared/meaning.ts': 'export var meaning = 42;', diff --git a/packages/angular_devkit/build_angular/src/builders/dev-server/tests/jasmine-helpers.ts b/packages/angular_devkit/build_angular/src/builders/dev-server/tests/jasmine-helpers.ts index f3d1bfcea48a..07182ebe07f1 100644 --- a/packages/angular_devkit/build_angular/src/builders/dev-server/tests/jasmine-helpers.ts +++ b/packages/angular_devkit/build_angular/src/builders/dev-server/tests/jasmine-helpers.ts @@ -14,6 +14,7 @@ import { host } from '../../../testing/test-utils'; import { setupApplicationTarget, setupBrowserTarget } from './setup'; const optionSchemaCache = new Map(); +let counter = 0; export function describeServeBuilder( builderHandler: BuilderHandlerFn, @@ -39,7 +40,8 @@ export function describeServeBuilder( optionSchema, }); - describe(options.name || builderHandler.name, () => { + // The counter is needed to avoid duplicate describe names as they are not allowed. + describe((options.name || builderHandler.name) + ` (${counter++})`, () => { for (const isViteRun of [true, false]) { describe(isViteRun ? 'vite' : 'webpack-dev-server', () => { beforeEach(() => host.initialize().toPromise()); diff --git a/packages/angular_devkit/build_angular/src/builders/karma/tests/setup.ts b/packages/angular_devkit/build_angular/src/builders/karma/tests/setup.ts index d78f691bef91..8850e470e67c 100644 --- a/packages/angular_devkit/build_angular/src/builders/karma/tests/setup.ts +++ b/packages/angular_devkit/build_angular/src/builders/karma/tests/setup.ts @@ -140,6 +140,8 @@ export async function setupApplicationTarget( await harness.appendToFile('src/polyfills.ts', `import '@angular/localize/init';`); } +let counter = 0; + /** Runs the test against both an application- and a browser-builder context. */ export function describeKarmaBuilder( builderHandler: BuilderHandlerFn, @@ -161,7 +163,8 @@ export function describeKarmaBuilder( optionSchema, }); - describe(options.name || builderHandler.name, () => { + // The counter is needed to avoid duplicate describe names as they are not allowed. + describe((options.name || builderHandler.name) + ` (${counter++})`, () => { for (const isApplicationTarget of [true, false]) { describe(isApplicationTarget ? 'with application builder' : 'with browser builder', () => { beforeEach(() => host.initialize().toPromise()); diff --git a/packages/angular_devkit/build_angular/src/builders/ssr-dev-server/specs/proxy_spec.ts b/packages/angular_devkit/build_angular/src/builders/ssr-dev-server/specs/proxy_spec.ts index 425aad21dada..c6ea08e05cda 100644 --- a/packages/angular_devkit/build_angular/src/builders/ssr-dev-server/specs/proxy_spec.ts +++ b/packages/angular_devkit/build_angular/src/builders/ssr-dev-server/specs/proxy_spec.ts @@ -13,7 +13,7 @@ import * as http from 'node:http'; import { createArchitect, host } from '../../../testing/test-utils'; import { SSRDevServerBuilderOutput } from '../index'; -describe('Serve SSR Builder', () => { +describe('Serve SSR Builder - Proxy', () => { const target = { project: 'app', target: 'serve-ssr' }; const originalTimeout = jasmine.DEFAULT_TIMEOUT_INTERVAL; let architect: Architect; diff --git a/packages/angular_devkit/build_angular/src/builders/ssr-dev-server/specs/ssl_spec.ts b/packages/angular_devkit/build_angular/src/builders/ssr-dev-server/specs/ssl_spec.ts index e61117812bbe..8c098b514fbb 100644 --- a/packages/angular_devkit/build_angular/src/builders/ssr-dev-server/specs/ssl_spec.ts +++ b/packages/angular_devkit/build_angular/src/builders/ssr-dev-server/specs/ssl_spec.ts @@ -13,7 +13,7 @@ import { Agent } from 'undici'; import { createArchitect, host } from '../../../testing/test-utils'; import { SSRDevServerBuilderOutput } from '../index'; -describe('Serve SSR Builder', () => { +describe('Serve SSR Builder - SSL', () => { const target = { project: 'app', target: 'serve-ssr' }; const originalTimeout = jasmine.DEFAULT_TIMEOUT_INTERVAL; let architect: Architect; diff --git a/packages/angular_devkit/build_angular/src/builders/ssr-dev-server/specs/works_spec.ts b/packages/angular_devkit/build_angular/src/builders/ssr-dev-server/specs/works_spec.ts index c8c70d148e63..731443b6cd94 100644 --- a/packages/angular_devkit/build_angular/src/builders/ssr-dev-server/specs/works_spec.ts +++ b/packages/angular_devkit/build_angular/src/builders/ssr-dev-server/specs/works_spec.ts @@ -12,7 +12,7 @@ import * as browserSync from 'browser-sync'; import { createArchitect, host } from '../../../testing/test-utils'; import { SSRDevServerBuilderOutput } from '../index'; -describe('Serve SSR Builder', () => { +describe('Serve SSR Builder - Works', () => { const target = { project: 'app', target: 'serve-ssr' }; const originalTimeout = jasmine.DEFAULT_TIMEOUT_INTERVAL; let architect: Architect; diff --git a/packages/angular_devkit/core/src/virtual-fs/path_spec.ts b/packages/angular_devkit/core/src/virtual-fs/path_spec.ts index 4e416a1ff12e..e5da5e66e838 100644 --- a/packages/angular_devkit/core/src/virtual-fs/path_spec.ts +++ b/packages/angular_devkit/core/src/virtual-fs/path_spec.ts @@ -94,9 +94,9 @@ describe('path', () => { ]; for (const [input, result] of tests) { - const normalizedInput = normalize(input); + it(`(${input}) == "${result}"`, () => { + const normalizedInput = normalize(input); - it(`(${JSON.stringify(normalizedInput)}) == "${result}"`, () => { expect(split(normalizedInput)).toEqual(result as PathFragment[]); }); } diff --git a/packages/ngtools/webpack/src/transformers/elide_imports_spec.ts b/packages/ngtools/webpack/src/transformers/elide_imports_spec.ts index 9bbcb4a78207..2138a0811034 100644 --- a/packages/ngtools/webpack/src/transformers/elide_imports_spec.ts +++ b/packages/ngtools/webpack/src/transformers/elide_imports_spec.ts @@ -12,63 +12,62 @@ import * as ts from 'typescript'; import { elideImports } from './elide_imports'; import { createTypescriptContext, transformTypescript } from './spec_helpers'; -describe('@ngtools/webpack transformers', () => { - describe('elide_imports', () => { - const dummyNode = `const remove = ''`; - - // Transformer that removes the last node and then elides unused imports - const transformer = (program: ts.Program) => { - return (context: ts.TransformationContext) => { - return (sourceFile: ts.SourceFile) => { - const lastNode = sourceFile.statements[sourceFile.statements.length - 1]; - const updatedSourceFile = context.factory.updateSourceFile( - sourceFile, - ts.setTextRange( - context.factory.createNodeArray(sourceFile.statements.slice(0, -1)), - sourceFile.statements, - ), - ); +describe('elide_imports', () => { + const dummyNode = `const remove = ''`; + + // Transformer that removes the last node and then elides unused imports + const transformer = (program: ts.Program) => { + return (context: ts.TransformationContext) => { + return (sourceFile: ts.SourceFile) => { + const lastNode = sourceFile.statements[sourceFile.statements.length - 1]; + const updatedSourceFile = context.factory.updateSourceFile( + sourceFile, + ts.setTextRange( + context.factory.createNodeArray(sourceFile.statements.slice(0, -1)), + sourceFile.statements, + ), + ); - const importRemovals = elideImports( + const importRemovals = elideImports( + updatedSourceFile, + [lastNode], + () => program.getTypeChecker(), + context.getCompilerOptions(), + ); + if (importRemovals.size > 0) { + return ts.visitEachChild( updatedSourceFile, - [lastNode], - () => program.getTypeChecker(), - context.getCompilerOptions(), + function visitForRemoval(node): ts.Node | undefined { + return importRemovals.has(node) + ? undefined + : ts.visitEachChild(node, visitForRemoval, context); + }, + context, ); - if (importRemovals.size > 0) { - return ts.visitEachChild( - updatedSourceFile, - function visitForRemoval(node): ts.Node | undefined { - return importRemovals.has(node) - ? undefined - : ts.visitEachChild(node, visitForRemoval, context); - }, - context, - ); - } + } - return updatedSourceFile; - }; + return updatedSourceFile; }; }; + }; - const additionalFiles: Record = { - 'const.ts': ` + const additionalFiles: Record = { + 'const.ts': ` export const animations = []; export const promise = () => null; export const take = () => null; export default promise; `, - 'decorator.ts': ` + 'decorator.ts': ` export function Decorator(value?: any): any { return function (): any { }; } `, - 'service.ts': ` + 'service.ts': ` export class Service { } export class Service2 { } `, - 'type.ts': ` + 'type.ts': ` export interface OnChanges { ngOnChanges(changes: SimpleChanges): void; } @@ -77,252 +76,252 @@ describe('@ngtools/webpack transformers', () => { [propName: string]: unknown; } `, - 'jsx.ts': ` + 'jsx.ts': ` export function createElement() {} `, - }; + }; - it('should remove unused imports', () => { - const input = tags.stripIndent` + it('should remove unused imports', () => { + const input = tags.stripIndent` import { promise } from './const'; import { take } from './const'; const unused = promise; `; - const { program, compilerHost } = createTypescriptContext(input, additionalFiles); - const result = transformTypescript(undefined, [transformer(program)], program, compilerHost); + const { program, compilerHost } = createTypescriptContext(input, additionalFiles); + const result = transformTypescript(undefined, [transformer(program)], program, compilerHost); - expect(tags.oneLine`${result}`).toEqual('export {};'); - }); + expect(tags.oneLine`${result}`).toEqual('export {};'); + }); - it('should remove unused aliased imports', () => { - const input = tags.stripIndent` + it('should remove unused aliased imports', () => { + const input = tags.stripIndent` import { promise as fromPromise } from './const'; const unused = fromPromise; `; - const { program, compilerHost } = createTypescriptContext(input, additionalFiles); - const result = transformTypescript(undefined, [transformer(program)], program, compilerHost); + const { program, compilerHost } = createTypescriptContext(input, additionalFiles); + const result = transformTypescript(undefined, [transformer(program)], program, compilerHost); - expect(tags.oneLine`${result}`).toEqual('export {};'); - }); + expect(tags.oneLine`${result}`).toEqual('export {};'); + }); - it('should retain used aliased imports', () => { - const input = tags.stripIndent` + it('should retain used aliased imports', () => { + const input = tags.stripIndent` import { promise as fromPromise } from './const'; const used = fromPromise; ${dummyNode} `; - const output = tags.stripIndent` + const output = tags.stripIndent` import { promise as fromPromise } from './const'; const used = fromPromise; `; - const { program, compilerHost } = createTypescriptContext(input, additionalFiles); - const result = transformTypescript(undefined, [transformer(program)], program, compilerHost); + const { program, compilerHost } = createTypescriptContext(input, additionalFiles); + const result = transformTypescript(undefined, [transformer(program)], program, compilerHost); - expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); - }); + expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); + }); - it('should retain used namespaced imports', () => { - const input = tags.stripIndent` + it('should retain used namespaced imports', () => { + const input = tags.stripIndent` import * as namespaced from './const'; const used = namespaced; ${dummyNode} `; - const output = tags.stripIndent` + const output = tags.stripIndent` import * as namespaced from './const'; const used = namespaced; `; - const { program, compilerHost } = createTypescriptContext(input, additionalFiles); - const result = transformTypescript(undefined, [transformer(program)], program, compilerHost); + const { program, compilerHost } = createTypescriptContext(input, additionalFiles); + const result = transformTypescript(undefined, [transformer(program)], program, compilerHost); - expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); - }); + expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); + }); - it('should drop unused namespaced imports', () => { - const input = tags.stripIndent` + it('should drop unused namespaced imports', () => { + const input = tags.stripIndent` import * as namespaced from './const'; const used = namespaced; `; - const { program, compilerHost } = createTypescriptContext(input, additionalFiles); - const result = transformTypescript(undefined, [transformer(program)], program, compilerHost); + const { program, compilerHost } = createTypescriptContext(input, additionalFiles); + const result = transformTypescript(undefined, [transformer(program)], program, compilerHost); - expect(tags.oneLine`${result}`).toEqual('export {};'); - }); + expect(tags.oneLine`${result}`).toEqual('export {};'); + }); - it('should drop unused imports in export specifier', () => { - const input = tags.stripIndent` + it('should drop unused imports in export specifier', () => { + const input = tags.stripIndent` import { promise as fromPromise } from './const'; export { fromPromise }; `; - const { program, compilerHost } = createTypescriptContext(input, additionalFiles); - const result = transformTypescript(undefined, [transformer(program)], program, compilerHost); + const { program, compilerHost } = createTypescriptContext(input, additionalFiles); + const result = transformTypescript(undefined, [transformer(program)], program, compilerHost); - expect(tags.oneLine`${result}`).toEqual('export {};'); - }); + expect(tags.oneLine`${result}`).toEqual('export {};'); + }); - it('should retain used imports in export specifier', () => { - const input = tags.stripIndent` + it('should retain used imports in export specifier', () => { + const input = tags.stripIndent` import { promise as fromPromise } from './const'; export { fromPromise }; ${dummyNode} `; - const output = tags.stripIndent` + const output = tags.stripIndent` import { promise as fromPromise } from './const'; export { fromPromise }; `; - const { program, compilerHost } = createTypescriptContext(input, additionalFiles); - const result = transformTypescript(undefined, [transformer(program)], program, compilerHost); + const { program, compilerHost } = createTypescriptContext(input, additionalFiles); + const result = transformTypescript(undefined, [transformer(program)], program, compilerHost); - expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); - }); + expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); + }); - it('should drop unused in shorthand property assignment', () => { - const input = tags.stripIndent` + it('should drop unused in shorthand property assignment', () => { + const input = tags.stripIndent` import { promise as fromPromise } from './const'; const unused = { fromPromise }; `; - const { program, compilerHost } = createTypescriptContext(input, additionalFiles); - const result = transformTypescript(undefined, [transformer(program)], program, compilerHost); + const { program, compilerHost } = createTypescriptContext(input, additionalFiles); + const result = transformTypescript(undefined, [transformer(program)], program, compilerHost); - expect(tags.oneLine`${result}`).toEqual('export {};'); - }); + expect(tags.oneLine`${result}`).toEqual('export {};'); + }); - it('should retain used imports in shorthand property assignment', () => { - const input = tags.stripIndent` + it('should retain used imports in shorthand property assignment', () => { + const input = tags.stripIndent` import { promise as fromPromise } from './const'; const used = { fromPromise }; ${dummyNode} `; - const output = tags.stripIndent` + const output = tags.stripIndent` import { promise as fromPromise } from './const'; const used = { fromPromise }; `; - const { program, compilerHost } = createTypescriptContext(input, additionalFiles); - const result = transformTypescript(undefined, [transformer(program)], program, compilerHost); + const { program, compilerHost } = createTypescriptContext(input, additionalFiles); + const result = transformTypescript(undefined, [transformer(program)], program, compilerHost); - expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); - }); + expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); + }); - it('should drop unused default import', () => { - const input = tags.stripIndent` + it('should drop unused default import', () => { + const input = tags.stripIndent` import defaultPromise from './const'; const unused = defaultPromise; `; - const { program, compilerHost } = createTypescriptContext(input, additionalFiles); - const result = transformTypescript(undefined, [transformer(program)], program, compilerHost); + const { program, compilerHost } = createTypescriptContext(input, additionalFiles); + const result = transformTypescript(undefined, [transformer(program)], program, compilerHost); - expect(tags.oneLine`${result}`).toEqual('export {};'); - }); + expect(tags.oneLine`${result}`).toEqual('export {};'); + }); - it('should retain used default import', () => { - const input = tags.stripIndent` + it('should retain used default import', () => { + const input = tags.stripIndent` import defaultPromise from './const'; const used = defaultPromise; ${dummyNode} `; - const output = tags.stripIndent` + const output = tags.stripIndent` import defaultPromise from './const'; const used = defaultPromise; `; - const { program, compilerHost } = createTypescriptContext(input, additionalFiles); - const result = transformTypescript(undefined, [transformer(program)], program, compilerHost); + const { program, compilerHost } = createTypescriptContext(input, additionalFiles); + const result = transformTypescript(undefined, [transformer(program)], program, compilerHost); - expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); - }); + expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); + }); - it('should only drop unused default imports when named and default (1)', () => { - const input = tags.stripIndent` + it('should only drop unused default imports when named and default (1)', () => { + const input = tags.stripIndent` import promise, { promise as fromPromise } from './const'; const used = fromPromise; const unused = promise; `; - const output = tags.stripIndent` + const output = tags.stripIndent` import { promise as fromPromise } from './const'; const used = fromPromise; `; - const { program, compilerHost } = createTypescriptContext(input, additionalFiles); - const result = transformTypescript(undefined, [transformer(program)], program, compilerHost); + const { program, compilerHost } = createTypescriptContext(input, additionalFiles); + const result = transformTypescript(undefined, [transformer(program)], program, compilerHost); - expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); - }); + expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); + }); - it('should only drop unused named imports when named and default (2)', () => { - const input = tags.stripIndent` + it('should only drop unused named imports when named and default (2)', () => { + const input = tags.stripIndent` import promise, { promise as fromPromise, take } from './const'; const used = fromPromise; const unused = promise; `; - const output = tags.stripIndent` + const output = tags.stripIndent` import { promise as fromPromise } from './const'; const used = fromPromise; `; - const { program, compilerHost } = createTypescriptContext(input, additionalFiles); - const result = transformTypescript(undefined, [transformer(program)], program, compilerHost); + const { program, compilerHost } = createTypescriptContext(input, additionalFiles); + const result = transformTypescript(undefined, [transformer(program)], program, compilerHost); - expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); - }); + expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); + }); - it('should only drop default imports when having named and default (3)', () => { - const input = tags.stripIndent` + it('should only drop default imports when having named and default (3)', () => { + const input = tags.stripIndent` import promise, { promise as fromPromise } from './const'; const used = promise; const unused = fromPromise; `; - const output = tags.stripIndent` + const output = tags.stripIndent` import promise from './const'; const used = promise; `; - const { program, compilerHost } = createTypescriptContext(input, additionalFiles); - const result = transformTypescript(undefined, [transformer(program)], program, compilerHost); + const { program, compilerHost } = createTypescriptContext(input, additionalFiles); + const result = transformTypescript(undefined, [transformer(program)], program, compilerHost); - expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); - }); + expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); + }); - it('should retain import clause', () => { - const input = tags.stripIndent` + it('should retain import clause', () => { + const input = tags.stripIndent` import './const'; ${dummyNode} `; - const output = tags.stripIndent` + const output = tags.stripIndent` import './const'; `; - const { program, compilerHost } = createTypescriptContext(input, additionalFiles); - const result = transformTypescript(undefined, [transformer(program)], program, compilerHost); + const { program, compilerHost } = createTypescriptContext(input, additionalFiles); + const result = transformTypescript(undefined, [transformer(program)], program, compilerHost); - expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); - }); + expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); + }); - it(`should remove import for 'ExpressionWithTypeArguments' implements token`, () => { - const input = tags.stripIndent` + it(`should remove import for 'ExpressionWithTypeArguments' implements token`, () => { + const input = tags.stripIndent` import { Bar, Buz, Unused } from './bar'; export class Foo extends Bar implements Buz { } @@ -330,26 +329,26 @@ describe('@ngtools/webpack transformers', () => { ${dummyNode} `; - const output = tags.stripIndent` + const output = tags.stripIndent` import { Bar } from './bar'; export class Foo extends Bar { } `; - const { program, compilerHost } = createTypescriptContext(input); - const result = transformTypescript(undefined, [transformer(program)], program, compilerHost); + const { program, compilerHost } = createTypescriptContext(input); + const result = transformTypescript(undefined, [transformer(program)], program, compilerHost); - expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); - }); + expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); + }); - describe('should elide imports decorator type references when emitDecoratorMetadata is false', () => { - const extraCompilerOptions: ts.CompilerOptions = { - emitDecoratorMetadata: false, - experimentalDecorators: true, - }; + describe('should elide imports decorator type references when emitDecoratorMetadata is false', () => { + const extraCompilerOptions: ts.CompilerOptions = { + emitDecoratorMetadata: false, + experimentalDecorators: true, + }; - it('should remove ctor parameter type reference', () => { - const input = tags.stripIndent` + it('should remove ctor parameter type reference', () => { + const input = tags.stripIndent` import { Decorator } from './decorator'; import { Service } from './service'; @@ -362,7 +361,7 @@ describe('@ngtools/webpack transformers', () => { ${dummyNode} `; - const output = tags.stripIndent` + const output = tags.stripIndent` import { __decorate } from "tslib"; import { Decorator } from './decorator'; @@ -371,24 +370,19 @@ describe('@ngtools/webpack transformers', () => { export { Foo }; `; - const { program, compilerHost } = createTypescriptContext( - input, - additionalFiles, - true, - extraCompilerOptions, - ); - const result = transformTypescript( - undefined, - [transformer(program)], - program, - compilerHost, - ); + const { program, compilerHost } = createTypescriptContext( + input, + additionalFiles, + true, + extraCompilerOptions, + ); + const result = transformTypescript(undefined, [transformer(program)], program, compilerHost); - expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); - }); + expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); + }); - it('should remove ctor parameter type reference and unused named import from same declaration', () => { - const input = tags.stripIndent` + it('should remove ctor parameter type reference and unused named import from same declaration', () => { + const input = tags.stripIndent` import { Decorator } from './decorator'; import { Service, Service2 as ServiceUnused } from './service'; @@ -401,7 +395,7 @@ describe('@ngtools/webpack transformers', () => { ${dummyNode} `; - const output = tags.stripIndent` + const output = tags.stripIndent` import { __decorate } from "tslib"; import { Decorator } from './decorator'; @@ -410,31 +404,26 @@ describe('@ngtools/webpack transformers', () => { export { Foo }; `; - const { program, compilerHost } = createTypescriptContext( - input, - additionalFiles, - true, - extraCompilerOptions, - ); - const result = transformTypescript( - undefined, - [transformer(program)], - program, - compilerHost, - ); + const { program, compilerHost } = createTypescriptContext( + input, + additionalFiles, + true, + extraCompilerOptions, + ); + const result = transformTypescript(undefined, [transformer(program)], program, compilerHost); - expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); - }); + expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); }); + }); - it('keeps jsxFactory imports when configured', () => { - const extraCompilerOptions: ts.CompilerOptions = { - jsxFactory: 'createElement', - experimentalDecorators: true, - jsx: ts.JsxEmit.React, - }; + it('keeps jsxFactory imports when configured', () => { + const extraCompilerOptions: ts.CompilerOptions = { + jsxFactory: 'createElement', + experimentalDecorators: true, + jsx: ts.JsxEmit.React, + }; - const input = tags.stripIndent` + const input = tags.stripIndent` import { Decorator } from './decorator'; import { Service } from './service'; import { createElement } from './jsx'; @@ -450,7 +439,7 @@ describe('@ngtools/webpack transformers', () => { ${dummyNode} `; - const output = tags.stripIndent` + const output = tags.stripIndent` import { __decorate } from "tslib"; import { Decorator } from './decorator'; import { createElement } from './jsx'; @@ -462,26 +451,26 @@ describe('@ngtools/webpack transformers', () => { export { Foo }; `; - const { program, compilerHost } = createTypescriptContext( - input, - additionalFiles, - true, - extraCompilerOptions, - true, - ); - const result = transformTypescript(undefined, [transformer(program)], program, compilerHost); + const { program, compilerHost } = createTypescriptContext( + input, + additionalFiles, + true, + extraCompilerOptions, + true, + ); + const result = transformTypescript(undefined, [transformer(program)], program, compilerHost); - expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); - }); + expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); + }); - describe('should not elide imports decorator type references when emitDecoratorMetadata is true', () => { - const extraCompilerOptions: ts.CompilerOptions = { - emitDecoratorMetadata: true, - experimentalDecorators: true, - }; + describe('should not elide imports decorator type references when emitDecoratorMetadata is true', () => { + const extraCompilerOptions: ts.CompilerOptions = { + emitDecoratorMetadata: true, + experimentalDecorators: true, + }; - it('should elide type only named imports', () => { - const input = tags.stripIndent` + it('should elide type only named imports', () => { + const input = tags.stripIndent` import { Decorator } from './decorator'; import { type OnChanges, type SimpleChanges } from './type'; @@ -493,7 +482,7 @@ describe('@ngtools/webpack transformers', () => { ${dummyNode} `; - const output = tags.stripIndent` + const output = tags.stripIndent` import { __decorate } from "tslib"; import { Decorator } from './decorator'; @@ -502,24 +491,19 @@ describe('@ngtools/webpack transformers', () => { export { Foo }; `; - const { program, compilerHost } = createTypescriptContext( - input, - additionalFiles, - true, - extraCompilerOptions, - ); - const result = transformTypescript( - undefined, - [transformer(program)], - program, - compilerHost, - ); + const { program, compilerHost } = createTypescriptContext( + input, + additionalFiles, + true, + extraCompilerOptions, + ); + const result = transformTypescript(undefined, [transformer(program)], program, compilerHost); - expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); - }); + expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); + }); - it('should not remove ctor parameter type reference', () => { - const input = tags.stripIndent` + it('should not remove ctor parameter type reference', () => { + const input = tags.stripIndent` import { Decorator } from './decorator'; import { Service } from './service'; @@ -532,7 +516,7 @@ describe('@ngtools/webpack transformers', () => { ${dummyNode} `; - const output = tags.stripIndent` + const output = tags.stripIndent` import { __decorate, __metadata } from "tslib"; import { Decorator } from './decorator'; import { Service } from './service'; @@ -542,24 +526,19 @@ describe('@ngtools/webpack transformers', () => { export { Foo }; `; - const { program, compilerHost } = createTypescriptContext( - input, - additionalFiles, - true, - extraCompilerOptions, - ); - const result = transformTypescript( - undefined, - [transformer(program)], - program, - compilerHost, - ); + const { program, compilerHost } = createTypescriptContext( + input, + additionalFiles, + true, + extraCompilerOptions, + ); + const result = transformTypescript(undefined, [transformer(program)], program, compilerHost); - expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); - }); + expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); + }); - it('should not remove property declaration parameter type reference', () => { - const input = tags.stripIndent` + it('should not remove property declaration parameter type reference', () => { + const input = tags.stripIndent` import { Decorator } from './decorator'; import { Service } from './service'; @@ -570,7 +549,7 @@ describe('@ngtools/webpack transformers', () => { ${dummyNode} `; - const output = tags.stripIndent` + const output = tags.stripIndent` import { __decorate, __metadata } from "tslib"; import { Decorator } from './decorator'; @@ -580,24 +559,19 @@ describe('@ngtools/webpack transformers', () => { __decorate([ Decorator(), __metadata("design:type", Service) ], Foo.prototype, "foo", void 0); `; - const { program, compilerHost } = createTypescriptContext( - input, - additionalFiles, - true, - extraCompilerOptions, - ); - const result = transformTypescript( - undefined, - [transformer(program)], - program, - compilerHost, - ); + const { program, compilerHost } = createTypescriptContext( + input, + additionalFiles, + true, + extraCompilerOptions, + ); + const result = transformTypescript(undefined, [transformer(program)], program, compilerHost); - expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); - }); + expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); + }); - it('should not remove set accessor parameter type reference', () => { - const input = tags.stripIndent` + it('should not remove set accessor parameter type reference', () => { + const input = tags.stripIndent` import { Decorator } from './decorator'; import { Service } from './service'; @@ -613,7 +587,7 @@ describe('@ngtools/webpack transformers', () => { ${dummyNode} `; - const output = tags.stripIndent` + const output = tags.stripIndent` import { __decorate, __metadata } from "tslib"; import { Decorator } from './decorator'; import { Service } from './service'; @@ -622,24 +596,19 @@ describe('@ngtools/webpack transformers', () => { __decorate([ Decorator(), __metadata("design:type", Service), __metadata("design:paramtypes", [Service]) ], Foo.prototype, "name", null); `; - const { program, compilerHost } = createTypescriptContext( - input, - additionalFiles, - true, - extraCompilerOptions, - ); - const result = transformTypescript( - undefined, - [transformer(program)], - program, - compilerHost, - ); + const { program, compilerHost } = createTypescriptContext( + input, + additionalFiles, + true, + extraCompilerOptions, + ); + const result = transformTypescript(undefined, [transformer(program)], program, compilerHost); - expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); - }); + expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); + }); - it('should not remove get accessor parameter type reference', () => { - const input = tags.stripIndent` + it('should not remove get accessor parameter type reference', () => { + const input = tags.stripIndent` import { Decorator } from './decorator'; import { Service } from './service'; @@ -655,7 +624,7 @@ describe('@ngtools/webpack transformers', () => { ${dummyNode} `; - const output = tags.stripIndent` + const output = tags.stripIndent` import { __decorate, __metadata } from "tslib"; import { Decorator } from './decorator'; import { Service } from './service'; @@ -664,24 +633,19 @@ describe('@ngtools/webpack transformers', () => { __decorate([ Decorator(), __metadata("design:type", Service), __metadata("design:paramtypes", []) ], Foo.prototype, "name", null); `; - const { program, compilerHost } = createTypescriptContext( - input, - additionalFiles, - true, - extraCompilerOptions, - ); - const result = transformTypescript( - undefined, - [transformer(program)], - program, - compilerHost, - ); + const { program, compilerHost } = createTypescriptContext( + input, + additionalFiles, + true, + extraCompilerOptions, + ); + const result = transformTypescript(undefined, [transformer(program)], program, compilerHost); - expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); - }); + expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); + }); - it('should not remove decorated method return type reference', () => { - const input = tags.stripIndent` + it('should not remove decorated method return type reference', () => { + const input = tags.stripIndent` import { Decorator } from './decorator'; import { Service } from './service'; @@ -695,7 +659,7 @@ describe('@ngtools/webpack transformers', () => { ${dummyNode} `; - const output = tags.stripIndent` + const output = tags.stripIndent` import { __decorate, __metadata } from "tslib"; import { Decorator } from './decorator'; import { Service } from './service'; @@ -705,24 +669,19 @@ describe('@ngtools/webpack transformers', () => { __metadata("design:paramtypes", []), __metadata("design:returntype", Service) ], Foo.prototype, "name", null); `; - const { program, compilerHost } = createTypescriptContext( - input, - additionalFiles, - true, - extraCompilerOptions, - ); - const result = transformTypescript( - undefined, - [transformer(program)], - program, - compilerHost, - ); + const { program, compilerHost } = createTypescriptContext( + input, + additionalFiles, + true, + extraCompilerOptions, + ); + const result = transformTypescript(undefined, [transformer(program)], program, compilerHost); - expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); - }); + expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); + }); - it('should not remove decorated method parameter type reference', () => { - const input = tags.stripIndent` + it('should not remove decorated method parameter type reference', () => { + const input = tags.stripIndent` import { Decorator } from './decorator'; import { Service } from './service'; @@ -735,7 +694,7 @@ describe('@ngtools/webpack transformers', () => { ${dummyNode} `; - const output = tags.stripIndent` + const output = tags.stripIndent` import { __decorate, __metadata } from "tslib"; import { Decorator } from './decorator'; @@ -747,24 +706,19 @@ describe('@ngtools/webpack transformers', () => { __metadata("design:returntype", void 0) ], Foo.prototype, "name", null); `; - const { program, compilerHost } = createTypescriptContext( - input, - additionalFiles, - true, - extraCompilerOptions, - ); - const result = transformTypescript( - undefined, - [transformer(program)], - program, - compilerHost, - ); + const { program, compilerHost } = createTypescriptContext( + input, + additionalFiles, + true, + extraCompilerOptions, + ); + const result = transformTypescript(undefined, [transformer(program)], program, compilerHost); - expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); - }); + expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); + }); - it('should remove type-only imports', () => { - const input = tags.stripIndent` + it('should remove type-only imports', () => { + const input = tags.stripIndent` import { Decorator } from './decorator'; import { Service } from './service'; import type { OnChanges, SimpleChanges } from './type'; @@ -778,7 +732,7 @@ describe('@ngtools/webpack transformers', () => { ${dummyNode} `; - const output = tags.stripIndent` + const output = tags.stripIndent` import { __decorate, __metadata } from "tslib"; import { Decorator } from './decorator'; import { Service } from './service'; @@ -791,39 +745,34 @@ describe('@ngtools/webpack transformers', () => { Foo = __decorate([ Decorator(), __metadata("design:paramtypes", [Service]) ], Foo); `; - const { program, compilerHost } = createTypescriptContext( - input, - additionalFiles, - true, - extraCompilerOptions, - ); - const result = transformTypescript( - undefined, - [transformer(program)], - program, - compilerHost, - ); - - expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); - }); + const { program, compilerHost } = createTypescriptContext( + input, + additionalFiles, + true, + extraCompilerOptions, + ); + const result = transformTypescript(undefined, [transformer(program)], program, compilerHost); - describe('NGTSC - ShorthandPropertyAssignment to PropertyAssignment', () => { - const transformShorthandPropertyAssignment = ( - context: ts.TransformationContext, - ): ts.Transformer => { - const visit: ts.Visitor = (node) => { - if (ts.isShorthandPropertyAssignment(node)) { - return ts.factory.createPropertyAssignment(node.name, node.name); - } + expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); + }); - return ts.visitEachChild(node, (child) => visit(child), context); - }; + describe('NGTSC - ShorthandPropertyAssignment to PropertyAssignment', () => { + const transformShorthandPropertyAssignment = ( + context: ts.TransformationContext, + ): ts.Transformer => { + const visit: ts.Visitor = (node) => { + if (ts.isShorthandPropertyAssignment(node)) { + return ts.factory.createPropertyAssignment(node.name, node.name); + } - return (node) => ts.visitNode(node, visit) as ts.SourceFile; + return ts.visitEachChild(node, (child) => visit(child), context); }; - it('should not elide import when ShorthandPropertyAssignment is transformed to PropertyAssignment', () => { - const input = tags.stripIndent` + return (node) => ts.visitNode(node, visit) as ts.SourceFile; + }; + + it('should not elide import when ShorthandPropertyAssignment is transformed to PropertyAssignment', () => { + const input = tags.stripIndent` import { animations } from './const'; const used = { animations @@ -832,21 +781,20 @@ describe('@ngtools/webpack transformers', () => { ${dummyNode} `; - const output = tags.stripIndent` + const output = tags.stripIndent` import { animations } from './const'; const used = { animations: animations }; `; - const { program, compilerHost } = createTypescriptContext(input, additionalFiles); - const result = transformTypescript( - undefined, - [transformShorthandPropertyAssignment, transformer(program)], - program, - compilerHost, - ); + const { program, compilerHost } = createTypescriptContext(input, additionalFiles); + const result = transformTypescript( + undefined, + [transformShorthandPropertyAssignment, transformer(program)], + program, + compilerHost, + ); - expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); - }); + expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); }); }); }); diff --git a/packages/ngtools/webpack/src/transformers/find_image_domains_spec.ts b/packages/ngtools/webpack/src/transformers/find_image_domains_spec.ts index ddb329412518..70bebf4ec15f 100644 --- a/packages/ngtools/webpack/src/transformers/find_image_domains_spec.ts +++ b/packages/ngtools/webpack/src/transformers/find_image_domains_spec.ts @@ -82,42 +82,43 @@ function inputTemplateComponent(provider: string) { `; } -function runSharedTests(template: (povider: string) => string) { - it('should find a domain when a built-in loader is used with a string-literal-like argument', () => { - // Intentionally inconsistent use of quote styles in this data structure: - const builtInLoaders: Array<[string, string]> = [ - ['provideCloudflareLoader("www.cloudflaredomain.com")', 'www.cloudflaredomain.com'], - [ - "provideCloudinaryLoader('https://www.cloudinarydomain.net')", - 'https://www.cloudinarydomain.net', - ], - ['provideImageKitLoader("www.imageKitdomain.com")', 'www.imageKitdomain.com'], - ['provideImgixLoader(`www.imgixdomain.com/images/`)', 'www.imgixdomain.com/images/'], - ]; - for (const loader of builtInLoaders) { - const input = template(loader[0]); - const result = Array.from(findDomains(input)); - expect(result.length).toBe(1); - expect(result[0]).toBe(loader[1]); - } - }); +function runSharedTests(name: string, template: (povider: string) => string) { + describe(name, () => { + it(`should find a domain when a built-in loader is used with a string-literal-like argument`, () => { + // Intentionally inconsistent use of quote styles in this data structure: + const builtInLoaders: Array<[string, string]> = [ + ['provideCloudflareLoader("www.cloudflaredomain.com")', 'www.cloudflaredomain.com'], + [ + "provideCloudinaryLoader('https://www.cloudinarydomain.net')", + 'https://www.cloudinarydomain.net', + ], + ['provideImageKitLoader("www.imageKitdomain.com")', 'www.imageKitdomain.com'], + ['provideImgixLoader(`www.imgixdomain.com/images/`)', 'www.imgixdomain.com/images/'], + ]; + for (const loader of builtInLoaders) { + const input = template(loader[0]); + const result = Array.from(findDomains(input)); + expect(result.length).toBe(1); + expect(result[0]).toBe(loader[1]); + } + }); - it('should find a domain in a custom loader function with a template literal', () => { - const customLoader = tags.stripIndent` + it(`should find a domain in a custom loader function with a template literal`, () => { + const customLoader = tags.stripIndent` { provide: IMAGE_LOADER, useValue: (config: ImageLoaderConfig) => { return ${'`https://customLoaderTemplate.com/images?src=${config.src}&width=${config.width}`'}; }, },`; - const input = template(customLoader); - const result = Array.from(findDomains(input)); - expect(result.length).toBe(1); - expect(result[0]).toBe('https://customLoaderTemplate.com/'); - }); + const input = template(customLoader); + const result = Array.from(findDomains(input)); + expect(result.length).toBe(1); + expect(result[0]).toBe('https://customLoaderTemplate.com/'); + }); - it('should find a domain when provider is alongside other providers', () => { - const customLoader = tags.stripIndent` + it('should find a domain when provider is alongside other providers', () => { + const customLoader = tags.stripIndent` { provide: SOME_OTHER_PROVIDER, useValue: (config: ImageLoaderConfig) => { @@ -137,71 +138,70 @@ function runSharedTests(template: (povider: string) => string) { return ${'`https://notacustomloadertemplate.com/images?src=${config.src}&width=${config.width}`'}; }, },`; - const input = template(customLoader); - const result = Array.from(findDomains(input)); - expect(result.length).toBe(1); - expect(result[0]).toBe('https://customloadertemplate.com/'); + const input = template(customLoader); + const result = Array.from(findDomains(input)); + expect(result.length).toBe(1); + expect(result[0]).toBe('https://customloadertemplate.com/'); + }); }); } -describe('@ngtools/webpack transformers', () => { - describe('find_image_domains (app module)', () => { - runSharedTests(inputTemplateAppModule); - runSharedTests(inputTemplateComponent); +describe('find_image_domains (app module)', () => { + runSharedTests('inputTemplateAppModule', inputTemplateAppModule); + runSharedTests('inputTemplateComponent', inputTemplateComponent); - it('should not find a domain when a built-in loader is used with a variable', () => { - const input = inputTemplateAppModule(`provideCloudflareLoader(myImageCDN)`); - const result = Array.from(findDomains(input)); - expect(result.length).toBe(0); - }); + it('should not find a domain when a built-in loader is used with a variable', () => { + const input = inputTemplateAppModule(`provideCloudflareLoader(myImageCDN)`); + const result = Array.from(findDomains(input)); + expect(result.length).toBe(0); + }); - it('should not find a domain when a built-in loader is used with an expression', () => { - const input = inputTemplateAppModule( - `provideCloudflareLoader("https://www." + (dev ? "dev." : "") + "cloudinarydomain.net")`, - ); - const result = Array.from(findDomains(input)); - expect(result.length).toBe(0); - }); + it('should not find a domain when a built-in loader is used with an expression', () => { + const input = inputTemplateAppModule( + `provideCloudflareLoader("https://www." + (dev ? "dev." : "") + "cloudinarydomain.net")`, + ); + const result = Array.from(findDomains(input)); + expect(result.length).toBe(0); + }); - it('should not find a domain when a built-in loader is used with a template literal', () => { - const input = inputTemplateAppModule( - 'provideCloudflareLoader(`https://www.${dev ? "dev." : ""}cloudinarydomain.net`)', - ); - const result = Array.from(findDomains(input)); - expect(result.length).toBe(0); - }); + it('should not find a domain when a built-in loader is used with a template literal', () => { + const input = inputTemplateAppModule( + 'provideCloudflareLoader(`https://www.${dev ? "dev." : ""}cloudinarydomain.net`)', + ); + const result = Array.from(findDomains(input)); + expect(result.length).toBe(0); + }); - it('should not find a domain in a function that is not a built-in loader', () => { - const input = inputTemplateAppModule('provideNotARealLoader("https://www.foo.com")'); - const result = Array.from(findDomains(input)); - expect(result.length).toBe(0); - }); + it('should not find a domain in a function that is not a built-in loader', () => { + const input = inputTemplateAppModule('provideNotARealLoader("https://www.foo.com")'); + const result = Array.from(findDomains(input)); + expect(result.length).toBe(0); + }); - it('should find a domain in a custom loader function with string concatenation', () => { - const customLoader = tags.stripIndent` + it('should find a domain in a custom loader function with string concatenation', () => { + const customLoader = tags.stripIndent` { provide: IMAGE_LOADER, useValue: (config: ImageLoaderConfig) => { return "https://customLoaderString.com/images?src=" + config.src + "&width=" + config.width; }, },`; - const input = inputTemplateAppModule(customLoader); - const result = Array.from(findDomains(input)); - expect(result.length).toBe(1); - expect(result[0]).toBe('https://customLoaderString.com/'); - }); + const input = inputTemplateAppModule(customLoader); + const result = Array.from(findDomains(input)); + expect(result.length).toBe(1); + expect(result[0]).toBe('https://customLoaderString.com/'); + }); - it('should not find a domain if not an IMAGE_LOADER provider', () => { - const customLoader = tags.stripIndent` + it('should not find a domain if not an IMAGE_LOADER provider', () => { + const customLoader = tags.stripIndent` { provide: SOME_OTHER_PROVIDER, useValue: (config: ImageLoaderConfig) => { return "https://customLoaderString.com/images?src=" + config.src + "&width=" + config.width; }, },`; - const input = inputTemplateAppModule(customLoader); - const result = Array.from(findDomains(input)); - expect(result.length).toBe(0); - }); + const input = inputTemplateAppModule(customLoader); + const result = Array.from(findDomains(input)); + expect(result.length).toBe(0); }); }); diff --git a/packages/ngtools/webpack/src/transformers/remove-ivy-jit-support-calls_spec.ts b/packages/ngtools/webpack/src/transformers/remove-ivy-jit-support-calls_spec.ts index d0ea21aa3054..2c2a2d73f9e7 100644 --- a/packages/ngtools/webpack/src/transformers/remove-ivy-jit-support-calls_spec.ts +++ b/packages/ngtools/webpack/src/transformers/remove-ivy-jit-support-calls_spec.ts @@ -187,10 +187,9 @@ const inputDebugInfo = tags.stripIndent` (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(TestCmp, { className: "TestCmp" }); })(); `; -describe('@ngtools/webpack transformers', () => { - describe('remove-ivy-dev-calls', () => { - it('should allow removing only set class metadata with pure annotation', () => { - const output = tags.stripIndent` +describe('remove-ivy-dev-calls', () => { + it('should allow removing only set class metadata with pure annotation', () => { + const output = tags.stripIndent` export class AppModule { } AppModule.ɵmod = i0.ɵɵdefineNgModule({ type: AppModule, bootstrap: [AppComponent] }); @@ -203,15 +202,15 @@ describe('@ngtools/webpack transformers', () => { AppRoutingModule] }); })(); `; - const result = transform(input, (getTypeChecker) => - removeIvyJitSupportCalls(true, false, false, getTypeChecker), - ); + const result = transform(input, (getTypeChecker) => + removeIvyJitSupportCalls(true, false, false, getTypeChecker), + ); - expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); - }); + expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); + }); - it('should allow removing only set class metadata', () => { - const output = tags.stripIndent` + it('should allow removing only set class metadata', () => { + const output = tags.stripIndent` export class AppModule { } AppModule.ɵmod = i0.ɵɵdefineNgModule({ type: AppModule, bootstrap: [AppComponent] }); @@ -224,15 +223,15 @@ describe('@ngtools/webpack transformers', () => { AppRoutingModule] }); })(); `; - const result = transform(inputNoPure, (getTypeChecker) => - removeIvyJitSupportCalls(true, false, false, getTypeChecker), - ); + const result = transform(inputNoPure, (getTypeChecker) => + removeIvyJitSupportCalls(true, false, false, getTypeChecker), + ); - expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); - }); + expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); + }); - it('should allow removing only ng module scope with pure annotation', () => { - const output = tags.stripIndent` + it('should allow removing only ng module scope with pure annotation', () => { + const output = tags.stripIndent` export class AppModule { } AppModule.ɵmod = i0.ɵɵdefineNgModule({ type: AppModule, bootstrap: [AppComponent] }); @@ -257,15 +256,15 @@ describe('@ngtools/webpack transformers', () => { }], null, null); })(); `; - const result = transform(input, (getTypeChecker) => - removeIvyJitSupportCalls(false, true, false, getTypeChecker), - ); + const result = transform(input, (getTypeChecker) => + removeIvyJitSupportCalls(false, true, false, getTypeChecker), + ); - expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); - }); + expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); + }); - it('should allow removing only ng module scope', () => { - const output = tags.stripIndent` + it('should allow removing only ng module scope', () => { + const output = tags.stripIndent` export class AppModule { } AppModule.ɵmod = i0.ɵɵdefineNgModule({ type: AppModule, bootstrap: [AppComponent] }); @@ -290,15 +289,15 @@ describe('@ngtools/webpack transformers', () => { }], null, null); })(); `; - const result = transform(inputNoPure, (getTypeChecker) => - removeIvyJitSupportCalls(false, true, false, getTypeChecker), - ); + const result = transform(inputNoPure, (getTypeChecker) => + removeIvyJitSupportCalls(false, true, false, getTypeChecker), + ); - expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); - }); + expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); + }); - it('should allow removing both set class metadata and ng module scope with pure annotation', () => { - const output = tags.stripIndent` + it('should allow removing both set class metadata and ng module scope with pure annotation', () => { + const output = tags.stripIndent` export class AppModule { } AppModule.ɵmod = i0.ɵɵdefineNgModule({ type: AppModule, bootstrap: [AppComponent] }); @@ -308,15 +307,15 @@ describe('@ngtools/webpack transformers', () => { ]] }); `; - const result = transform(input, (getTypeChecker) => - removeIvyJitSupportCalls(true, true, false, getTypeChecker), - ); + const result = transform(input, (getTypeChecker) => + removeIvyJitSupportCalls(true, true, false, getTypeChecker), + ); - expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); - }); + expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); + }); - it('should allow removing both set class metadata and ng module scope', () => { - const output = tags.stripIndent` + it('should allow removing both set class metadata and ng module scope', () => { + const output = tags.stripIndent` export class AppModule { } AppModule.ɵmod = i0.ɵɵdefineNgModule({ type: AppModule, bootstrap: [AppComponent] }); @@ -326,31 +325,31 @@ describe('@ngtools/webpack transformers', () => { ]] }); `; - const result = transform(inputNoPure, (getTypeChecker) => - removeIvyJitSupportCalls(true, true, false, getTypeChecker), - ); + const result = transform(inputNoPure, (getTypeChecker) => + removeIvyJitSupportCalls(true, true, false, getTypeChecker), + ); - expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); - }); + expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); + }); - it('should allow removing neither set class metadata nor ng module scope with pure annotation', () => { - const result = transform(input, (getTypeChecker) => - removeIvyJitSupportCalls(false, false, false, getTypeChecker), - ); + it('should allow removing neither set class metadata nor ng module scope with pure annotation', () => { + const result = transform(input, (getTypeChecker) => + removeIvyJitSupportCalls(false, false, false, getTypeChecker), + ); - expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${input}`); - }); + expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${input}`); + }); - it('should allow removing neither set class metadata nor ng module scope', () => { - const result = transform(inputNoPure, (getTypeChecker) => - removeIvyJitSupportCalls(false, false, false, getTypeChecker), - ); + it('should allow removing neither set class metadata nor ng module scope', () => { + const result = transform(inputNoPure, (getTypeChecker) => + removeIvyJitSupportCalls(false, false, false, getTypeChecker), + ); - expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${inputNoPure}`); - }); + expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${inputNoPure}`); + }); - it('should strip unused imports when removing set class metadata and ng module scope with pure annotation', () => { - const imports = tags.stripIndent` + it('should strip unused imports when removing set class metadata and ng module scope with pure annotation', () => { + const imports = tags.stripIndent` import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { AppRoutingModule } from './app-routing.module'; @@ -359,7 +358,7 @@ describe('@ngtools/webpack transformers', () => { import * as i0 from "@angular/core"; `; - const output = tags.stripIndent` + const output = tags.stripIndent` import { BrowserModule } from '@angular/platform-browser'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; @@ -373,15 +372,15 @@ describe('@ngtools/webpack transformers', () => { ]] }); `; - const result = transform(imports + input, (getTypeChecker) => - removeIvyJitSupportCalls(true, true, false, getTypeChecker), - ); + const result = transform(imports + input, (getTypeChecker) => + removeIvyJitSupportCalls(true, true, false, getTypeChecker), + ); - expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); - }); + expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); + }); - it('should strip unused imports when removing set class metadata and ng module scope', () => { - const imports = tags.stripIndent` + it('should strip unused imports when removing set class metadata and ng module scope', () => { + const imports = tags.stripIndent` import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { AppRoutingModule } from './app-routing.module'; @@ -390,7 +389,7 @@ describe('@ngtools/webpack transformers', () => { import * as i0 from "@angular/core"; `; - const output = tags.stripIndent` + const output = tags.stripIndent` import { BrowserModule } from '@angular/platform-browser'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; @@ -404,15 +403,15 @@ describe('@ngtools/webpack transformers', () => { ]] }); `; - const result = transform(imports + inputNoPure, (getTypeChecker) => - removeIvyJitSupportCalls(true, true, false, getTypeChecker), - ); + const result = transform(imports + inputNoPure, (getTypeChecker) => + removeIvyJitSupportCalls(true, true, false, getTypeChecker), + ); - expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); - }); + expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); + }); - it('should remove setClassMetadata and setNgModuleScope calls inside arrow-function-based IIFEs that have bodies', () => { - const output = tags.stripIndent` + it('should remove setClassMetadata and setNgModuleScope calls inside arrow-function-based IIFEs that have bodies', () => { + const output = tags.stripIndent` export class AppModule { } AppModule.ɵmod = i0.ɵɵdefineNgModule({ type: AppModule, bootstrap: [AppComponent] }); @@ -422,15 +421,15 @@ describe('@ngtools/webpack transformers', () => { ]] }); `; - const result = transform(inputArrowFnWithBody, (getTypeChecker) => - removeIvyJitSupportCalls(true, true, false, getTypeChecker), - ); + const result = transform(inputArrowFnWithBody, (getTypeChecker) => + removeIvyJitSupportCalls(true, true, false, getTypeChecker), + ); - expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); - }); + expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); + }); - it('should remove setClassMetadata and setNgModuleScope calls inside arrow-function-based IIFEs that have an implicit return', () => { - const output = tags.stripIndent` + it('should remove setClassMetadata and setNgModuleScope calls inside arrow-function-based IIFEs that have an implicit return', () => { + const output = tags.stripIndent` export class AppModule { } AppModule.ɵmod = i0.ɵɵdefineNgModule({ type: AppModule, bootstrap: [AppComponent] }); @@ -440,56 +439,55 @@ describe('@ngtools/webpack transformers', () => { ]] }); `; - const result = transform(inputArrowFnWithImplicitReturn, (getTypeChecker) => - removeIvyJitSupportCalls(true, true, false, getTypeChecker), - ); + const result = transform(inputArrowFnWithImplicitReturn, (getTypeChecker) => + removeIvyJitSupportCalls(true, true, false, getTypeChecker), + ); - expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); - }); + expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); + }); - it('should remove setClassMetadataAsync calls', () => { - const output = tags.stripIndent` + it('should remove setClassMetadataAsync calls', () => { + const output = tags.stripIndent` export class TestCmp { } TestCmp.ɵfac = function TestCmp_Factory(t) { return new (t || TestCmp)(); }; TestCmp.ɵcmp = i0.ɵɵdefineComponent({ type: TestCmp, selectors: [["test-cmp"]], standalone: true, features: [i0.ɵɵStandaloneFeature], decls: 3, vars: 0, template: function TestCmp_Template(rf, ctx) { }, encapsulation: 2 }); `; - const result = transform(inputAsync, (getTypeChecker) => - removeIvyJitSupportCalls(true, false, false, getTypeChecker), - ); + const result = transform(inputAsync, (getTypeChecker) => + removeIvyJitSupportCalls(true, false, false, getTypeChecker), + ); - expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); - }); + expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); + }); - it('should remove arrow-function-based setClassMetadataAsync calls', () => { - const output = tags.stripIndent` + it('should remove arrow-function-based setClassMetadataAsync calls', () => { + const output = tags.stripIndent` export class TestCmp { } TestCmp.ɵfac = function TestCmp_Factory(t) { return new (t || TestCmp)(); }; TestCmp.ɵcmp = i0.ɵɵdefineComponent({ type: TestCmp, selectors: [["test-cmp"]], standalone: true, features: [i0.ɵɵStandaloneFeature], decls: 3, vars: 0, template: function TestCmp_Template(rf, ctx) { }, encapsulation: 2 }); `; - const result = transform(inputAsyncArrowFn, (getTypeChecker) => - removeIvyJitSupportCalls(true, false, false, getTypeChecker), - ); + const result = transform(inputAsyncArrowFn, (getTypeChecker) => + removeIvyJitSupportCalls(true, false, false, getTypeChecker), + ); - expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); - }); + expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); + }); - it('should remove setClassDebugInfo calls', () => { - const output = tags.stripIndent` + it('should remove setClassDebugInfo calls', () => { + const output = tags.stripIndent` import * as i0 from "@angular/core"; export class TestCmp { } TestCmp.ɵfac = function TestCmp_Factory(t) { return new (t || TestCmp)(); }; TestCmp.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: TestCmp, selectors: [["test-cmp"]], decls: 0, vars: 0, template: function TestCmp_Template(rf, ctx) { }, encapsulation: 2 }); `; - const result = transform(inputDebugInfo, (getTypeChecker) => - removeIvyJitSupportCalls(true, false, true, getTypeChecker), - ); + const result = transform(inputDebugInfo, (getTypeChecker) => + removeIvyJitSupportCalls(true, false, true, getTypeChecker), + ); - expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); - }); + expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); }); }); diff --git a/packages/ngtools/webpack/src/transformers/replace_resources_spec.ts b/packages/ngtools/webpack/src/transformers/replace_resources_spec.ts index 8b15f5d55b09..e0be8e4ebb03 100644 --- a/packages/ngtools/webpack/src/transformers/replace_resources_spec.ts +++ b/packages/ngtools/webpack/src/transformers/replace_resources_spec.ts @@ -27,10 +27,9 @@ function transform( return transformTypescript(input, [transformer], program, compilerHost); } -describe('@ngtools/webpack transformers', () => { - describe('find_resources', () => { - it('should replace resources', () => { - const input = tags.stripIndent` +describe('find_resources', () => { + it('should replace resources', () => { + const input = tags.stripIndent` import { Component } from '@angular/core'; @Component({ @@ -42,7 +41,7 @@ describe('@ngtools/webpack transformers', () => { title = 'app'; } `; - const output = tags.stripIndent` + const output = tags.stripIndent` import { __decorate } from "tslib"; import __NG_CLI_RESOURCE__0 from "./app.component.html?ngResource"; import __NG_CLI_RESOURCE__1 from "./app.component.css?ngResource"; @@ -64,12 +63,12 @@ describe('@ngtools/webpack transformers', () => { export { AppComponent }; `; - const result = transform(input); - expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); - }); + const result = transform(input); + expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); + }); - it('should replace resources with `require()` when module is CommonJs', () => { - const input = tags.stripIndent` + it('should replace resources with `require()` when module is CommonJs', () => { + const input = tags.stripIndent` import { Component } from '@angular/core'; @Component({ @@ -82,7 +81,7 @@ describe('@ngtools/webpack transformers', () => { } `; - const output = tags.stripIndent` + const output = tags.stripIndent` "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.AppComponent = void 0; @@ -100,12 +99,12 @@ describe('@ngtools/webpack transformers', () => { styles: [require("./app.component.css?ngResource"), require("./app.component.2.css?ngResource")] }) ], AppComponent); `; - const result = transform(input, true, true, ts.ModuleKind.CommonJS); - expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); - }); + const result = transform(input, true, true, ts.ModuleKind.CommonJS); + expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); + }); - it('should support svg as templates', () => { - const input = tags.stripIndent` + it('should support svg as templates', () => { + const input = tags.stripIndent` import { Component } from '@angular/core'; @Component({ @@ -116,7 +115,7 @@ describe('@ngtools/webpack transformers', () => { title = 'app'; } `; - const output = tags.stripIndent` + const output = tags.stripIndent` import { __decorate } from "tslib"; import __NG_CLI_RESOURCE__0 from "./app.component.svg?ngResource"; import { Component } from '@angular/core'; @@ -134,12 +133,12 @@ describe('@ngtools/webpack transformers', () => { export { AppComponent }; `; - const result = transform(input); - expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); - }); + const result = transform(input); + expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); + }); - it('should merge styleUrls with styles', () => { - const input = tags.stripIndent` + it('should merge styleUrls with styles', () => { + const input = tags.stripIndent` import { Component } from '@angular/core'; @Component({ @@ -152,7 +151,7 @@ describe('@ngtools/webpack transformers', () => { title = 'app'; } `; - const output = tags.stripIndent` + const output = tags.stripIndent` import { __decorate } from "tslib"; import __NG_CLI_RESOURCE__0 from "./app.component.html?ngResource"; import __NG_CLI_RESOURCE__1 from "./app.component.css?ngResource"; @@ -173,12 +172,12 @@ describe('@ngtools/webpack transformers', () => { export { AppComponent }; `; - const result = transform(input); - expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); - }); + const result = transform(input); + expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); + }); - it('should replace resources with backticks', () => { - const input = ` + it('should replace resources with backticks', () => { + const input = ` import { Component } from '@angular/core'; @Component({ @@ -190,7 +189,7 @@ describe('@ngtools/webpack transformers', () => { title = 'app'; } `; - const output = ` + const output = ` import { __decorate } from "tslib"; import __NG_CLI_RESOURCE__0 from "./app.component.html?ngResource"; import __NG_CLI_RESOURCE__1 from "./app.component.css?ngResource"; @@ -212,12 +211,12 @@ describe('@ngtools/webpack transformers', () => { export { AppComponent }; `; - const result = transform(input); - expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); - }); + const result = transform(input); + expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); + }); - it('should replace resources if Component decorator is aliased', () => { - const input = tags.stripIndent` + it('should replace resources if Component decorator is aliased', () => { + const input = tags.stripIndent` import { Component as NgComponent } from '@angular/core'; @NgComponent({ @@ -229,7 +228,7 @@ describe('@ngtools/webpack transformers', () => { title = 'app'; } `; - const output = tags.stripIndent` + const output = tags.stripIndent` import { __decorate } from "tslib"; import __NG_CLI_RESOURCE__0 from "./app.component.html?ngResource"; import __NG_CLI_RESOURCE__1 from "./app.component.css?ngResource"; @@ -251,16 +250,16 @@ describe('@ngtools/webpack transformers', () => { export { AppComponent }; `; - const { program } = createTypescriptContext(input); - const getTypeChecker = () => program.getTypeChecker(); - const transformer = replaceResources(() => true, getTypeChecker); - const result = transformTypescript(input, [transformer]); + const { program } = createTypescriptContext(input); + const getTypeChecker = () => program.getTypeChecker(); + const transformer = replaceResources(() => true, getTypeChecker); + const result = transformTypescript(input, [transformer]); - expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); - }); + expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); + }); - it('should replace resources if Angular Core import is namespaced', () => { - const input = tags.stripIndent` + it('should replace resources if Angular Core import is namespaced', () => { + const input = tags.stripIndent` import * as ng from '@angular/core'; @ng.Component({ @@ -272,7 +271,7 @@ describe('@ngtools/webpack transformers', () => { title = 'app'; } `; - const output = tags.stripIndent` + const output = tags.stripIndent` import { __decorate } from "tslib"; import __NG_CLI_RESOURCE__0 from "./app.component.html?ngResource"; import __NG_CLI_RESOURCE__1 from "./app.component.css?ngResource"; @@ -294,12 +293,12 @@ describe('@ngtools/webpack transformers', () => { export { AppComponent }; `; - const result = transform(input); - expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); - }); + const result = transform(input); + expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); + }); - it('should replace resources specified as string literals', () => { - const input = tags.stripIndent` + it('should replace resources specified as string literals', () => { + const input = tags.stripIndent` import { Component } from '@angular/core'; @Component({ @@ -312,7 +311,7 @@ describe('@ngtools/webpack transformers', () => { title = 'app'; } `; - const output = tags.stripIndent` + const output = tags.stripIndent` import { __decorate } from "tslib"; import __NG_CLI_RESOURCE__0 from "./app.component.html?ngResource"; import __NG_CLI_RESOURCE__1 from "./app.component.css?ngResource"; @@ -333,12 +332,12 @@ describe('@ngtools/webpack transformers', () => { export { AppComponent }; `; - const result = transform(input); - expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); - }); + const result = transform(input); + expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); + }); - it('should not replace resources if not in Component decorator', () => { - const input = tags.stripIndent` + it('should not replace resources if not in Component decorator', () => { + const input = tags.stripIndent` import { Component } from '@angular/core'; @Component({ @@ -356,7 +355,7 @@ describe('@ngtools/webpack transformers', () => { } `; - const output = tags.stripIndent` + const output = tags.stripIndent` import { __decorate } from "tslib"; import __NG_CLI_RESOURCE__0 from "./app.component.html?ngResource"; import __NG_CLI_RESOURCE__1 from "./app.component.css?ngResource"; @@ -384,12 +383,12 @@ describe('@ngtools/webpack transformers', () => { export { AppComponent }; `; - const result = transform(input); - expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); - }); + const result = transform(input); + expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); + }); - it('should not replace resources if not in an NG Component decorator', () => { - const input = tags.stripIndent` + it('should not replace resources if not in an NG Component decorator', () => { + const input = tags.stripIndent` import { Component } from 'foo'; @Component({ @@ -407,7 +406,7 @@ describe('@ngtools/webpack transformers', () => { } `; - const output = tags.stripIndent` + const output = tags.stripIndent` import { __decorate } from "tslib"; import { Component } from 'foo'; @@ -432,12 +431,12 @@ describe('@ngtools/webpack transformers', () => { export { AppComponent }; `; - const result = transform(input); - expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); - }); + const result = transform(input); + expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); + }); - it('should not replace resources if shouldTransform returns false', () => { - const input = tags.stripIndent` + it('should not replace resources if shouldTransform returns false', () => { + const input = tags.stripIndent` import { Component } from '@angular/core'; @Component({ @@ -449,7 +448,7 @@ describe('@ngtools/webpack transformers', () => { title = 'app'; } `; - const output = ` + const output = ` import { __decorate } from "tslib"; import { Component } from '@angular/core'; let AppComponent = class AppComponent { @@ -467,8 +466,7 @@ describe('@ngtools/webpack transformers', () => { export { AppComponent }; `; - const result = transform(input, false); - expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); - }); + const result = transform(input, false); + expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`); }); }); diff --git a/packages/schematics/angular/e2e/index_spec.ts b/packages/schematics/angular/e2e/index_spec.ts index e04e4ca177b5..d8253e52154f 100644 --- a/packages/schematics/angular/e2e/index_spec.ts +++ b/packages/schematics/angular/e2e/index_spec.ts @@ -11,7 +11,7 @@ import { Schema as ApplicationOptions } from '../application/schema'; import { Schema as WorkspaceOptions } from '../workspace/schema'; import { Schema as E2eOptions } from './schema'; -describe('Application Schematic', () => { +describe('E2E Schematic', () => { const schematicRunner = new SchematicTestRunner( '@schematics/angular', require.resolve('../collection.json'), diff --git a/packages/schematics/angular/enum/index_spec.ts b/packages/schematics/angular/enum/index_spec.ts index f6bee88e7243..1b0e8edcad0d 100644 --- a/packages/schematics/angular/enum/index_spec.ts +++ b/packages/schematics/angular/enum/index_spec.ts @@ -41,13 +41,6 @@ describe('Enum Schematic', () => { appTree = await schematicRunner.runSchematic('application', appOptions, appTree); }); - it('should create an enumeration', async () => { - const tree = await schematicRunner.runSchematic('enum', defaultOptions, appTree); - - const files = tree.files; - expect(files).toContain('/projects/bar/src/app/foo.ts'); - }); - it('should create an enumeration', async () => { const tree = await schematicRunner.runSchematic('enum', defaultOptions, appTree); diff --git a/packages/schematics/angular/library/index_spec.ts b/packages/schematics/angular/library/index_spec.ts index bf4f8714294e..9d76bb913d17 100644 --- a/packages/schematics/angular/library/index_spec.ts +++ b/packages/schematics/angular/library/index_spec.ts @@ -414,7 +414,7 @@ describe('Library Schematic', () => { expect(workspace.projects.foo.architect.test.builder).toBe('@angular/build:unit-test'); }); - it(`should add 'unit-test' test builder`, async () => { + it(`should add 'unit-test' test builder when vitest is available`, async () => { const packageJson = getJsonFileContent(workspaceTree, 'package.json'); packageJson['devDependencies']['vitest'] = '^4.0.0'; workspaceTree.overwrite('package.json', JSON.stringify(packageJson)); diff --git a/packages/schematics/angular/module/index_spec.ts b/packages/schematics/angular/module/index_spec.ts index 661142b66fc7..8224f3642111 100644 --- a/packages/schematics/angular/module/index_spec.ts +++ b/packages/schematics/angular/module/index_spec.ts @@ -70,15 +70,6 @@ describe('Module Schematic', () => { expect(content).toMatch(/imports: \[[^\]]*FooModule[^\]]*\]/m); }); - it('should import into another module when using flat', async () => { - const options = { ...defaultOptions, flat: true, module: 'app-module.ts' }; - - const tree = await schematicRunner.runSchematic('module', options, appTree); - const content = tree.readContent('/projects/bar/src/app/app-module.ts'); - expect(content).toMatch(/import { FooModule } from '.\/foo-module'/); - expect(content).toMatch(/imports: \[[^\]]*FooModule[^\]]*\]/m); - }); - it('should import into another module (deep)', async () => { let tree = appTree; diff --git a/packages/schematics/angular/refactor/jasmine-vitest/test-file-transformer_add-imports_spec.ts b/packages/schematics/angular/refactor/jasmine-vitest/test-file-transformer_add-imports_spec.ts index 1fd4beb6546e..6cef7fc3d5ca 100644 --- a/packages/schematics/angular/refactor/jasmine-vitest/test-file-transformer_add-imports_spec.ts +++ b/packages/schematics/angular/refactor/jasmine-vitest/test-file-transformer_add-imports_spec.ts @@ -8,60 +8,59 @@ import { expectTransformation } from './test-helpers'; -describe('Jasmine to Vitest Transformer', () => { - describe('addImports option', () => { - it('should add value imports when addImports is true', async () => { - const input = `spyOn(foo, 'bar');`; - const expected = ` +describe('Jasmine to Vitest Transformer - addImports option', () => { + it('should add value imports when addImports is true', async () => { + const input = `spyOn(foo, 'bar');`; + const expected = ` import { vi } from 'vitest'; vi.spyOn(foo, 'bar'); `; - await expectTransformation(input, expected, true); - }); + await expectTransformation(input, expected, true); + }); - it('should generate a single, combined import for value and type imports when addImports is true', async () => { - const input = ` + it('should generate a single, combined import for value and type imports when addImports is true', async () => { + const input = ` let mySpy: jasmine.Spy; spyOn(foo, 'bar'); `; - const expected = ` + const expected = ` import { type Mock, vi } from 'vitest'; let mySpy: Mock; vi.spyOn(foo, 'bar'); `; - await expectTransformation(input, expected, true); - }); + await expectTransformation(input, expected, true); + }); - it('should only add type imports when addImports is false', async () => { - const input = ` + it('should only add type imports when addImports is false', async () => { + const input = ` let mySpy: jasmine.Spy; spyOn(foo, 'bar'); `; - const expected = ` + const expected = ` import type { Mock } from 'vitest'; let mySpy: Mock; vi.spyOn(foo, 'bar'); `; - await expectTransformation(input, expected, false); - }); + await expectTransformation(input, expected, false); + }); - it('should not add an import if no Vitest APIs are used, even when addImports is true', async () => { - const input = `const a = 1;`; - const expected = `const a = 1;`; - await expectTransformation(input, expected, true); - }); + it('should not add an import if no Vitest APIs are used, even when addImports is true', async () => { + const input = `const a = 1;`; + const expected = `const a = 1;`; + await expectTransformation(input, expected, true); + }); - it('should add imports for top-level describe and it when addImports is true', async () => { - const input = ` + it('should add imports for top-level describe and it when addImports is true', async () => { + const input = ` describe('My Suite', () => { it('should do something', () => { // test content }); }); `; - const expected = ` + const expected = ` import { describe, it } from 'vitest'; describe('My Suite', () => { @@ -70,26 +69,26 @@ describe('Jasmine to Vitest Transformer', () => { }); }); `; - await expectTransformation(input, expected, true); - }); + await expectTransformation(input, expected, true); + }); - it('should add imports for top-level expect when addImports is true', async () => { - const input = `expect(true).toBe(true);`; - const expected = ` + it('should add imports for top-level expect when addImports is true', async () => { + const input = `expect(true).toBe(true);`; + const expected = ` import { expect } from 'vitest'; expect(true).toBe(true); `; - await expectTransformation(input, expected, true); - }); + await expectTransformation(input, expected, true); + }); - it('should add imports for beforeEach and afterEach when addImports is true', async () => { - const input = ` + it('should add imports for beforeEach and afterEach when addImports is true', async () => { + const input = ` describe('My Suite', () => { beforeEach(() => {}); afterEach(() => {}); }); `; - const expected = ` + const expected = ` import { afterEach, beforeEach, describe } from 'vitest'; describe('My Suite', () => { @@ -97,17 +96,17 @@ describe('Jasmine to Vitest Transformer', () => { afterEach(() => {}); }); `; - await expectTransformation(input, expected, true); - }); + await expectTransformation(input, expected, true); + }); - it('should add imports for beforeAll and afterAll when addImports is true', async () => { - const input = ` + it('should add imports for beforeAll and afterAll when addImports is true', async () => { + const input = ` describe('My Suite', () => { beforeAll(() => {}); afterAll(() => {}); }); `; - const expected = ` + const expected = ` import { afterAll, beforeAll, describe } from 'vitest'; describe('My Suite', () => { @@ -115,7 +114,6 @@ describe('Jasmine to Vitest Transformer', () => { afterAll(() => {}); }); `; - await expectTransformation(input, expected, true); - }); + await expectTransformation(input, expected, true); }); }); diff --git a/packages/schematics/angular/refactor/jasmine-vitest/test-file-transformer_spec.ts b/packages/schematics/angular/refactor/jasmine-vitest/test-file-transformer_spec.ts index abe1f3655cdd..d9f78c471e18 100644 --- a/packages/schematics/angular/refactor/jasmine-vitest/test-file-transformer_spec.ts +++ b/packages/schematics/angular/refactor/jasmine-vitest/test-file-transformer_spec.ts @@ -8,34 +8,33 @@ import { expectTransformation } from './test-helpers'; -describe('Jasmine to Vitest Transformer', () => { - describe('Nested Transformations', () => { - const testCases = [ - { - description: 'should handle nested transforms like a spy returning an asymmetric matcher', - input: `spyOn(service, 'getValue').and.returnValue(jasmine.any(Number));`, - expected: `vi.spyOn(service, 'getValue').mockReturnValue(expect.any(Number));`, - }, - { - description: 'should handle expectAsync resolving to an asymmetric matcher', - input: `await expectAsync(myPromise).toBeResolvedTo(jasmine.any(Number));`, - expected: `await expect(myPromise).resolves.toEqual(expect.any(Number));`, - }, - { - description: - 'should handle spying on a property that returns a promise and using expectAsync', - input: ` +describe('Jasmine to Vitest Transformer - Nested Transformations', () => { + const testCases = [ + { + description: 'should handle nested transforms like a spy returning an asymmetric matcher', + input: `spyOn(service, 'getValue').and.returnValue(jasmine.any(Number));`, + expected: `vi.spyOn(service, 'getValue').mockReturnValue(expect.any(Number));`, + }, + { + description: 'should handle expectAsync resolving to an asymmetric matcher', + input: `await expectAsync(myPromise).toBeResolvedTo(jasmine.any(Number));`, + expected: `await expect(myPromise).resolves.toEqual(expect.any(Number));`, + }, + { + description: + 'should handle spying on a property that returns a promise and using expectAsync', + input: ` spyOnProperty(service, 'myProp', 'get').and.returnValue(Promise.resolve(42)); await expectAsync(service.myProp).toBeResolvedTo(42); `, - expected: ` + expected: ` vi.spyOn(service, 'myProp', 'get').mockReturnValue(Promise.resolve(42)); await expect(service.myProp).resolves.toEqual(42); `, - }, - { - description: 'should handle a done callback that also uses timer mocks', - input: ` + }, + { + description: 'should handle a done callback that also uses timer mocks', + input: ` it('should handle timers and async', (done) => { jasmine.clock().install(); setTimeout(() => { @@ -46,7 +45,7 @@ describe('Jasmine to Vitest Transformer', () => { jasmine.clock().tick(100); }); `, - expected: ` + expected: ` it('should handle timers and async', async () => { vi.useFakeTimers(); setTimeout(() => { @@ -56,57 +55,57 @@ describe('Jasmine to Vitest Transformer', () => { vi.advanceTimersByTime(100); }); `, - }, - { - description: 'should handle toHaveBeenCalledOnceWith using an asymmetric matcher', - input: `expect(mySpy).toHaveBeenCalledOnceWith(jasmine.objectContaining({ id: 1 }));`, - expected: ` + }, + { + description: 'should handle toHaveBeenCalledOnceWith using an asymmetric matcher', + input: `expect(mySpy).toHaveBeenCalledOnceWith(jasmine.objectContaining({ id: 1 }));`, + expected: ` expect(mySpy).toHaveBeenCalledTimes(1); expect(mySpy).toHaveBeenCalledWith(expect.objectContaining({ id: 1 })); `, - }, - { - description: 'should handle withContext combined with a multi-statement matcher', - input: `expect(mySpy).withContext('custom message').toHaveBeenCalledOnceWith('foo');`, - expected: ` + }, + { + description: 'should handle withContext combined with a multi-statement matcher', + input: `expect(mySpy).withContext('custom message').toHaveBeenCalledOnceWith('foo');`, + expected: ` expect(mySpy, 'custom message').toHaveBeenCalledTimes(1); expect(mySpy, 'custom message').toHaveBeenCalledWith('foo'); `, - }, - { - description: 'should handle createSpyObj with complex return values', - input: `const spy = jasmine.createSpyObj('MyService', { getPromise: Promise.resolve(jasmine.any(String)) });`, - expected: ` + }, + { + description: 'should handle createSpyObj with complex return values', + input: `const spy = jasmine.createSpyObj('MyService', { getPromise: Promise.resolve(jasmine.any(String)) });`, + expected: ` const spy = { getPromise: vi.fn().mockName("MyService.getPromise").mockReturnValue(Promise.resolve(expect.any(String))), }; `, - }, - { - description: 'should handle arrayWithExactContents containing nested asymmetric matchers', - input: `expect(myArray).toEqual(jasmine.arrayWithExactContents([jasmine.objectContaining({ id: 1 })]));`, - /* eslint-disable max-len */ - expected: ` + }, + { + description: 'should handle arrayWithExactContents containing nested asymmetric matchers', + input: `expect(myArray).toEqual(jasmine.arrayWithExactContents([jasmine.objectContaining({ id: 1 })]));`, + /* eslint-disable max-len */ + expected: ` // TODO: vitest-migration: Verify this matches strict array content (multiset equality). Vitest's arrayContaining is a subset check. expect(myArray).toHaveLength(1); expect(myArray).toEqual(expect.arrayContaining([expect.objectContaining({ id: 1 })])); `, - /* eslint-enable max-len */ - }, - { - description: 'should handle a spy rejecting with an asymmetric matcher', - input: `spyOn(service, 'myMethod').and.rejectWith(jasmine.objectContaining({ code: 'ERROR' }));`, - expected: `vi.spyOn(service, 'myMethod').mockRejectedValue(expect.objectContaining({ code: 'ERROR' }));`, - }, - { - description: 'should handle a complex spy object with a property map and subsequent spyOn', - input: ` + /* eslint-enable max-len */ + }, + { + description: 'should handle a spy rejecting with an asymmetric matcher', + input: `spyOn(service, 'myMethod').and.rejectWith(jasmine.objectContaining({ code: 'ERROR' }));`, + expected: `vi.spyOn(service, 'myMethod').mockRejectedValue(expect.objectContaining({ code: 'ERROR' }));`, + }, + { + description: 'should handle a complex spy object with a property map and subsequent spyOn', + input: ` const myService = jasmine.createSpyObj('MyService', ['methodA'], { propA: 'valueA' }); spyOn(myService, 'methodA').and.returnValue('mocked value'); myService.methodA('test'); expect(myService.methodA).toHaveBeenCalledWith('test'); `, - expected: ` + expected: ` const myService = { methodA: vi.fn().mockName("MyService.methodA"), propA: 'valueA', @@ -115,58 +114,58 @@ describe('Jasmine to Vitest Transformer', () => { myService.methodA('test'); expect(myService.methodA).toHaveBeenCalledWith('test'); `, - }, - ]; + }, + ]; - testCases.forEach(({ description, input, expected }) => { - it(description, async () => { - await expectTransformation(input, expected); - }); + testCases.forEach(({ description, input, expected }) => { + it(description, async () => { + await expectTransformation(input, expected); }); }); +}); - describe('Comment Preservation', () => { - const testCases = [ - { - description: 'should preserve a comment before a spy', - input: ` +describe('Comment Preservation', () => { + const testCases = [ + { + description: 'should preserve a comment before a spy', + input: ` // This is an important spy spyOn(service, 'myMethod').and.returnValue(true); `, - expected: ` + expected: ` // This is an important spy vi.spyOn(service, 'myMethod').mockReturnValue(true); `, - }, - { - description: 'should preserve a multi-line comment between chained calls', - input: ` + }, + { + description: 'should preserve a multi-line comment between chained calls', + input: ` spyOn(service, 'myMethod') /* * This spy needs to return a specific value. */ .and.returnValue(true); `, - expected: ` + expected: ` vi.spyOn(service, 'myMethod') /* * This spy needs to return a specific value. */ .mockReturnValue(true); `, - }, - { - description: 'should preserve a trailing comment on a matcher line', - input: ` + }, + { + description: 'should preserve a trailing comment on a matcher line', + input: ` expect(mySpy).toHaveBeenCalledWith('foo'); // Trailing comment `, - expected: ` + expected: ` expect(mySpy).toHaveBeenCalledWith('foo'); // Trailing comment `, - }, - { - description: 'should preserve comments inside a done callback function', - input: ` + }, + { + description: 'should preserve comments inside a done callback function', + input: ` it('should do something async', (done) => { // Start the async operation setTimeout(() => { @@ -175,7 +174,7 @@ describe('Jasmine to Vitest Transformer', () => { }, 100); }); `, - expected: ` + expected: ` it('should do something async', async () => { // Start the async operation setTimeout(() => { @@ -183,26 +182,25 @@ describe('Jasmine to Vitest Transformer', () => { }, 100); }); `, - }, - { - description: 'should preserve comments around a multi-statement transformation', - input: ` + }, + { + description: 'should preserve comments around a multi-statement transformation', + input: ` // Check if the spy was called correctly expect(mySpy).toHaveBeenCalledOnceWith('foo'); `, - expected: ` + expected: ` // Check if the spy was called correctly expect(mySpy).toHaveBeenCalledTimes(1); expect(mySpy).toHaveBeenCalledWith('foo'); `, - skipped: true, - }, - ]; + skipped: true, + }, + ]; - testCases.forEach(({ description, input, expected, skipped }) => { - (skipped ? xit : it)(description, async () => { - await expectTransformation(input, expected); - }); + testCases.forEach(({ description, input, expected, skipped }) => { + (skipped ? xit : it)(description, async () => { + await expectTransformation(input, expected); }); }); }); diff --git a/packages/schematics/angular/refactor/jasmine-vitest/transformers/jasmine-lifecycle_spec.ts b/packages/schematics/angular/refactor/jasmine-vitest/transformers/jasmine-lifecycle_spec.ts index f41f5fa7ae32..611bb2330cd3 100644 --- a/packages/schematics/angular/refactor/jasmine-vitest/transformers/jasmine-lifecycle_spec.ts +++ b/packages/schematics/angular/refactor/jasmine-vitest/transformers/jasmine-lifecycle_spec.ts @@ -8,12 +8,11 @@ import { expectTransformation } from '../test-helpers'; -describe('Jasmine to Vitest Transformer', () => { - describe('transformDoneCallback', () => { - const testCases = [ - { - description: 'should transform an `it` block with a done callback to an async function', - input: ` +describe('Jasmine to Vitest Transformer - transformDoneCallback', () => { + const testCases = [ + { + description: 'should transform an `it` block with a done callback to an async function', + input: ` it('should do something async', (done) => { setTimeout(() => { expect(true).toBe(true); @@ -21,93 +20,93 @@ describe('Jasmine to Vitest Transformer', () => { }, 100); }); `, - expected: ` + expected: ` it('should do something async', async () => { setTimeout(() => { expect(true).toBe(true); }, 100); }); `, - }, - { - description: 'should transform a promise chain with a done callback to await', - input: ` + }, + { + description: 'should transform a promise chain with a done callback to await', + input: ` beforeEach((done) => { service.init().then(() => done()); }); `, - expected: ` + expected: ` beforeEach(async () => { await service.init().then(() => {}); }); `, - }, - { - description: 'should transform done.fail() to throw new Error()', - input: ` + }, + { + description: 'should transform done.fail() to throw new Error()', + input: ` it('should fail', (done) => { done.fail('it failed'); }); `, - expected: ` + expected: ` it('should fail', async () => { throw new Error('it failed'); }); `, - }, - { - description: 'should transform an `afterEach` block with a done callback', - input: 'afterEach((done) => { promise.then(done); });', - expected: 'afterEach(async () => { await promise; });', - }, - { - description: 'should transform a test with a function(done) signature', - input: ` + }, + { + description: 'should transform an `afterEach` block with a done callback', + input: 'afterEach((done) => { promise.then(done); });', + expected: 'afterEach(async () => { await promise; });', + }, + { + description: 'should transform a test with a function(done) signature', + input: ` it('should work with a function expression', function(done) { done(); }); `, - expected: ` + expected: ` it('should work with a function expression', async function() {}); `, - }, - { - description: 'should transform done.fail() without a message', - input: `it('fails', (done) => { done.fail(); });`, - expected: `it('fails', async () => { throw new Error(); });`, - }, - { - description: 'should handle promise rejections via catch', - input: ` + }, + { + description: 'should transform done.fail() without a message', + input: `it('fails', (done) => { done.fail(); });`, + expected: `it('fails', async () => { throw new Error(); });`, + }, + { + description: 'should handle promise rejections via catch', + input: ` it('should handle promise rejections via catch', (done) => { myPromise.catch(done.fail); }); `, - expected: ` + expected: ` it('should handle promise rejections via catch', async () => { await myPromise; }); `, - }, - { - description: 'should work with a custom done name', - input: ` + }, + { + description: 'should work with a custom done name', + input: ` it('should work with a custom done name', (finish) => { setTimeout(() => { finish(); }, 100); }); `, - expected: ` + expected: ` it('should work with a custom done name', async () => { setTimeout(() => { }, 100); }); `, - }, - { - description: 'should handle done in a finally block', - input: ` + }, + { + description: 'should handle done in a finally block', + input: ` it('should handle done in a finally block', (done) => { try { // some logic @@ -116,31 +115,31 @@ describe('Jasmine to Vitest Transformer', () => { } }); `, - expected: ` + expected: ` it('should handle done in a finally block', async () => { try { // some logic } finally {} }); `, - }, - { - description: 'should not transform a function with a parameter that is not a done callback', - input: ` + }, + { + description: 'should not transform a function with a parameter that is not a done callback', + input: ` it('should not transform a function with a parameter that is not a done callback', (value) => { expect(value).toBe(true); }); `, - expected: ` + expected: ` // TODO: vitest-migration: The 'done' callback was used in an unhandled way. Please migrate manually. it('should not transform a function with a parameter that is not a done callback', (value) => { expect(value).toBe(true); }); `, - }, - { - description: 'should handle a .then() call with a multi-statement body', - input: ` + }, + { + description: 'should handle a .then() call with a multi-statement body', + input: ` it('should handle a complex then', (done) => { let myValue = false; myPromise.then(() => { @@ -149,7 +148,7 @@ describe('Jasmine to Vitest Transformer', () => { }); }); `, - expected: ` + expected: ` it('should handle a complex then', async () => { let myValue = false; await myPromise.then(() => { @@ -157,97 +156,96 @@ describe('Jasmine to Vitest Transformer', () => { }); }); `, - }, - { - description: 'should add a TODO for unhandled done usage', - input: ` + }, + { + description: 'should add a TODO for unhandled done usage', + input: ` it('should do something with helper', (done) => { someHelper(done); }); `, - expected: ` + expected: ` // TODO: vitest-migration: The 'done' callback was used in an unhandled way. Please migrate manually. it('should do something with helper', (done) => { someHelper(done); }); `, - }, - ]; + }, + ]; - testCases.forEach(({ description, input, expected }) => { - it(description, async () => { - await expectTransformation(input, expected); - }); + testCases.forEach(({ description, input, expected }) => { + it(description, async () => { + await expectTransformation(input, expected); }); }); +}); - describe('transformPending', () => { - const testCases = [ - { - description: 'should transform a test with pending() to it.skip()', - input: ` +describe('transformPending', () => { + const testCases = [ + { + description: 'should transform a test with pending() to it.skip()', + input: ` it('is a work in progress', () => { pending('Not yet implemented'); }); `, - expected: ` + expected: ` it.skip('is a work in progress', () => { // TODO: vitest-migration: The pending() function was converted to a skipped test (\`it.skip\`). See: https://vitest.dev/api/vi.html#it-skip // pending('Not yet implemented'); }); `, - }, - { - description: 'should transform a test with pending() using function keyword', - input: ` + }, + { + description: 'should transform a test with pending() using function keyword', + input: ` it('is a work in progress', function() { pending('Not yet implemented'); }); `, - expected: ` + expected: ` it.skip('is a work in progress', function() { // TODO: vitest-migration: The pending() function was converted to a skipped test (\`it.skip\`). See: https://vitest.dev/api/vi.html#it-skip // pending('Not yet implemented'); }); `, - }, - ]; + }, + ]; - testCases.forEach(({ description, input, expected }) => { - it(description, async () => { - await expectTransformation(input, expected); - }); + testCases.forEach(({ description, input, expected }) => { + it(description, async () => { + await expectTransformation(input, expected); }); }); +}); - describe('transformFocusedAndSkippedTests', () => { - const testCases = [ - { - description: 'should transform fdescribe to describe.only', - input: `fdescribe('My Suite', () => {});`, - expected: `describe.only('My Suite', () => {});`, - }, - { - description: 'should transform fit to it.only', - input: `fit('My Test', () => {});`, - expected: `it.only('My Test', () => {});`, - }, - { - description: 'should transform xdescribe to describe.skip', - input: `xdescribe('My Suite', () => {});`, - expected: `describe.skip('My Suite', () => {});`, - }, - { - description: 'should transform xit to it.skip', - input: `xit('My Test', () => {});`, - expected: `it.skip('My Test', () => {});`, - }, - ]; +describe('transformFocusedAndSkippedTests', () => { + const testCases = [ + { + description: 'should transform fdescribe to describe.only', + input: `fdescribe('My Suite', () => {});`, + expected: `describe.only('My Suite', () => {});`, + }, + { + description: 'should transform fit to it.only', + input: `fit('My Test', () => {});`, + expected: `it.only('My Test', () => {});`, + }, + { + description: 'should transform xdescribe to describe.skip', + input: `xdescribe('My Suite', () => {});`, + expected: `describe.skip('My Suite', () => {});`, + }, + { + description: 'should transform xit to it.skip', + input: `xit('My Test', () => {});`, + expected: `it.skip('My Test', () => {});`, + }, + ]; - testCases.forEach(({ description, input, expected }) => { - it(description, async () => { - await expectTransformation(input, expected); - }); + testCases.forEach(({ description, input, expected }) => { + it(description, async () => { + await expectTransformation(input, expected); }); }); }); diff --git a/packages/schematics/angular/refactor/jasmine-vitest/transformers/jasmine-matcher_spec.ts b/packages/schematics/angular/refactor/jasmine-vitest/transformers/jasmine-matcher_spec.ts index a46fc63d2a01..c5e9f8d25a65 100644 --- a/packages/schematics/angular/refactor/jasmine-vitest/transformers/jasmine-matcher_spec.ts +++ b/packages/schematics/angular/refactor/jasmine-vitest/transformers/jasmine-matcher_spec.ts @@ -8,355 +8,351 @@ import { expectTransformation } from '../test-helpers'; -describe('Jasmine to Vitest Transformer', () => { - describe('transformAsymmetricMatchers', () => { - const testCases = [ - { - description: 'should transform jasmine.any(String) to expect.any(String)', - input: `expect(foo).toEqual(jasmine.any(String));`, - expected: `expect(foo).toEqual(expect.any(String));`, - }, - { - description: - 'should transform jasmine.objectContaining(...) to expect.objectContaining(...)', - input: `expect(foo).toEqual(jasmine.objectContaining({ bar: 'baz' }));`, - expected: `expect(foo).toEqual(expect.objectContaining({ bar: 'baz' }));`, - }, - { - description: 'should transform jasmine.anything() to expect.anything()', - input: `expect(foo).toEqual(jasmine.anything());`, - expected: `expect(foo).toEqual(expect.anything());`, - }, - { - description: 'should transform jasmine.stringMatching(...) to expect.stringMatching(...)', - input: `expect(foo).toEqual(jasmine.stringMatching(/some-pattern/));`, - expected: `expect(foo).toEqual(expect.stringMatching(/some-pattern/));`, - }, - { - description: 'should transform jasmine.arrayContaining(...) to expect.arrayContaining(...)', - input: `expect(foo).toEqual(jasmine.arrayContaining(['a']));`, - expected: `expect(foo).toEqual(expect.arrayContaining(['a']));`, - }, - { - description: - 'should transform jasmine.stringContaining(...) to expect.stringContaining(...)', - input: `expect(foo).toEqual(jasmine.stringContaining('substring'));`, - expected: `expect(foo).toEqual(expect.stringContaining('substring'));`, - }, - ]; +describe('Jasmine to Vitest Transformer - transformAsymmetricMatchers', () => { + const testCases = [ + { + description: 'should transform jasmine.any(String) to expect.any(String)', + input: `expect(foo).toEqual(jasmine.any(String));`, + expected: `expect(foo).toEqual(expect.any(String));`, + }, + { + description: 'should transform jasmine.objectContaining(...) to expect.objectContaining(...)', + input: `expect(foo).toEqual(jasmine.objectContaining({ bar: 'baz' }));`, + expected: `expect(foo).toEqual(expect.objectContaining({ bar: 'baz' }));`, + }, + { + description: 'should transform jasmine.anything() to expect.anything()', + input: `expect(foo).toEqual(jasmine.anything());`, + expected: `expect(foo).toEqual(expect.anything());`, + }, + { + description: 'should transform jasmine.stringMatching(...) to expect.stringMatching(...)', + input: `expect(foo).toEqual(jasmine.stringMatching(/some-pattern/));`, + expected: `expect(foo).toEqual(expect.stringMatching(/some-pattern/));`, + }, + { + description: 'should transform jasmine.arrayContaining(...) to expect.arrayContaining(...)', + input: `expect(foo).toEqual(jasmine.arrayContaining(['a']));`, + expected: `expect(foo).toEqual(expect.arrayContaining(['a']));`, + }, + { + description: 'should transform jasmine.stringContaining(...) to expect.stringContaining(...)', + input: `expect(foo).toEqual(jasmine.stringContaining('substring'));`, + expected: `expect(foo).toEqual(expect.stringContaining('substring'));`, + }, + ]; - testCases.forEach(({ description, input, expected }) => { - it(description, async () => { - await expectTransformation(input, expected); - }); + testCases.forEach(({ description, input, expected }) => { + it(description, async () => { + await expectTransformation(input, expected); }); }); +}); - describe('transformExpectAsync', () => { - const testCases = [ - { - description: 'should transform expectAsync(...).toBeResolved()', - input: `await expectAsync(myPromise).toBeResolved();`, - expected: `await expect(myPromise).resolves.not.toThrow();`, - }, - { - description: 'should transform expectAsync(...).toBeResolvedTo(value)', - input: `await expectAsync(myPromise).toBeResolvedTo(42);`, - expected: `await expect(myPromise).resolves.toEqual(42);`, - }, - { - description: 'should transform expectAsync(...).toBeRejected()', - input: `await expectAsync(myPromise).toBeRejected();`, - expected: `await expect(myPromise).rejects.toThrow();`, - }, - { - description: 'should transform expectAsync(...).toBeRejectedWith(error)', - input: `await expectAsync(myPromise).toBeRejectedWith('Error');`, - expected: `await expect(myPromise).rejects.toEqual('Error');`, - }, - { - description: 'should transform expectAsync(...).toBeRejectedWithError(ErrorClass, message)', - input: `await expectAsync(myPromise).toBeRejectedWithError(TypeError, 'Failed');`, - expected: `await expect(myPromise).rejects.toThrowError(TypeError, 'Failed');`, - }, - { - description: 'should add a TODO for an unknown expectAsync matcher', - input: `await expectAsync(myPromise).toBeSomethingElse();`, - expected: ` +describe('transformExpectAsync', () => { + const testCases = [ + { + description: 'should transform expectAsync(...).toBeResolved()', + input: `await expectAsync(myPromise).toBeResolved();`, + expected: `await expect(myPromise).resolves.not.toThrow();`, + }, + { + description: 'should transform expectAsync(...).toBeResolvedTo(value)', + input: `await expectAsync(myPromise).toBeResolvedTo(42);`, + expected: `await expect(myPromise).resolves.toEqual(42);`, + }, + { + description: 'should transform expectAsync(...).toBeRejected()', + input: `await expectAsync(myPromise).toBeRejected();`, + expected: `await expect(myPromise).rejects.toThrow();`, + }, + { + description: 'should transform expectAsync(...).toBeRejectedWith(error)', + input: `await expectAsync(myPromise).toBeRejectedWith('Error');`, + expected: `await expect(myPromise).rejects.toEqual('Error');`, + }, + { + description: 'should transform expectAsync(...).toBeRejectedWithError(ErrorClass, message)', + input: `await expectAsync(myPromise).toBeRejectedWithError(TypeError, 'Failed');`, + expected: `await expect(myPromise).rejects.toThrowError(TypeError, 'Failed');`, + }, + { + description: 'should add a TODO for an unknown expectAsync matcher', + input: `await expectAsync(myPromise).toBeSomethingElse();`, + expected: ` // TODO: vitest-migration: Unsupported expectAsync matcher ".toBeSomethingElse()" found. Please migrate this manually. await expectAsync(myPromise).toBeSomethingElse(); `, - }, - { - description: 'should add a specific TODO for toBePending', - input: `await expectAsync(myPromise).toBePending();`, - /* eslint-disable max-len */ - expected: ` + }, + { + description: 'should add a specific TODO for toBePending', + input: `await expectAsync(myPromise).toBePending();`, + /* eslint-disable max-len */ + expected: ` // TODO: vitest-migration: Unsupported matcher ".toBePending()" found. Vitest does not have a direct equivalent. Please migrate this manually, for example by using \`Promise.race\` to check if the promise settles within a short timeout. await expectAsync(myPromise).toBePending(); `, - /* eslint-enable max-len */ - }, - ]; + /* eslint-enable max-len */ + }, + ]; - testCases.forEach(({ description, input, expected }) => { - it(description, async () => { - await expectTransformation(input, expected); - }); + testCases.forEach(({ description, input, expected }) => { + it(description, async () => { + await expectTransformation(input, expected); }); }); +}); - describe('transformCalledOnceWith', () => { - const testCases = [ - { - description: 'should transform toHaveBeenCalledOnceWith(...) into two separate calls', - input: `expect(mySpy).toHaveBeenCalledOnceWith('foo', 'bar');`, - expected: ` +describe('transformCalledOnceWith', () => { + const testCases = [ + { + description: 'should transform toHaveBeenCalledOnceWith(...) into two separate calls', + input: `expect(mySpy).toHaveBeenCalledOnceWith('foo', 'bar');`, + expected: ` expect(mySpy).toHaveBeenCalledTimes(1); expect(mySpy).toHaveBeenCalledWith('foo', 'bar'); `, - }, - ]; + }, + ]; - testCases.forEach(({ description, input, expected }) => { - it(description, async () => { - await expectTransformation(input, expected); - }); + testCases.forEach(({ description, input, expected }) => { + it(description, async () => { + await expectTransformation(input, expected); }); }); +}); - describe('transformSyntacticSugarMatchers', () => { - const testCases = [ - { - description: 'should transform toBeTrue() to toBe(true)', - input: `expect(value).toBeTrue();`, - expected: `expect(value).toBe(true);`, - }, - { - description: 'should transform toBeFalse() to toBe(false)', - input: `expect(value).toBeFalse();`, - expected: `expect(value).toBe(false);`, - }, - { - description: 'should transform toBePositiveInfinity() to toBe(Infinity)', - input: `expect(value).toBePositiveInfinity();`, - expected: `expect(value).toBe(Infinity);`, - }, - { - description: 'should transform toBeNegativeInfinity() to toBe(-Infinity)', - input: `expect(value).toBeNegativeInfinity();`, - expected: `expect(value).toBe(-Infinity);`, - }, - { - description: 'should transform toHaveSize(number) to toHaveLength(number)', - input: `expect(myArray).toHaveSize(3);`, - expected: `expect(myArray).toHaveLength(3);`, - }, - { - description: 'should add a TODO for toThrowMatching', - input: `expect(() => {}).toThrowMatching((e) => e.message === 'foo');`, - expected: `// TODO: vitest-migration: Unsupported matcher ".toThrowMatching()" found. Please migrate this manually. See: https://vitest.dev/api/expect.html#tothrowerror +describe('transformSyntacticSugarMatchers', () => { + const testCases = [ + { + description: 'should transform toBeTrue() to toBe(true)', + input: `expect(value).toBeTrue();`, + expected: `expect(value).toBe(true);`, + }, + { + description: 'should transform toBeFalse() to toBe(false)', + input: `expect(value).toBeFalse();`, + expected: `expect(value).toBe(false);`, + }, + { + description: 'should transform toBePositiveInfinity() to toBe(Infinity)', + input: `expect(value).toBePositiveInfinity();`, + expected: `expect(value).toBe(Infinity);`, + }, + { + description: 'should transform toBeNegativeInfinity() to toBe(-Infinity)', + input: `expect(value).toBeNegativeInfinity();`, + expected: `expect(value).toBe(-Infinity);`, + }, + { + description: 'should transform toHaveSize(number) to toHaveLength(number)', + input: `expect(myArray).toHaveSize(3);`, + expected: `expect(myArray).toHaveLength(3);`, + }, + { + description: 'should add a TODO for toThrowMatching', + input: `expect(() => {}).toThrowMatching((e) => e.message === 'foo');`, + expected: `// TODO: vitest-migration: Unsupported matcher ".toThrowMatching()" found. Please migrate this manually. See: https://vitest.dev/api/expect.html#tothrowerror expect(() => {}).toThrowMatching((e) => e.message === 'foo');`, - }, - { - description: 'should add a TODO for toHaveSpyInteractions', - input: `expect(mySpyObj).toHaveSpyInteractions();`, - // eslint-disable-next-line max-len - expected: `// TODO: vitest-migration: Unsupported matcher ".toHaveSpyInteractions()" found. Please migrate this manually by checking the \`mock.calls.length\` of the individual spies. + }, + { + description: 'should add a TODO for toHaveSpyInteractions', + input: `expect(mySpyObj).toHaveSpyInteractions();`, + // eslint-disable-next-line max-len + expected: `// TODO: vitest-migration: Unsupported matcher ".toHaveSpyInteractions()" found. Please migrate this manually by checking the \`mock.calls.length\` of the individual spies. expect(mySpyObj).toHaveSpyInteractions();`, - }, - ]; + }, + ]; - testCases.forEach(({ description, input, expected }) => { - it(description, async () => { - await expectTransformation(input, expected); - }); + testCases.forEach(({ description, input, expected }) => { + it(description, async () => { + await expectTransformation(input, expected); }); }); +}); - describe('transformComplexMatchers', () => { - const testCases = [ - { - description: 'should transform toEqual(jasmine.truthy()) to toBeTruthy()', - input: `expect(value).toEqual(jasmine.truthy());`, - expected: `expect(value).toBeTruthy();`, - }, - { - description: 'should transform toEqual(jasmine.falsy()) to toBeFalsy()', - input: `expect(value).toEqual(jasmine.falsy());`, - expected: `expect(value).toBeFalsy();`, - }, - { - description: 'should transform toEqual(jasmine.empty()) to toHaveLength(0)', - input: `expect([]).toEqual(jasmine.empty());`, - expected: `expect([]).toHaveLength(0);`, - }, - { - description: 'should transform not.toEqual(jasmine.empty()) to not.toHaveLength(0)', - input: `expect([1]).not.toEqual(jasmine.empty());`, - expected: `expect([1]).not.toHaveLength(0);`, - }, - { - description: 'should transform toEqual(jasmine.notEmpty()) to not.toHaveLength(0)', - input: `expect([1]).toEqual(jasmine.notEmpty());`, - expected: `expect([1]).not.toHaveLength(0);`, - }, - { - description: 'should transform not.toEqual(jasmine.notEmpty()) to toHaveLength(0)', - input: `expect([]).not.toEqual(jasmine.notEmpty());`, - expected: `expect([]).toHaveLength(0);`, - }, - { - description: 'should transform toEqual(jasmine.is()) to toBe()', - input: `expect(value).toEqual(jasmine.is(otherValue));`, - expected: `expect(value).toBe(otherValue);`, - }, - ]; +describe('transformComplexMatchers', () => { + const testCases = [ + { + description: 'should transform toEqual(jasmine.truthy()) to toBeTruthy()', + input: `expect(value).toEqual(jasmine.truthy());`, + expected: `expect(value).toBeTruthy();`, + }, + { + description: 'should transform toEqual(jasmine.falsy()) to toBeFalsy()', + input: `expect(value).toEqual(jasmine.falsy());`, + expected: `expect(value).toBeFalsy();`, + }, + { + description: 'should transform toEqual(jasmine.empty()) to toHaveLength(0)', + input: `expect([]).toEqual(jasmine.empty());`, + expected: `expect([]).toHaveLength(0);`, + }, + { + description: 'should transform not.toEqual(jasmine.empty()) to not.toHaveLength(0)', + input: `expect([1]).not.toEqual(jasmine.empty());`, + expected: `expect([1]).not.toHaveLength(0);`, + }, + { + description: 'should transform toEqual(jasmine.notEmpty()) to not.toHaveLength(0)', + input: `expect([1]).toEqual(jasmine.notEmpty());`, + expected: `expect([1]).not.toHaveLength(0);`, + }, + { + description: 'should transform not.toEqual(jasmine.notEmpty()) to toHaveLength(0)', + input: `expect([]).not.toEqual(jasmine.notEmpty());`, + expected: `expect([]).toHaveLength(0);`, + }, + { + description: 'should transform toEqual(jasmine.is()) to toBe()', + input: `expect(value).toEqual(jasmine.is(otherValue));`, + expected: `expect(value).toBe(otherValue);`, + }, + ]; - testCases.forEach(({ description, input, expected }) => { - it(description, async () => { - await expectTransformation(input, expected); - }); + testCases.forEach(({ description, input, expected }) => { + it(description, async () => { + await expectTransformation(input, expected); }); }); +}); - describe('transformArrayWithExactContents', () => { - const testCases = [ - { - description: 'should transform toEqual(jasmine.arrayWithExactContents()) into two calls', - input: `expect(myArray).toEqual(jasmine.arrayWithExactContents(['a', 'b']));`, - /* eslint-disable max-len */ - expected: ` +describe('transformArrayWithExactContents', () => { + const testCases = [ + { + description: 'should transform toEqual(jasmine.arrayWithExactContents()) into two calls', + input: `expect(myArray).toEqual(jasmine.arrayWithExactContents(['a', 'b']));`, + /* eslint-disable max-len */ + expected: ` // TODO: vitest-migration: Verify this matches strict array content (multiset equality). Vitest's arrayContaining is a subset check. expect(myArray).toHaveLength(2); expect(myArray).toEqual(expect.arrayContaining(['a', 'b'])); `, - /* eslint-enable max-len */ - }, - { - description: - 'should transform toEqual(jasmine.arrayWithExactContents()) with asymmetric matchers', - input: `expect(myArray).toEqual(jasmine.arrayWithExactContents([jasmine.any(Number), 'a']));`, - /* eslint-disable max-len */ - expected: ` + /* eslint-enable max-len */ + }, + { + description: + 'should transform toEqual(jasmine.arrayWithExactContents()) with asymmetric matchers', + input: `expect(myArray).toEqual(jasmine.arrayWithExactContents([jasmine.any(Number), 'a']));`, + /* eslint-disable max-len */ + expected: ` // TODO: vitest-migration: Verify this matches strict array content (multiset equality). Vitest's arrayContaining is a subset check. expect(myArray).toHaveLength(2); expect(myArray).toEqual(expect.arrayContaining([expect.any(Number), 'a'])); `, - /* eslint-enable max-len */ - }, - { - description: - 'should add a TODO for toEqual(jasmine.arrayWithExactContents()) with a variable', - input: `expect(myArray).toEqual(jasmine.arrayWithExactContents(someOtherArray));`, - expected: ` + /* eslint-enable max-len */ + }, + { + description: + 'should add a TODO for toEqual(jasmine.arrayWithExactContents()) with a variable', + input: `expect(myArray).toEqual(jasmine.arrayWithExactContents(someOtherArray));`, + expected: ` // TODO: vitest-migration: Cannot transform jasmine.arrayWithExactContents with a dynamic variable. Please migrate this manually. expect(myArray).toEqual(jasmine.arrayWithExactContents(someOtherArray)); `, - }, - ]; + }, + ]; - testCases.forEach(({ description, input, expected }) => { - it(description, async () => { - await expectTransformation(input, expected); - }); + testCases.forEach(({ description, input, expected }) => { + it(description, async () => { + await expectTransformation(input, expected); }); }); +}); - describe('transformExpectNothing', () => { - const testCases = [ - { - description: 'should remove expect().nothing() and add a comment', - input: ` +describe('transformExpectNothing', () => { + const testCases = [ + { + description: 'should remove expect().nothing() and add a comment', + input: ` it('should be a passing test', () => { expect().nothing(); }); `, - /* eslint-disable max-len */ - expected: ` + /* eslint-disable max-len */ + expected: ` it('should be a passing test', () => { // TODO: vitest-migration: expect().nothing() has been removed because it is redundant in Vitest. Tests without assertions pass by default. // expect().nothing(); }); `, - /* eslint-enable max-len */ - }, - ]; + /* eslint-enable max-len */ + }, + ]; - testCases.forEach(({ description, input, expected }) => { - it(description, async () => { - await expectTransformation(input, expected); - }); + testCases.forEach(({ description, input, expected }) => { + it(description, async () => { + await expectTransformation(input, expected); }); }); +}); - describe('transformWithContext', () => { - const testCases = [ - { - description: 'should transform .withContext() to an expect message', - input: `expect(value).withContext('It should be true').toBe(true);`, - expected: `expect(value, 'It should be true').toBe(true);`, - }, - { - description: 'should handle chained matchers', - input: `expect(value).withContext('It should not be false').not.toBe(false);`, - expected: `expect(value, 'It should not be false').not.toBe(false);`, - }, - { - description: 'should handle .withContext() with no arguments by removing it', - input: `expect(value).withContext().toBe(true);`, - expected: `expect(value).toBe(true);`, - }, - ]; +describe('transformWithContext', () => { + const testCases = [ + { + description: 'should transform .withContext() to an expect message', + input: `expect(value).withContext('It should be true').toBe(true);`, + expected: `expect(value, 'It should be true').toBe(true);`, + }, + { + description: 'should handle chained matchers', + input: `expect(value).withContext('It should not be false').not.toBe(false);`, + expected: `expect(value, 'It should not be false').not.toBe(false);`, + }, + { + description: 'should handle .withContext() with no arguments by removing it', + input: `expect(value).withContext().toBe(true);`, + expected: `expect(value).toBe(true);`, + }, + ]; - testCases.forEach(({ description, input, expected }) => { - it(description, async () => { - await expectTransformation(input, expected); - }); + testCases.forEach(({ description, input, expected }) => { + it(description, async () => { + await expectTransformation(input, expected); }); }); +}); - describe('transformtoHaveBeenCalledBefore', () => { - const testCases = [ - { - description: 'should transform toHaveBeenCalledBefore', - input: `expect(spyA).toHaveBeenCalledBefore(spyB);`, - // eslint-disable-next-line max-len - expected: `expect(Math.min(...vi.mocked(spyA).mock.invocationCallOrder)).toBeLessThan(Math.min(...vi.mocked(spyB).mock.invocationCallOrder));`, - }, - { - description: 'should transform not.toHaveBeenCalledBefore', - input: `expect(spyA).not.toHaveBeenCalledBefore(spyB);`, - // eslint-disable-next-line max-len - expected: `expect(Math.min(...vi.mocked(spyA).mock.invocationCallOrder)).toBeGreaterThanOrEqual(Math.min(...vi.mocked(spyB).mock.invocationCallOrder));`, - }, - ]; +describe('transformtoHaveBeenCalledBefore', () => { + const testCases = [ + { + description: 'should transform toHaveBeenCalledBefore', + input: `expect(spyA).toHaveBeenCalledBefore(spyB);`, + // eslint-disable-next-line max-len + expected: `expect(Math.min(...vi.mocked(spyA).mock.invocationCallOrder)).toBeLessThan(Math.min(...vi.mocked(spyB).mock.invocationCallOrder));`, + }, + { + description: 'should transform not.toHaveBeenCalledBefore', + input: `expect(spyA).not.toHaveBeenCalledBefore(spyB);`, + // eslint-disable-next-line max-len + expected: `expect(Math.min(...vi.mocked(spyA).mock.invocationCallOrder)).toBeGreaterThanOrEqual(Math.min(...vi.mocked(spyB).mock.invocationCallOrder));`, + }, + ]; - testCases.forEach(({ description, input, expected }) => { - it(description, async () => { - await expectTransformation(input, expected); - }); + testCases.forEach(({ description, input, expected }) => { + it(description, async () => { + await expectTransformation(input, expected); }); }); +}); - describe('transformToHaveClass', () => { - const testCases = [ - { - description: 'should transform toHaveClass', - input: `expect(element).toHaveClass('my-class');`, - expected: `expect(element.classList.contains('my-class')).toBe(true);`, - }, - { - description: 'should transform not.toHaveClass', - input: `expect(element).not.toHaveClass('my-class');`, - expected: `expect(element.classList.contains('my-class')).toBe(false);`, - }, - ]; +describe('transformToHaveClass', () => { + const testCases = [ + { + description: 'should transform toHaveClass', + input: `expect(element).toHaveClass('my-class');`, + expected: `expect(element.classList.contains('my-class')).toBe(true);`, + }, + { + description: 'should transform not.toHaveClass', + input: `expect(element).not.toHaveClass('my-class');`, + expected: `expect(element.classList.contains('my-class')).toBe(false);`, + }, + ]; - testCases.forEach(({ description, input, expected }) => { - it(description, async () => { - await expectTransformation(input, expected); - }); + testCases.forEach(({ description, input, expected }) => { + it(description, async () => { + await expectTransformation(input, expected); }); }); }); diff --git a/packages/schematics/angular/refactor/jasmine-vitest/transformers/jasmine-misc_spec.ts b/packages/schematics/angular/refactor/jasmine-vitest/transformers/jasmine-misc_spec.ts index 0ce25ccacfd5..c4e76f51c9fb 100644 --- a/packages/schematics/angular/refactor/jasmine-vitest/transformers/jasmine-misc_spec.ts +++ b/packages/schematics/angular/refactor/jasmine-vitest/transformers/jasmine-misc_spec.ts @@ -8,85 +8,84 @@ import { expectTransformation } from '../test-helpers'; -describe('Jasmine to Vitest Transformer', () => { - describe('transformTimerMocks', () => { - const testCases = [ - { - description: 'should transform jasmine.clock().install() to vi.useFakeTimers()', - input: `jasmine.clock().install();`, - expected: `vi.useFakeTimers();`, - }, - { - description: 'should transform jasmine.clock().tick(100) to vi.advanceTimersByTime(100)', - input: `jasmine.clock().tick(100);`, - expected: `vi.advanceTimersByTime(100);`, - }, - { - description: 'should transform jasmine.clock().uninstall() to vi.useRealTimers()', - input: `jasmine.clock().uninstall();`, - expected: `vi.useRealTimers();`, - }, - { - description: 'should transform jasmine.clock().mockDate(date) to vi.setSystemTime(date)', - input: `jasmine.clock().mockDate(new Date('2025-01-01'));`, - expected: `vi.setSystemTime(new Date('2025-01-01'));`, - }, - { - description: 'should transform jasmine.clock().mockDate() to vi.setSystemTime(new Date())', - input: `jasmine.clock().mockDate();`, - expected: `vi.setSystemTime(new Date());`, - }, - ]; - - testCases.forEach(({ description, input, expected }) => { - it(description, async () => { - await expectTransformation(input, expected); - }); +describe('Jasmine to Vitest Transformer - transformTimerMocks', () => { + const testCases = [ + { + description: 'should transform jasmine.clock().install() to vi.useFakeTimers()', + input: `jasmine.clock().install();`, + expected: `vi.useFakeTimers();`, + }, + { + description: 'should transform jasmine.clock().tick(100) to vi.advanceTimersByTime(100)', + input: `jasmine.clock().tick(100);`, + expected: `vi.advanceTimersByTime(100);`, + }, + { + description: 'should transform jasmine.clock().uninstall() to vi.useRealTimers()', + input: `jasmine.clock().uninstall();`, + expected: `vi.useRealTimers();`, + }, + { + description: 'should transform jasmine.clock().mockDate(date) to vi.setSystemTime(date)', + input: `jasmine.clock().mockDate(new Date('2025-01-01'));`, + expected: `vi.setSystemTime(new Date('2025-01-01'));`, + }, + { + description: 'should transform jasmine.clock().mockDate() to vi.setSystemTime(new Date())', + input: `jasmine.clock().mockDate();`, + expected: `vi.setSystemTime(new Date());`, + }, + ]; + + testCases.forEach(({ description, input, expected }) => { + it(description, async () => { + await expectTransformation(input, expected); }); }); +}); - describe('transformFail', () => { - const testCases = [ - { - description: 'should transform fail() to throw new Error()', - input: `fail('This should not happen');`, - expected: `throw new Error('This should not happen');`, - }, - { - description: 'should transform fail() without a message to throw new Error()', - input: `fail();`, - expected: `throw new Error();`, - }, - ]; - - testCases.forEach(({ description, input, expected }) => { - it(description, async () => { - await expectTransformation(input, expected); - }); +describe('transformFail', () => { + const testCases = [ + { + description: 'should transform fail() to throw new Error()', + input: `fail('This should not happen');`, + expected: `throw new Error('This should not happen');`, + }, + { + description: 'should transform fail() without a message to throw new Error()', + input: `fail();`, + expected: `throw new Error();`, + }, + ]; + + testCases.forEach(({ description, input, expected }) => { + it(description, async () => { + await expectTransformation(input, expected); }); }); +}); - describe('transformDefaultTimeoutInterval', () => { - const testCases = [ - { - description: 'should transform jasmine.DEFAULT_TIMEOUT_INTERVAL', - input: `jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000;`, - expected: `vi.setConfig({ testTimeout: 10000 });`, - }, - ]; - - testCases.forEach(({ description, input, expected }) => { - it(description, async () => { - await expectTransformation(input, expected); - }); +describe('transformDefaultTimeoutInterval', () => { + const testCases = [ + { + description: 'should transform jasmine.DEFAULT_TIMEOUT_INTERVAL', + input: `jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000;`, + expected: `vi.setConfig({ testTimeout: 10000 });`, + }, + ]; + + testCases.forEach(({ description, input, expected }) => { + it(description, async () => { + await expectTransformation(input, expected); }); }); +}); - describe('transformAddMatchers', () => { - const testCases = [ - { - description: 'should add a TODO for jasmine.addMatchers', - input: ` +describe('transformAddMatchers', () => { + const testCases = [ + { + description: 'should add a TODO for jasmine.addMatchers', + input: ` jasmine.addMatchers({ toBeDivisibleByTwo: function() { return { @@ -99,7 +98,7 @@ describe('Jasmine to Vitest Transformer', () => { } }); `, - expected: ` + expected: ` // TODO: vitest-migration: jasmine.addMatchers is not supported. Please manually migrate to expect.extend(). See: https://vitest.dev/api/expect.html#expect-extend jasmine.addMatchers({ toBeDivisibleByTwo: function () { @@ -113,109 +112,108 @@ describe('Jasmine to Vitest Transformer', () => { }, }); `, - }, - ]; + }, + ]; - testCases.forEach(({ description, input, expected }) => { - it(description, async () => { - await expectTransformation(input, expected); - }); + testCases.forEach(({ description, input, expected }) => { + it(description, async () => { + await expectTransformation(input, expected); }); }); +}); - describe('transformAddCustomEqualityTester', () => { - const testCases = [ - { - description: 'should add a TODO for jasmine.addCustomEqualityTester', - input: ` +describe('transformAddCustomEqualityTester', () => { + const testCases = [ + { + description: 'should add a TODO for jasmine.addCustomEqualityTester', + input: ` jasmine.addCustomEqualityTester((a, b) => { return a.toString() === b.toString(); }); `, - expected: `// TODO: vitest-migration: jasmine.addCustomEqualityTester is not supported. Please manually migrate to expect.addEqualityTesters(). See: https://vitest.dev/api/expect.html#expect-addequalitytesters + expected: `// TODO: vitest-migration: jasmine.addCustomEqualityTester is not supported. Please manually migrate to expect.addEqualityTesters(). See: https://vitest.dev/api/expect.html#expect-addequalitytesters jasmine.addCustomEqualityTester((a, b) => { return a.toString() === b.toString(); }); `, - }, - ]; + }, + ]; - testCases.forEach(({ description, input, expected }) => { - it(description, async () => { - await expectTransformation(input, expected); - }); + testCases.forEach(({ description, input, expected }) => { + it(description, async () => { + await expectTransformation(input, expected); }); }); +}); - describe('transformUnknownJasmineProperties', () => { - const testCases = [ - { - description: 'should add a TODO for an unknown jasmine property', - input: `const env = jasmine.getEnv();`, - expected: `// TODO: vitest-migration: Unsupported jasmine property "getEnv" found. Please migrate this manually. +describe('transformUnknownJasmineProperties', () => { + const testCases = [ + { + description: 'should add a TODO for an unknown jasmine property', + input: `const env = jasmine.getEnv();`, + expected: `// TODO: vitest-migration: Unsupported jasmine property "getEnv" found. Please migrate this manually. const env = jasmine.getEnv();`, - }, - { - description: 'should not add a TODO for a known jasmine property', - input: `const spy = jasmine.createSpy();`, - expected: `const spy = vi.fn();`, - }, - ]; - - testCases.forEach(({ description, input, expected }) => { - it(description, async () => { - await expectTransformation(input, expected); - }); + }, + { + description: 'should not add a TODO for a known jasmine property', + input: `const spy = jasmine.createSpy();`, + expected: `const spy = vi.fn();`, + }, + ]; + + testCases.forEach(({ description, input, expected }) => { + it(description, async () => { + await expectTransformation(input, expected); }); }); +}); - describe('transformGlobalFunctions', () => { - const testCases = [ - { - description: 'should add a TODO for setSpecProperty', - input: `setSpecProperty('myKey', 'myValue');`, - // eslint-disable-next-line max-len - expected: `// TODO: vitest-migration: Unsupported global function \`setSpecProperty\` found. This function is used for custom reporters in Jasmine and has no direct equivalent in Vitest. +describe('transformGlobalFunctions', () => { + const testCases = [ + { + description: 'should add a TODO for setSpecProperty', + input: `setSpecProperty('myKey', 'myValue');`, + // eslint-disable-next-line max-len + expected: `// TODO: vitest-migration: Unsupported global function \`setSpecProperty\` found. This function is used for custom reporters in Jasmine and has no direct equivalent in Vitest. setSpecProperty('myKey', 'myValue');`, - }, - { - description: 'should add a TODO for setSuiteProperty', - input: `setSuiteProperty('myKey', 'myValue');`, - // eslint-disable-next-line max-len - expected: `// TODO: vitest-migration: Unsupported global function \`setSuiteProperty\` found. This function is used for custom reporters in Jasmine and has no direct equivalent in Vitest. + }, + { + description: 'should add a TODO for setSuiteProperty', + input: `setSuiteProperty('myKey', 'myValue');`, + // eslint-disable-next-line max-len + expected: `// TODO: vitest-migration: Unsupported global function \`setSuiteProperty\` found. This function is used for custom reporters in Jasmine and has no direct equivalent in Vitest. setSuiteProperty('myKey', 'myValue');`, - }, - ]; + }, + ]; - testCases.forEach(({ description, input, expected }) => { - it(description, async () => { - await expectTransformation(input, expected); - }); + testCases.forEach(({ description, input, expected }) => { + it(description, async () => { + await expectTransformation(input, expected); }); }); +}); - describe('transformUnsupportedJasmineCalls', () => { - const testCases = [ - { - description: 'should add a TODO for jasmine.mapContaining', - input: `expect(myMap).toEqual(jasmine.mapContaining(new Map()));`, - // eslint-disable-next-line max-len - expected: `// TODO: vitest-migration: jasmine.mapContaining is not supported. Vitest does not have a built-in matcher for Maps. Please manually assert the contents of the Map. +describe('transformUnsupportedJasmineCalls', () => { + const testCases = [ + { + description: 'should add a TODO for jasmine.mapContaining', + input: `expect(myMap).toEqual(jasmine.mapContaining(new Map()));`, + // eslint-disable-next-line max-len + expected: `// TODO: vitest-migration: jasmine.mapContaining is not supported. Vitest does not have a built-in matcher for Maps. Please manually assert the contents of the Map. expect(myMap).toEqual(jasmine.mapContaining(new Map()));`, - }, - { - description: 'should add a TODO for jasmine.setContaining', - input: `expect(mySet).toEqual(jasmine.setContaining(new Set()));`, - // eslint-disable-next-line max-len - expected: `// TODO: vitest-migration: jasmine.setContaining is not supported. Vitest does not have a built-in matcher for Sets. Please manually assert the contents of the Set. + }, + { + description: 'should add a TODO for jasmine.setContaining', + input: `expect(mySet).toEqual(jasmine.setContaining(new Set()));`, + // eslint-disable-next-line max-len + expected: `// TODO: vitest-migration: jasmine.setContaining is not supported. Vitest does not have a built-in matcher for Sets. Please manually assert the contents of the Set. expect(mySet).toEqual(jasmine.setContaining(new Set()));`, - }, - ]; + }, + ]; - testCases.forEach(({ description, input, expected }) => { - it(description, async () => { - await expectTransformation(input, expected); - }); + testCases.forEach(({ description, input, expected }) => { + it(description, async () => { + await expectTransformation(input, expected); }); }); }); diff --git a/packages/schematics/angular/refactor/jasmine-vitest/transformers/jasmine-spy_spec.ts b/packages/schematics/angular/refactor/jasmine-vitest/transformers/jasmine-spy_spec.ts index 6c11f776bd3b..44113c3938c2 100644 --- a/packages/schematics/angular/refactor/jasmine-vitest/transformers/jasmine-spy_spec.ts +++ b/packages/schematics/angular/refactor/jasmine-vitest/transformers/jasmine-spy_spec.ts @@ -8,274 +8,272 @@ import { expectTransformation } from '../test-helpers'; -describe('Jasmine to Vitest Transformer', () => { - describe('transformSpies', () => { - const testCases = [ - { - description: 'should transform spyOn(object, "method") to vi.spyOn(object, "method")', - input: `spyOn(service, 'myMethod');`, - expected: `vi.spyOn(service, 'myMethod');`, - }, - { - description: 'should transform .and.returnValue(...) to .mockReturnValue(...)', - input: `spyOn(service, 'myMethod').and.returnValue(42);`, - expected: `vi.spyOn(service, 'myMethod').mockReturnValue(42);`, - }, - { - description: 'should transform .and.returnValues() to chained .mockReturnValueOnce() calls', - input: `spyOn(service, 'myMethod').and.returnValues('a', 'b', 'c');`, - expected: `vi.spyOn(service, 'myMethod').mockReturnValueOnce('a').mockReturnValueOnce('b').mockReturnValueOnce('c');`, - }, - { - description: 'should transform .and.callFake(...) to .mockImplementation(...)', - input: `spyOn(service, 'myMethod').and.callFake(() => 'fake');`, - expected: `vi.spyOn(service, 'myMethod').mockImplementation(() => 'fake');`, - }, - { - description: 'should remove .and.callThrough()', - input: `spyOn(service, 'myMethod').and.callThrough();`, - expected: `vi.spyOn(service, 'myMethod');`, - }, - { - description: 'should transform jasmine.createSpy("name") to vi.fn()', - input: `const mySpy = jasmine.createSpy('mySpy');`, - expected: `const mySpy = vi.fn();`, - }, - { - description: 'should transform jasmine.createSpy("name", fn) to vi.fn(fn)', - input: `const mySpy = jasmine.createSpy('mySpy', () => 'foo');`, - expected: `const mySpy = vi.fn(() => 'foo');`, - }, - { - description: 'should transform spyOnProperty(object, "prop") to vi.spyOn(object, "prop")', - input: `spyOnProperty(service, 'myProp');`, - expected: `vi.spyOn(service, 'myProp');`, - }, - { - description: 'should transform .and.stub() to .mockImplementation(() => {})', - input: `spyOn(service, 'myMethod').and.stub();`, - expected: `vi.spyOn(service, 'myMethod').mockImplementation(() => {});`, - }, - { - description: 'should add a TODO for jasmine.spyOnAllFunctions(object)', - input: `jasmine.spyOnAllFunctions(myObject);`, - expected: `// TODO: vitest-migration: Vitest does not have a direct equivalent for jasmine.spyOnAllFunctions(). Please spy on individual methods manually using vi.spyOn(). See: https://vitest.dev/api/vi.html#vi-spyon +describe('Jasmine to Vitest Transformer - transformSpies', () => { + const testCases = [ + { + description: 'should transform spyOn(object, "method") to vi.spyOn(object, "method")', + input: `spyOn(service, 'myMethod');`, + expected: `vi.spyOn(service, 'myMethod');`, + }, + { + description: 'should transform .and.returnValue(...) to .mockReturnValue(...)', + input: `spyOn(service, 'myMethod').and.returnValue(42);`, + expected: `vi.spyOn(service, 'myMethod').mockReturnValue(42);`, + }, + { + description: 'should transform .and.returnValues() to chained .mockReturnValueOnce() calls', + input: `spyOn(service, 'myMethod').and.returnValues('a', 'b', 'c');`, + expected: `vi.spyOn(service, 'myMethod').mockReturnValueOnce('a').mockReturnValueOnce('b').mockReturnValueOnce('c');`, + }, + { + description: 'should transform .and.callFake(...) to .mockImplementation(...)', + input: `spyOn(service, 'myMethod').and.callFake(() => 'fake');`, + expected: `vi.spyOn(service, 'myMethod').mockImplementation(() => 'fake');`, + }, + { + description: 'should remove .and.callThrough()', + input: `spyOn(service, 'myMethod').and.callThrough();`, + expected: `vi.spyOn(service, 'myMethod');`, + }, + { + description: 'should transform jasmine.createSpy("name") to vi.fn()', + input: `const mySpy = jasmine.createSpy('mySpy');`, + expected: `const mySpy = vi.fn();`, + }, + { + description: 'should transform jasmine.createSpy("name", fn) to vi.fn(fn)', + input: `const mySpy = jasmine.createSpy('mySpy', () => 'foo');`, + expected: `const mySpy = vi.fn(() => 'foo');`, + }, + { + description: 'should transform spyOnProperty(object, "prop") to vi.spyOn(object, "prop")', + input: `spyOnProperty(service, 'myProp');`, + expected: `vi.spyOn(service, 'myProp');`, + }, + { + description: 'should transform .and.stub() to .mockImplementation(() => {})', + input: `spyOn(service, 'myMethod').and.stub();`, + expected: `vi.spyOn(service, 'myMethod').mockImplementation(() => {});`, + }, + { + description: 'should add a TODO for jasmine.spyOnAllFunctions(object)', + input: `jasmine.spyOnAllFunctions(myObject);`, + expected: `// TODO: vitest-migration: Vitest does not have a direct equivalent for jasmine.spyOnAllFunctions(). Please spy on individual methods manually using vi.spyOn(). See: https://vitest.dev/api/vi.html#vi-spyon jasmine.spyOnAllFunctions(myObject); `, - }, - { - description: 'should handle chained calls on jasmine.createSpy()', - input: `const mySpy = jasmine.createSpy('mySpy').and.returnValue(true);`, - expected: `const mySpy = vi.fn().mockReturnValue(true);`, - }, - { - description: 'should handle .and.returnValues() with no arguments', - input: `spyOn(service, 'myMethod').and.returnValues();`, - expected: `vi.spyOn(service, 'myMethod');`, - }, - { - description: - 'should transform .and.throwError("message") to .mockImplementation(() => { throw new Error("message") })', - input: `spyOn(service, 'myMethod').and.throwError('Something went wrong');`, - expected: `vi.spyOn(service, 'myMethod').mockImplementation(() => { throw new Error('Something went wrong') });`, - }, - { - description: - 'should transform .and.throwError(new Error("message")) to .mockImplementation(() => { throw new Error("message") })', - input: `spyOn(service, 'myMethod').and.throwError(new Error('Custom Error'));`, - expected: `vi.spyOn(service, 'myMethod').mockImplementation(() => { throw new Error('Custom Error') });`, - }, - { - description: 'should transform .and.resolveTo(value) to .mockResolvedValue(value)', - input: `spyOn(service, 'myMethod').and.resolveTo('some value');`, - expected: `vi.spyOn(service, 'myMethod').mockResolvedValue('some value');`, - }, - { - description: 'should transform .and.rejectWith(error) to .mockRejectedValue(error)', - input: `spyOn(service, 'myMethod').and.rejectWith('some error');`, - expected: `vi.spyOn(service, 'myMethod').mockRejectedValue('some error');`, - }, - { - description: 'should add a TODO for an unsupported spy strategy', - input: `spyOn(service, 'myMethod').and.unknownStrategy();`, - expected: `// TODO: vitest-migration: Unsupported spy strategy ".and.unknownStrategy()" found. Please migrate this manually. See: https://vitest.dev/api/mocked.html#mock + }, + { + description: 'should handle chained calls on jasmine.createSpy()', + input: `const mySpy = jasmine.createSpy('mySpy').and.returnValue(true);`, + expected: `const mySpy = vi.fn().mockReturnValue(true);`, + }, + { + description: 'should handle .and.returnValues() with no arguments', + input: `spyOn(service, 'myMethod').and.returnValues();`, + expected: `vi.spyOn(service, 'myMethod');`, + }, + { + description: + 'should transform .and.throwError("message") to .mockImplementation(() => { throw new Error("message") })', + input: `spyOn(service, 'myMethod').and.throwError('Something went wrong');`, + expected: `vi.spyOn(service, 'myMethod').mockImplementation(() => { throw new Error('Something went wrong') });`, + }, + { + description: + 'should transform .and.throwError(new Error("message")) to .mockImplementation(() => { throw new Error("message") })', + input: `spyOn(service, 'myMethod').and.throwError(new Error('Custom Error'));`, + expected: `vi.spyOn(service, 'myMethod').mockImplementation(() => { throw new Error('Custom Error') });`, + }, + { + description: 'should transform .and.resolveTo(value) to .mockResolvedValue(value)', + input: `spyOn(service, 'myMethod').and.resolveTo('some value');`, + expected: `vi.spyOn(service, 'myMethod').mockResolvedValue('some value');`, + }, + { + description: 'should transform .and.rejectWith(error) to .mockRejectedValue(error)', + input: `spyOn(service, 'myMethod').and.rejectWith('some error');`, + expected: `vi.spyOn(service, 'myMethod').mockRejectedValue('some error');`, + }, + { + description: 'should add a TODO for an unsupported spy strategy', + input: `spyOn(service, 'myMethod').and.unknownStrategy();`, + expected: `// TODO: vitest-migration: Unsupported spy strategy ".and.unknownStrategy()" found. Please migrate this manually. See: https://vitest.dev/api/mocked.html#mock vi.spyOn(service, 'myMethod').and.unknownStrategy();`, - }, - ]; + }, + ]; - testCases.forEach(({ description, input, expected }) => { - it(description, async () => { - await expectTransformation(input, expected); - }); + testCases.forEach(({ description, input, expected }) => { + it(description, async () => { + await expectTransformation(input, expected); }); }); +}); - describe('transformCreateSpyObj', () => { - const testCases = [ - { - description: 'should transform jasmine.createSpyObj with an array of methods', - input: `const myService = jasmine.createSpyObj('MyService', ['methodA', 'methodB']);`, - expected: `const myService = { +describe('transformCreateSpyObj', () => { + const testCases = [ + { + description: 'should transform jasmine.createSpyObj with an array of methods', + input: `const myService = jasmine.createSpyObj('MyService', ['methodA', 'methodB']);`, + expected: `const myService = { methodA: vi.fn().mockName("MyService.methodA"), methodB: vi.fn().mockName("MyService.methodB"), };`, - }, - { - description: - 'should transform jasmine.createSpyObj with an array of methods without base name', - input: `const myService = jasmine.createSpyObj(['methodA', 'methodB']);`, - expected: `const myService = { + }, + { + description: + 'should transform jasmine.createSpyObj with an array of methods without base name', + input: `const myService = jasmine.createSpyObj(['methodA', 'methodB']);`, + expected: `const myService = { methodA: vi.fn(), methodB: vi.fn(), };`, - }, - { - description: 'should add a TODO if the second argument is not a literal', - input: `const myService = jasmine.createSpyObj('MyService', methodNames);`, - expected: ` + }, + { + description: 'should add a TODO if the second argument is not a literal', + input: `const myService = jasmine.createSpyObj('MyService', methodNames);`, + expected: ` // TODO: vitest-migration: Cannot transform jasmine.createSpyObj with a dynamic variable. Please migrate this manually. See: https://vitest.dev/api/vi.html#vi-fn const myService = jasmine.createSpyObj('MyService', methodNames); `, - }, - { - description: 'should transform jasmine.createSpyObj with an object of return values', - input: `const myService = jasmine.createSpyObj('MyService', { methodA: 'foo', methodB: 42 });`, - expected: `const myService = { + }, + { + description: 'should transform jasmine.createSpyObj with an object of return values', + input: `const myService = jasmine.createSpyObj('MyService', { methodA: 'foo', methodB: 42 });`, + expected: `const myService = { methodA: vi.fn().mockName("MyService.methodA").mockReturnValue('foo'), methodB: vi.fn().mockName("MyService.methodB").mockReturnValue(42), };`, - }, - { - description: - 'should transform jasmine.createSpyObj with an object of return values without base name', - input: `const myService = jasmine.createSpyObj({ methodA: 'foo', methodB: 42 });`, - expected: `const myService = { + }, + { + description: + 'should transform jasmine.createSpyObj with an object of return values without base name', + input: `const myService = jasmine.createSpyObj({ methodA: 'foo', methodB: 42 });`, + expected: `const myService = { methodA: vi.fn().mockReturnValue('foo'), methodB: vi.fn().mockReturnValue(42), };`, - }, - { - description: - 'should transform jasmine.createSpyObj with an object of return values containing an asymmetric matcher', - input: `const myService = jasmine.createSpyObj('MyService', { methodA: jasmine.any(String) });`, - expected: `const myService = { + }, + { + description: + 'should transform jasmine.createSpyObj with an object of return values containing an asymmetric matcher', + input: `const myService = jasmine.createSpyObj('MyService', { methodA: jasmine.any(String) });`, + expected: `const myService = { methodA: vi.fn().mockName("MyService.methodA").mockReturnValue(expect.any(String)), };`, - }, - { - description: 'should add a TODO for jasmine.createSpyObj with only base name argument', - input: `const myService = jasmine.createSpyObj('MyService');`, - expected: ` + }, + { + description: 'should add a TODO for jasmine.createSpyObj with only base name argument', + input: `const myService = jasmine.createSpyObj('MyService');`, + expected: ` // TODO: vitest-migration: jasmine.createSpyObj called with a single argument is not supported for transformation. See: https://vitest.dev/api/vi.html#vi-fn const myService = jasmine.createSpyObj('MyService'); `, - }, - { - description: 'should transform jasmine.createSpyObj with a property map', - input: `const myService = jasmine.createSpyObj('MyService', ['methodA'], { propA: 'valueA' });`, - expected: `const myService = { + }, + { + description: 'should transform jasmine.createSpyObj with a property map', + input: `const myService = jasmine.createSpyObj('MyService', ['methodA'], { propA: 'valueA' });`, + expected: `const myService = { methodA: vi.fn().mockName("MyService.methodA"), propA: 'valueA', };`, - }, - { - description: 'should transform jasmine.createSpyObj with a method map and a property map', - input: `const myService = jasmine.createSpyObj('MyService', { methodA: 'foo' }, { propA: 'valueA' });`, - expected: `const myService = { + }, + { + description: 'should transform jasmine.createSpyObj with a method map and a property map', + input: `const myService = jasmine.createSpyObj('MyService', { methodA: 'foo' }, { propA: 'valueA' });`, + expected: `const myService = { methodA: vi.fn().mockName("MyService.methodA").mockReturnValue('foo'), propA: 'valueA', };`, - }, - { - description: - 'should transform jasmine.createSpyObj with a method map and a property map without base name', - input: `const myService = jasmine.createSpyObj({ methodA: 'foo' }, { propA: 'valueA' });`, - expected: `const myService = { + }, + { + description: + 'should transform jasmine.createSpyObj with a method map and a property map without base name', + input: `const myService = jasmine.createSpyObj({ methodA: 'foo' }, { propA: 'valueA' });`, + expected: `const myService = { methodA: vi.fn().mockReturnValue('foo'), propA: 'valueA', };`, - }, - { - description: 'should ignore non-string literals in the method array', - input: `const myService = jasmine.createSpyObj('MyService', ['methodA', 123, someVar]);`, - expected: `const myService = { + }, + { + description: 'should ignore non-string literals in the method array', + input: `const myService = jasmine.createSpyObj('MyService', ['methodA', 123, someVar]);`, + expected: `const myService = { methodA: vi.fn().mockName("MyService.methodA"), };`, - }, - ]; + }, + ]; - testCases.forEach(({ description, input, expected }) => { - it(description, async () => { - await expectTransformation(input, expected); - }); + testCases.forEach(({ description, input, expected }) => { + it(description, async () => { + await expectTransformation(input, expected); }); }); +}); - describe('transformSpyReset', () => { - const testCases = [ - { - description: 'should transform spy.calls.reset() to spy.mockClear()', - input: `mySpy.calls.reset();`, - expected: `mySpy.mockClear();`, - }, - ]; +describe('transformSpyReset', () => { + const testCases = [ + { + description: 'should transform spy.calls.reset() to spy.mockClear()', + input: `mySpy.calls.reset();`, + expected: `mySpy.mockClear();`, + }, + ]; - testCases.forEach(({ description, input, expected }) => { - it(description, async () => { - await expectTransformation(input, expected); - }); + testCases.forEach(({ description, input, expected }) => { + it(description, async () => { + await expectTransformation(input, expected); }); }); +}); - describe('transformSpyCallInspection', () => { - const testCases = [ - { - description: 'should transform spy.calls.any()', - input: `expect(mySpy.calls.any()).toBe(true);`, - expected: `expect(vi.mocked(mySpy).mock.calls.length > 0).toBe(true);`, - }, - { - description: 'should transform spy.calls.count()', - input: `expect(mySpy.calls.count()).toBe(1);`, - expected: `expect(vi.mocked(mySpy).mock.calls.length).toBe(1);`, - }, - { - description: 'should transform spy.calls.argsFor(0)', - input: `const args = mySpy.calls.argsFor(0);`, - expected: `const args = vi.mocked(mySpy).mock.calls[0];`, - }, - { - description: 'should transform spy.calls.allArgs()', - input: `const allArgs = mySpy.calls.allArgs();`, - expected: `const allArgs = vi.mocked(mySpy).mock.calls;`, - }, - { - description: 'should transform spy.calls.all()', - input: `const allCalls = mySpy.calls.all();`, - expected: `const allCalls = vi.mocked(mySpy).mock.calls;`, - }, - { - description: 'should transform spy.calls.mostRecent().args', - input: `const recentArgs = mySpy.calls.mostRecent().args;`, - expected: `const recentArgs = vi.mocked(mySpy).mock.lastCall;`, - }, - { - description: 'should transform spy.calls.first()', - input: `const firstCall = mySpy.calls.first();`, - expected: `const firstCall = vi.mocked(mySpy).mock.calls[0];`, - }, - { - description: 'should add a TODO for spy.calls.mostRecent() without .args', - input: `const mostRecent = mySpy.calls.mostRecent();`, - expected: `// TODO: vitest-migration: Direct usage of mostRecent() is not supported. Please refactor to access .args directly or use vi.mocked(spy).mock.lastCall. See: https://vitest.dev/api/mocked.html#mock-lastcall +describe('transformSpyCallInspection', () => { + const testCases = [ + { + description: 'should transform spy.calls.any()', + input: `expect(mySpy.calls.any()).toBe(true);`, + expected: `expect(vi.mocked(mySpy).mock.calls.length > 0).toBe(true);`, + }, + { + description: 'should transform spy.calls.count()', + input: `expect(mySpy.calls.count()).toBe(1);`, + expected: `expect(vi.mocked(mySpy).mock.calls.length).toBe(1);`, + }, + { + description: 'should transform spy.calls.argsFor(0)', + input: `const args = mySpy.calls.argsFor(0);`, + expected: `const args = vi.mocked(mySpy).mock.calls[0];`, + }, + { + description: 'should transform spy.calls.allArgs()', + input: `const allArgs = mySpy.calls.allArgs();`, + expected: `const allArgs = vi.mocked(mySpy).mock.calls;`, + }, + { + description: 'should transform spy.calls.all()', + input: `const allCalls = mySpy.calls.all();`, + expected: `const allCalls = vi.mocked(mySpy).mock.calls;`, + }, + { + description: 'should transform spy.calls.mostRecent().args', + input: `const recentArgs = mySpy.calls.mostRecent().args;`, + expected: `const recentArgs = vi.mocked(mySpy).mock.lastCall;`, + }, + { + description: 'should transform spy.calls.first()', + input: `const firstCall = mySpy.calls.first();`, + expected: `const firstCall = vi.mocked(mySpy).mock.calls[0];`, + }, + { + description: 'should add a TODO for spy.calls.mostRecent() without .args', + input: `const mostRecent = mySpy.calls.mostRecent();`, + expected: `// TODO: vitest-migration: Direct usage of mostRecent() is not supported. Please refactor to access .args directly or use vi.mocked(spy).mock.lastCall. See: https://vitest.dev/api/mocked.html#mock-lastcall const mostRecent = mySpy.calls.mostRecent();`, - }, - ]; + }, + ]; - testCases.forEach(({ description, input, expected }) => { - it(description, async () => { - await expectTransformation(input, expected); - }); + testCases.forEach(({ description, input, expected }) => { + it(description, async () => { + await expectTransformation(input, expected); }); }); }); diff --git a/packages/schematics/angular/refactor/jasmine-vitest/transformers/jasmine-type_spec.ts b/packages/schematics/angular/refactor/jasmine-vitest/transformers/jasmine-type_spec.ts index d38891730f99..d43bd5b8e157 100644 --- a/packages/schematics/angular/refactor/jasmine-vitest/transformers/jasmine-type_spec.ts +++ b/packages/schematics/angular/refactor/jasmine-vitest/transformers/jasmine-type_spec.ts @@ -8,69 +8,67 @@ import { expectTransformation } from '../test-helpers'; -describe('Jasmine to Vitest Transformer', () => { - describe('transformJasmineTypes', () => { - const testCases = [ - { - description: 'should transform a variable with a jasmine.Spy type', - input: `let mySpy: jasmine.Spy;`, - expected: ` +describe('Jasmine to Vitest Transformer - transformJasmineTypes', () => { + const testCases = [ + { + description: 'should transform a variable with a jasmine.Spy type', + input: `let mySpy: jasmine.Spy;`, + expected: ` import type { Mock } from 'vitest'; let mySpy: Mock; `, - }, - { - description: 'should transform a variable with a jasmine.SpyObj type', - input: `let mySpy: jasmine.SpyObj;`, - expected: ` + }, + { + description: 'should transform a variable with a jasmine.SpyObj type', + input: `let mySpy: jasmine.SpyObj;`, + expected: ` import type { MockedObject } from 'vitest'; let mySpy: MockedObject; `, - }, - { - description: 'should handle multiple jasmine types and create a single import', - input: ` + }, + { + description: 'should handle multiple jasmine types and create a single import', + input: ` let mySpy: jasmine.Spy; let mySpyObj: jasmine.SpyObj; `, - expected: ` + expected: ` import type { Mock, MockedObject } from 'vitest'; let mySpy: Mock; let mySpyObj: MockedObject; `, - }, - { - description: 'should not add an import if no jasmine types are used', - input: `let mySpy: any;`, - expected: `let mySpy: any;`, - }, - { - description: 'should transform jasmine.Any to any', - input: `let myMatcher: jasmine.Any;`, - expected: `let myMatcher: any;`, - }, - { - description: 'should transform jasmine.ObjectContaining to Partial', - input: `let myMatcher: jasmine.ObjectContaining;`, - expected: `let myMatcher: Partial;`, - }, - { - description: 'should transform jasmine.ObjectContaining to object', - input: `let myMatcher: jasmine.ObjectContaining;`, - expected: `let myMatcher: object;`, - }, - { - description: 'should transform jasmine.DoneFn to () => void', - input: `let myDoneFn: jasmine.DoneFn;`, - expected: `let myDoneFn: () => void;`, - }, - ]; + }, + { + description: 'should not add an import if no jasmine types are used', + input: `let mySpy: any;`, + expected: `let mySpy: any;`, + }, + { + description: 'should transform jasmine.Any to any', + input: `let myMatcher: jasmine.Any;`, + expected: `let myMatcher: any;`, + }, + { + description: 'should transform jasmine.ObjectContaining to Partial', + input: `let myMatcher: jasmine.ObjectContaining;`, + expected: `let myMatcher: Partial;`, + }, + { + description: 'should transform jasmine.ObjectContaining to object', + input: `let myMatcher: jasmine.ObjectContaining;`, + expected: `let myMatcher: object;`, + }, + { + description: 'should transform jasmine.DoneFn to () => void', + input: `let myDoneFn: jasmine.DoneFn;`, + expected: `let myDoneFn: () => void;`, + }, + ]; - testCases.forEach(({ description, input, expected }) => { - it(description, async () => { - await expectTransformation(input, expected); - }); + testCases.forEach(({ description, input, expected }) => { + it(description, async () => { + await expectTransformation(input, expected); }); }); }); diff --git a/packages/schematics/angular/utility/dependencies_spec.ts b/packages/schematics/angular/utility/dependencies_spec.ts index d2d7b69e2c45..01a0278828fc 100644 --- a/packages/schematics/angular/utility/dependencies_spec.ts +++ b/packages/schematics/angular/utility/dependencies_spec.ts @@ -19,16 +19,10 @@ describe('dependencies', () => { describe('addDependency', () => { let tree: UnitTestTree; const pkgJsonPath = '/package.json'; - let dependency: NodeDependency; + beforeEach(() => { tree = new UnitTestTree(new EmptyTree()); tree.create(pkgJsonPath, '{}'); - - dependency = { - type: NodeDependencyType.Default, - name: 'my-pkg', - version: '1.2.3', - }; }); [ @@ -36,29 +30,39 @@ describe('dependencies', () => { { type: NodeDependencyType.Dev, key: 'devDependencies' }, { type: NodeDependencyType.Optional, key: 'optionalDependencies' }, { type: NodeDependencyType.Peer, key: 'peerDependencies' }, - ].forEach((type) => { - describe(`Type: ${type.toString()}`, () => { - beforeEach(() => { - dependency.type = type.type; - }); + ].forEach(({ type, key }) => { + describe(`Type: ${type}`, () => { + const dependency: NodeDependency = { + type, + name: 'my-pkg', + version: '1.2.3', + }; it('should add a dependency', () => { addPackageJsonDependency(tree, dependency); const pkgJson = JSON.parse(tree.readContent(pkgJsonPath)); - expect(pkgJson[type.key][dependency.name]).toEqual(dependency.version); + + expect(pkgJson[key][dependency.name]).toEqual(dependency.version); }); it('should handle an existing dependency (update version)', () => { addPackageJsonDependency(tree, { ...dependency, version: '0.0.0' }); addPackageJsonDependency(tree, { ...dependency, overwrite: true }); const pkgJson = JSON.parse(tree.readContent(pkgJsonPath)); - expect(pkgJson[type.key][dependency.name]).toEqual(dependency.version); + + expect(pkgJson[key][dependency.name]).toEqual(dependency.version); }); }); }); it('should throw when missing package.json', () => { - expect(() => addPackageJsonDependency(new EmptyTree(), dependency)).toThrow(); + expect(() => + addPackageJsonDependency(new EmptyTree(), { + type: NodeDependencyType.Default, + name: 'my-pkg', + version: '1.2.3', + }), + ).toThrow(); }); }); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index cdedec51bfbf..b320f1708085 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -116,8 +116,8 @@ importers: specifier: ^4.0.0 version: 4.1.1 '@types/jasmine': - specifier: ~5.1.0 - version: 5.1.15 + specifier: ~6.0.0 + version: 6.0.0 '@types/jasmine-reporters': specifier: ^2 version: 2.5.3 @@ -209,11 +209,11 @@ importers: specifier: 9.1.7 version: 9.1.7 jasmine: - specifier: ~5.13.0 - version: 5.13.0 + specifier: ~6.1.0 + version: 6.1.0 jasmine-core: - specifier: ~5.13.0 - version: 5.13.0 + specifier: ~6.1.0 + version: 6.1.0 jasmine-reporters: specifier: ^2.5.2 version: 2.5.2 @@ -234,7 +234,7 @@ importers: version: 5.1.0(karma@6.4.4(bufferutil@4.1.0)) karma-jasmine-html-reporter: specifier: ~2.2.0 - version: 2.2.0(jasmine-core@5.13.0)(karma-jasmine@5.1.0(karma@6.4.4(bufferutil@4.1.0)))(karma@6.4.4(bufferutil@4.1.0)) + version: 2.2.0(jasmine-core@6.1.0)(karma-jasmine@5.1.0(karma@6.4.4(bufferutil@4.1.0)))(karma@6.4.4(bufferutil@4.1.0)) karma-source-map-support: specifier: 1.4.0 version: 1.4.0 @@ -3526,9 +3526,6 @@ packages: '@types/jasmine-reporters@2.5.3': resolution: {integrity: sha512-8aojAUdgdiD9VQbllBJb/9gny3lOjz9T5gyMcbYlKe6npwGVsarbr8v2JYSFJSZSuFYXcPVzFG2lLX3ib0j/DA==} - '@types/jasmine@5.1.15': - resolution: {integrity: sha512-ZAC8KjmV2MJxbNTrwXFN+HKeajpXQZp6KpPiR6Aa4XvaEnjP6qh23lL/Rqb7AYzlp3h/rcwDrQ7Gg7q28cQTQg==} - '@types/jasmine@6.0.0': resolution: {integrity: sha512-18lgGsLmEh3VJk9eZ5wAjTISxdqzl6YOwu8UdMpolajN57QOCNbl+AbHUd+Yu9ItrsFdB+c8LSZSGNg8nHaguw==} @@ -6400,9 +6397,6 @@ packages: jasmine-core@4.6.1: resolution: {integrity: sha512-VYz/BjjmC3klLJlLwA4Kw8ytk0zDSmbbDLNs794VnWmkcCB7I9aAL/D48VNQtmITyPvea2C3jdUMfc3kAoy0PQ==} - jasmine-core@5.13.0: - resolution: {integrity: sha512-vsYjfh7lyqvZX5QgqKc4YH8phs7g96Z8bsdIFNEU3VqXhlHaq+vov/Fgn/sr6MiUczdZkyXRC3TX369Ll4Nzbw==} - jasmine-core@6.1.0: resolution: {integrity: sha512-p/tjBw58O6vxKIWMlrU+yys8lqR3+l3UrqwNTT7wpj+dQ7N4etQekFM8joI+cWzPDYqZf54kN+hLC1+s5TvZvg==} @@ -6416,10 +6410,6 @@ packages: resolution: {integrity: sha512-KbdGQTf5jbZgltoHs31XGiChAPumMSY64OZMWLNYnEnMfG5uwGBhffePwuskexjT+/Jea/gU3qAU8344hNohSw==} hasBin: true - jasmine@5.13.0: - resolution: {integrity: sha512-oLCXIhEb5e0zzjn9GyuvcuisvLBwUjmgz7a0RNGWKwQtJCDld4m+vwKUpAIJVLB5vbmQFdtKhT86/tIZlJ5gYw==} - hasBin: true - jasmine@6.1.0: resolution: {integrity: sha512-WPphPqEMY0uBRMjuhRHoVoxQNvJuxIMqz0yIcJ3k3oYxBedeGoH60/NXNgasxnx2FvfXrq5/r+2wssJ7WE8ABw==} hasBin: true @@ -11989,7 +11979,7 @@ snapshots: '@tufjs/models@4.1.0': dependencies: '@tufjs/canonical-json': 2.0.0 - minimatch: 10.2.0 + minimatch: 10.2.2 '@tybys/wasm-util@0.10.1': dependencies: @@ -12166,9 +12156,7 @@ snapshots: '@types/jasmine-reporters@2.5.3': dependencies: - '@types/jasmine': 5.1.15 - - '@types/jasmine@5.1.15': {} + '@types/jasmine': 6.0.0 '@types/jasmine@6.0.0': {} @@ -15015,7 +15003,7 @@ snapshots: glob@13.0.3: dependencies: - minimatch: 10.2.0 + minimatch: 10.2.2 minipass: 7.1.2 path-scurry: 2.0.1 @@ -15705,8 +15693,6 @@ snapshots: jasmine-core@4.6.1: {} - jasmine-core@5.13.0: {} - jasmine-core@6.1.0: {} jasmine-reporters@2.5.2: @@ -15724,11 +15710,6 @@ snapshots: glob: 7.2.3 jasmine-core: 2.8.0 - jasmine@5.13.0: - dependencies: - glob: 10.5.0 - jasmine-core: 5.13.0 - jasmine@6.1.0: dependencies: '@jasminejs/reporters': 1.0.0 @@ -15888,9 +15869,9 @@ snapshots: transitivePeerDependencies: - supports-color - karma-jasmine-html-reporter@2.2.0(jasmine-core@5.13.0)(karma-jasmine@5.1.0(karma@6.4.4(bufferutil@4.1.0)))(karma@6.4.4(bufferutil@4.1.0)): + karma-jasmine-html-reporter@2.2.0(jasmine-core@6.1.0)(karma-jasmine@5.1.0(karma@6.4.4(bufferutil@4.1.0)))(karma@6.4.4(bufferutil@4.1.0)): dependencies: - jasmine-core: 5.13.0 + jasmine-core: 6.1.0 karma: 6.4.4(bufferutil@4.1.0) karma-jasmine: 5.1.0(karma@6.4.4(bufferutil@4.1.0))