/
githubmirror
/
angular-cli
Обзор
Документация
Войти
/
githubmirror
/
angular-cli
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
packages/schematics/angular/refactor/jasmine-vitest/utils/todo-notes.ts
217 строк
9 KB
Younes Jaaidi
feat(@schematics/angular): migrate fake async to Vitest fake timers
04 май 2026, 20:23
04 май 2026, 20:23
d227e69
Код
Авторство
О чём код?
/** * @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 */ /** * @fileoverview This file is the single source of truth for all "TODO" notes * generated by the Jasmine to Vitest schematic. * * It defines the `TODO_NOTES` constant, which contains the message and optional * documentation URL for each category of manual migration task. * * The file also exports advanced mapped types (`TodoCategory`, `TodoContextMap`) * that are inferred directly from the `TODO_NOTES` object. This creates a * maintainable, type-safe system that ensures consistency across all * transformers and prevents runtime errors. */ /** * The central configuration for all "TODO" notes. Each key represents a unique * `TodoCategory`. * * Each entry is an object with: * - `message`: A string or a function that returns a string. If it's a function, * it receives a `context` object to generate a dynamic message. * - `url`: An optional documentation URL that will be appended to the message. */ export const TODO_NOTES = { 'pending': { message: 'The pending() function was converted to a skipped test (`it.skip`).', url: 'https://vitest.dev/api/vi.html#it-skip', }, 'toHaveSpyInteractions': { message: 'Unsupported matcher ".toHaveSpyInteractions()" found. ' + 'Please migrate this manually by checking the `mock.calls.length` of the individual spies.', }, 'toThrowMatching': { message: (context: { name: string }): string => `Unsupported matcher ".${context.name}()" found. Please migrate this manually.`, url: 'https://vitest.dev/api/expect.html#tothrowerror', }, 'toBePending': { message: '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.', }, 'unsupported-expect-async-matcher': { message: (context: { name: string }): string => `Unsupported expectAsync matcher ".${context.name}()" found. Please migrate this manually.`, }, 'arrayWithExactContents-dynamic-variable': { message: 'Cannot transform jasmine.arrayWithExactContents with a dynamic variable. Please migrate this manually.', }, 'arrayWithExactContents-check': { message: "Verify this matches strict array content (multiset equality). Vitest's arrayContaining is a subset check.", }, 'expect-nothing': { message: 'expect().nothing() has been removed because it is redundant in Vitest. Tests without assertions pass by default.', }, 'unsupported-jasmine-member': { message: (context: { name: string }): string => `jasmine.${context.name} is not supported.`, }, 'setSpecProperty': { message: 'Unsupported global function `setSpecProperty` found. This function is used for custom reporters in Jasmine ' + 'and has no direct equivalent in Vitest.', }, 'setSuiteProperty': { message: 'Unsupported global function `setSuiteProperty` found. This function is used for custom reporters in Jasmine ' + 'and has no direct equivalent in Vitest.', }, 'throwUnless': { message: 'Unsupported global function `throwUnless` found. Please migrate manually to a direct assertion.', }, 'throwUnlessAsync': { message: 'Unsupported global function `throwUnlessAsync` found. Please migrate manually to a direct assertion.', }, 'getSpecProperty': { message: 'Unsupported global function `getSpecProperty` found. Please migrate manually.', }, 'addMatchers': { message: 'jasmine.addMatchers is not supported. Please manually migrate to expect.extend().', url: 'https://vitest.dev/api/expect.html#expect-extend', }, 'addAsyncMatchers': { message: 'jasmine.addAsyncMatchers is not supported. Please manually migrate to expect.extend().', url: 'https://vitest.dev/api/expect.html#expect-extend', }, 'addCustomEqualityTester': { message: 'jasmine.addCustomEqualityTester is not supported. Please manually migrate to expect.addEqualityTesters().', url: 'https://vitest.dev/api/expect.html#expect-addequalitytesters', }, 'addCustomObjectFormatter': { message: 'jasmine.addCustomObjectFormatter is not supported. May be possible to migrate to expect.addSnapshotSerializer().', url: 'https://vitest.dev/api/expect.html#expect-addsnapshotserializer', }, 'mapContaining': { message: 'jasmine.mapContaining is not supported. Vitest does not have a built-in matcher for Maps.' + ' Please manually assert the contents of the Map.', }, 'setContaining': { message: 'jasmine.setContaining is not supported. Vitest does not have a built-in matcher for Sets.' + ' Please manually assert the contents of the Set.', }, 'addSpyStrategy': { message: 'jasmine.addSpyStrategy is not supported. Please manually migrate to spy.mockImplementation().', url: 'https://vitest.dev/api/mock.html#mockimplementation', }, 'unknown-jasmine-property': { message: (context: { name: string }): string => `Unsupported jasmine property "${context.name}" found. Please migrate this manually.`, }, 'spyOnAllFunctions': { message: 'Vitest does not have a direct equivalent for jasmine.spyOnAllFunctions().' + ' Please spy on individual methods manually using vi.spyOn().', url: 'https://vitest.dev/api/vi.html#vi-spyon', }, 'createSpyObj-single-argument': { message: 'jasmine.createSpyObj called with a single argument is not supported for transformation.', url: 'https://vitest.dev/api/vi.html#vi-fn', }, 'createSpyObj-dynamic-variable': { message: 'Cannot transform jasmine.createSpyObj with a dynamic variable. Please migrate this manually.', url: 'https://vitest.dev/api/vi.html#vi-fn', }, 'createSpyObj-dynamic-property-map': { message: 'Cannot transform jasmine.createSpyObj with a dynamic property map. Please migrate this manually.', url: 'https://vitest.dev/api/vi.html#vi-fn', }, 'unsupported-spy-strategy': { message: (context: { name: string }): string => `Unsupported spy strategy ".and.${context.name}()" found. Please migrate this manually.`, url: 'https://vitest.dev/api/mocked.html#mock', }, 'mostRecent-without-args': { message: 'Direct usage of mostRecent() is not supported.' + ' Please refactor to access .args directly or use vi.mocked(spy).mock.lastCall.', url: 'https://vitest.dev/api/mocked.html#mock-lastcall', }, 'saveArgumentsByValue': { message: 'Vitest does not have a direct equivalent for spy.calls.saveArgumentsByValue().' + ' Please migrate this manually by cloning and storing the arguments in a local variable.', }, 'clockAutoTick': { message: 'Vitest does not have a direct equivalent for jasmine.clock().autoTick(). Please migrate this manually.', url: 'https://vitest.dev/api/vi.html#fake-timers', }, 'clockWithMock': { message: 'Vitest does not have a direct equivalent for jasmine.clock().withMock().' + ' Please migrate this manually via vi.useFakeTimers() and vi.useRealTimers().', url: 'https://vitest.dev/api/vi.html#vi-usefaketimers', }, 'unhandled-done-usage': { message: "The 'done' callback was used in an unhandled way. Please migrate manually.", }, 'flush-max-turns': { message: 'flush(maxTurns) was called but maxTurns parameter is not migrated. Please migrate manually.', }, 'flush-return-value': { message: 'flush() return value is not migrated. Please migrate manually.', }, } as const; /** * A union type of all possible "TODO" categories. * It is derived from the keys of the `TODO_NOTES` object to ensure that only * valid categories can be used throughout the transformers. */ export type TodoCategory = keyof typeof TODO_NOTES; /** * A mapped type that creates a map from a `TodoCategory` to the type of the * context object that its message function expects. This provides strong type * safety for calls to `addTodoComment`. * * It works by checking if the `message` property for a given category is a * function. If it is, it uses `infer` to extract the type of the first * parameter (`P`). If it's not a function, it resolves to `never`. * * @example * // `Context` will be `{ name: string }` * type Context = TodoContextMap['unknown-jasmine-property']; * * // `Context` will be `never` * type Context = TodoContextMap['pending']; */ export type TodoContextMap = { [K in TodoCategory]: (typeof TODO_NOTES)[K]['message'] extends (context: infer P) => string ? P : never; };