feat(runner): Add full names to tasks (#9087)

This commit is contained in:
Raul Macarie 2025-11-25 14:50:06 +01:00 committed by GitHub
parent 2cc34e0d4a
commit 821aa20021
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 453 additions and 9 deletions

View File

@ -42,7 +42,7 @@ export async function collectTests(
runner.onCollectStart?.(file)
clearCollectorContext(filepath, runner)
clearCollectorContext(file, runner)
try {
const setupFiles = toArray(config.setupFiles)

View File

@ -38,6 +38,7 @@ import { getHooks, setFn, setHooks, setTestFixture } from './map'
import { getCurrentTest } from './test-state'
import { findTestFileStackTrace } from './utils'
import { createChainable } from './utils/chain'
import { createTaskName } from './utils/tasks'
/**
* Creates a suite of tests, allowing for grouping and hierarchical organization of tests.
@ -213,14 +214,15 @@ function createDefaultSuite(runner: VitestRunner) {
}
export function clearCollectorContext(
filepath: string,
file: File,
currentRunner: VitestRunner,
): void {
if (!defaultSuite) {
defaultSuite = createDefaultSuite(currentRunner)
}
defaultSuite.file = file
runner = currentRunner
currentTestFilepath = filepath
currentTestFilepath = file.filepath
collectorContext.tasks.length = 0
defaultSuite.clear()
collectorContext.currentSuite = defaultSuite
@ -297,10 +299,16 @@ function createSuiteCollector(
const task = function (name = '', options: TaskCustomOptions = {}) {
const timeout = options?.timeout ?? runner.config.testTimeout
const currentSuite = collectorContext.currentSuite?.suite
const task: Test = {
id: '',
name,
suite: collectorContext.currentSuite?.suite,
fullName: createTaskName([
currentSuite?.fullName ?? collectorContext.currentSuite?.file?.fullName,
name,
]),
fullTestName: createTaskName([currentSuite?.fullTestName, name]),
suite: currentSuite,
each: options.each,
fails: options.fails,
context: undefined!,
@ -439,11 +447,18 @@ function createSuiteCollector(
suiteOptions = { timeout: suiteOptions }
}
const currentSuite = collectorContext.currentSuite?.suite
suite = {
id: '',
type: 'suite',
name,
suite: collectorContext.currentSuite?.suite,
fullName: createTaskName([
currentSuite?.fullName ?? collectorContext.currentSuite?.file?.fullName,
name,
]),
fullTestName: createTaskName([currentSuite?.fullTestName, name]),
suite: currentSuite,
mode,
each,
file: undefined!,

View File

@ -18,6 +18,40 @@ export interface TaskBase {
* Task name provided by the user. If no name was provided, it will be an empty string.
*/
name: string
/**
* Full name including the file path, any parent suites, and this task's name.
*
* Uses ` > ` as the separator between levels.
*
* @example
* // file
* 'test/task-names.test.ts'
* @example
* // suite
* 'test/task-names.test.ts > meal planning'
* 'test/task-names.test.ts > meal planning > grocery lists'
* @example
* // test
* 'test/task-names.test.ts > meal planning > grocery lists > calculates ingredients'
*/
fullName: string
/**
* Full name excluding the file path, including any parent suites and this task's name. `undefined` for file tasks.
*
* Uses ` > ` as the separator between levels.
*
* @example
* // file
* undefined
* @example
* // suite
* 'meal planning'
* 'meal planning > grocery lists'
* @example
* // test
* 'meal planning > grocery lists > calculates ingredients'
*/
fullTestName?: string
/**
* Task mode.
* - **skip**: task is skipped
@ -291,6 +325,7 @@ export interface Test<ExtraContext = object> extends TaskPopulated {
* @experimental
*/
artifacts: TestArtifact[]
fullTestName: string
}
export type Task = Test | Suite | File
@ -630,6 +665,7 @@ export interface SuiteCollector<ExtraContext = object> {
)[]
scoped: (fixtures: Fixtures<any, ExtraContext>) => void
fixtures: () => FixtureItem[] | undefined
file?: File
suite?: Suite
task: (name: string, options?: TaskCustomOptions) => Test<ExtraContext>
collect: (file: File) => Promise<Suite>

View File

@ -187,6 +187,7 @@ export function createFileTask(
const file: File = {
id: generateFileHash(path, projectName),
name: path,
fullName: path,
type: 'suite',
mode: 'queued',
filepath,

View File

@ -11,6 +11,7 @@ export {
export { limitConcurrency } from './limit-concurrency'
export { partitionSuiteChildren } from './suite'
export {
createTaskName,
getFullName,
getNames,
getSuites,

View File

@ -80,3 +80,7 @@ export function getFullName(task: Task, separator = ' > '): string {
export function getTestName(task: Task, separator = ' > '): string {
return getNames(task).slice(1).join(separator)
}
export function createTaskName(names: readonly (string | undefined)[], separator = ' > '): string {
return names.filter(name => name !== undefined).join(separator)
}

View File

@ -48,6 +48,7 @@ const fileWithTextStacks: RunnerTestFile = {
type: 'suite',
mode: 'run',
filepath: 'test/plain-stack-trace.ts',
fullName: 'test/plain-stack-trace.ts',
meta: {},
result: {
state: 'fail',
@ -98,6 +99,7 @@ describe('ViewReport', () => {
type: 'suite',
mode: 'run',
filepath: 'test/plain-stack-trace.ts',
fullName: 'test/plain-stack-trace.ts',
meta: {},
result: {
state: 'fail',
@ -157,6 +159,7 @@ describe('ViewReport', () => {
type: 'suite',
mode: 'run',
filepath: 'test/plain-stack-trace.ts',
fullName: 'test/plain-stack-trace.ts',
meta: {},
result: {
state: 'fail',

View File

@ -46,6 +46,7 @@ const failed = computed(() => {
id: file!.id,
file: file!,
name: file!.name,
fullName: file!.name,
level: 0,
type: 'suite',
mode: 'run',

View File

@ -4,6 +4,7 @@ import type { TestProject } from './project'
import { originalPositionFor, TraceMap } from '@jridgewell/trace-mapping'
import {
calculateSuiteHash,
createTaskName,
generateHash,
interpretTaskModes,
someTasksAreOnly,
@ -193,6 +194,7 @@ export function createFailedFileTask(project: TestProject, filepath: string, err
type: 'suite',
id: /* @__PURE__ */ generateHash(`${testFilepath}${project.config.name || ''}`),
name: testFilepath,
fullName: testFilepath,
mode: 'run',
tasks: [],
start: 0,
@ -252,6 +254,7 @@ function createFileTask(
type: 'suite',
id: /* @__PURE__ */ generateHash(`${testFilepath}${options.name || ''}`),
name: testFilepath,
fullName: testFilepath,
mode: 'run',
tasks: [],
start: ast.start,
@ -324,6 +327,8 @@ function createFileTask(
tasks: [],
mode,
name: definition.name,
fullName: createTaskName([latestSuite.fullName, definition.name]),
fullTestName: createTaskName([latestSuite.fullTestName, definition.name]),
end: definition.end,
start: definition.start,
location,
@ -343,6 +348,8 @@ function createFileTask(
mode,
context: {} as any, // not used on the server
name: definition.name,
fullName: createTaskName([latestSuite.fullName, definition.name]),
fullTestName: createTaskName([latestSuite.fullTestName, definition.name]),
end: definition.end,
start: definition.start,
location,

View File

@ -327,6 +327,8 @@ export class JUnitReporter implements Reporter {
id: file.id,
type: 'test',
name: file.name,
fullName: file.name,
fullTestName: file.name,
mode: 'run',
result: file.result,
meta: {},

View File

@ -3,6 +3,7 @@ import type { Rollup } from 'vite'
import type { TestProject } from '../node/project'
import {
calculateSuiteHash,
createTaskName,
generateHash,
interpretTaskModes,
someTasksAreOnly,
@ -60,6 +61,7 @@ export async function collectTests(
type: 'suite',
id: generateHash(`${testFilepath}${typecheckSubprojectName}`),
name: testFilepath,
fullName: testFilepath,
mode: 'run',
tasks: [],
start: ast.start,
@ -185,6 +187,8 @@ export async function collectTests(
tasks: [],
mode,
name: definition.name,
fullName: createTaskName([lastSuite.fullName, definition.name]),
fullTestName: createTaskName([lastSuite.fullTestName, definition.name]),
end: definition.end,
start: definition.start,
meta: {
@ -205,6 +209,8 @@ export async function collectTests(
timeout: 0,
context: {} as any, // not used in typecheck
name: definition.name,
fullName: createTaskName([lastSuite.fullName, definition.name]),
fullTestName: createTaskName([lastSuite.fullTestName, definition.name]),
end: definition.end,
start: definition.start,
annotations: [],

View File

@ -83,9 +83,12 @@ async function onMessage(message: WorkerRequest, project: TestProject, options:
)
taskFile.mode = 'run'
taskFile.result = { state: 'pass' }
const taskName = 'custom test'
const taskTest: RunnerTestCase = {
type: 'test',
name: 'custom test',
name: taskName,
fullName: `${taskFile.fullName} > ${taskName}`,
fullTestName: `${taskFile.fullTestName} > ${taskName}`,
id: `${taskFile.id}_0`,
context: {} as any,
suite: taskFile,

View File

@ -0,0 +1,325 @@
/**
* This test is self-referential - it validates its own structure and the structure of the tests defined below.
*
* The order and nesting of these test definitions MUST match the assertions, or the test will fail. The assertions use array indices (e.g., `task.file.tasks[0]`) to access specific tests, so reordering will break the test.
*
* If you need to modify this structure, update both the setup below AND the corresponding assertions above to maintain consistency.
*/
import type { RunnerTestSuite } from 'vitest'
import { describe, test } from 'vitest'
test('tasks have correct `fullName` and `fullTestName` properties', ({ expect, task }) => {
// this test validates the structure defined at the bottom of this file.
//
// structure (must match setup at bottom):
//
// task-names.test.ts
// ├─ [0] tasks have correct `fullName` and `fullTestName` properties (this test)
// ├─ [1] creates new recipe
// ├─ [2] searches by ingredient
// ├─ [3] recipe management/
// │ ├─ [0] saves recipe
// │ └─ [1] deletes recipe
// └─ [4] meal planning/
// ├─ [0] generates weekly plan
// ├─ [1] grocery lists/
// │ ├─ [0] calculates ingredients
// │ ├─ [1] combines duplicate items
// │ └─ [2] shopping/
// │ ├─ [0] marks items as purchased
// │ └─ [1] estimates total cost
// ├─ [2] exports calendar
// └─ [3] nutrition tracking/
// ├─ [0] calculates daily calories
// └─ [1] tracks macros
// validate this test itself (task.file.tasks[0])
expect(task.suite).toBe(undefined)
expect(
task.fullName,
).toBe('test/task-names.test.ts > tasks have correct `fullName` and `fullTestName` properties')
expect(
task.fullTestName,
).toBe('tasks have correct `fullName` and `fullTestName` properties')
expect(task.file.fullName).toBe('test/task-names.test.ts')
expect(task.file.fullTestName).toBe(undefined)
const thisTest = task.file.tasks[0]
expect(thisTest.suite).toBe(undefined)
expect(thisTest.fullName).toBe(
'test/task-names.test.ts > tasks have correct `fullName` and `fullTestName` properties',
)
expect(thisTest.fullTestName).toBe(
'tasks have correct `fullName` and `fullTestName` properties',
)
expect(
task.file.tasks,
).toHaveLength(5)
// top-level tests
const createsRecipe = task.file.tasks[1]
expect(createsRecipe.suite).toBe(undefined)
expect(createsRecipe.fullName).toBe(
'test/task-names.test.ts > creates new recipe',
)
expect(createsRecipe.fullTestName).toBe(
'creates new recipe',
)
const searchIngredient = task.file.tasks[2]
expect(searchIngredient.suite).toBe(undefined)
expect(searchIngredient.fullName).toBe(
'test/task-names.test.ts > searches by ingredient',
)
expect(searchIngredient.fullTestName).toBe(
'searches by ingredient',
)
// single-level suite
const recipeManagement = task.file.tasks[3] as RunnerTestSuite
expect(recipeManagement.suite).toBe(undefined)
expect(recipeManagement.fullName).toBe(
'test/task-names.test.ts > recipe management',
)
expect(recipeManagement.fullTestName).toBe(
'recipe management',
)
expect(recipeManagement.tasks).toHaveLength(2)
const savesRecipe = recipeManagement.tasks[0]
expect(savesRecipe.suite?.fullName).toBe(
'test/task-names.test.ts > recipe management',
)
expect(savesRecipe.suite?.fullTestName).toBe(
'recipe management',
)
expect(savesRecipe.fullName).toBe(
'test/task-names.test.ts > recipe management > saves recipe',
)
expect(savesRecipe.fullTestName).toBe(
'recipe management > saves recipe',
)
const deletesRecipe = recipeManagement.tasks[1]
expect(deletesRecipe.suite?.fullName).toBe(
'test/task-names.test.ts > recipe management',
)
expect(deletesRecipe.suite?.fullTestName).toBe(
'recipe management',
)
expect(deletesRecipe.fullName).toBe(
'test/task-names.test.ts > recipe management > deletes recipe',
)
expect(deletesRecipe.fullTestName).toBe(
'recipe management > deletes recipe',
)
// nested suites with mixed patterns
const mealPlanning = task.file.tasks[4] as RunnerTestSuite
expect(mealPlanning.suite).toBe(undefined)
expect(mealPlanning.fullName).toBe(
'test/task-names.test.ts > meal planning',
)
expect(mealPlanning.fullTestName).toBe(
'meal planning',
)
expect(mealPlanning.tasks).toHaveLength(4)
const generatesPlan = mealPlanning.tasks[0]
expect(generatesPlan.suite?.fullName).toBe(
'test/task-names.test.ts > meal planning',
)
expect(generatesPlan.suite?.fullTestName).toBe(
'meal planning',
)
expect(generatesPlan.fullName).toBe(
'test/task-names.test.ts > meal planning > generates weekly plan',
)
expect(generatesPlan.fullTestName).toBe(
'meal planning > generates weekly plan',
)
const groceryList = mealPlanning.tasks[1] as RunnerTestSuite
expect(groceryList.suite?.fullName).toBe(
'test/task-names.test.ts > meal planning',
)
expect(groceryList.suite?.fullTestName).toBe(
'meal planning',
)
expect(groceryList.fullName).toBe(
'test/task-names.test.ts > meal planning > grocery lists',
)
expect(groceryList.fullTestName).toBe(
'meal planning > grocery lists',
)
expect(groceryList.tasks).toHaveLength(3)
const calculatesIngredients = groceryList.tasks[0]
expect(calculatesIngredients.suite?.fullName).toBe(
'test/task-names.test.ts > meal planning > grocery lists',
)
expect(calculatesIngredients.suite?.fullTestName).toBe(
'meal planning > grocery lists',
)
expect(calculatesIngredients.fullName).toBe(
'test/task-names.test.ts > meal planning > grocery lists > calculates ingredients',
)
expect(calculatesIngredients.fullTestName).toBe(
'meal planning > grocery lists > calculates ingredients',
)
const combinesItems = groceryList.tasks[1]
expect(combinesItems.suite?.fullName).toBe(
'test/task-names.test.ts > meal planning > grocery lists',
)
expect(combinesItems.suite?.fullTestName).toBe(
'meal planning > grocery lists',
)
expect(combinesItems.fullName).toBe(
'test/task-names.test.ts > meal planning > grocery lists > combines duplicate items',
)
expect(combinesItems.fullTestName).toBe(
'meal planning > grocery lists > combines duplicate items',
)
const shopping = groceryList.tasks[2] as RunnerTestSuite
expect(shopping.suite?.fullName).toBe(
'test/task-names.test.ts > meal planning > grocery lists',
)
expect(shopping.suite?.fullTestName).toBe(
'meal planning > grocery lists',
)
expect(shopping.fullName).toBe(
'test/task-names.test.ts > meal planning > grocery lists > shopping',
)
expect(shopping.fullTestName).toBe(
'meal planning > grocery lists > shopping',
)
expect(shopping.tasks).toHaveLength(2)
const marksItemsPurchased = shopping.tasks[0]
expect(marksItemsPurchased.suite?.fullName).toBe(
'test/task-names.test.ts > meal planning > grocery lists > shopping',
)
expect(marksItemsPurchased.suite?.fullTestName).toBe(
'meal planning > grocery lists > shopping',
)
expect(marksItemsPurchased.fullName).toBe(
'test/task-names.test.ts > meal planning > grocery lists > shopping > marks items as purchased',
)
expect(marksItemsPurchased.fullTestName).toBe(
'meal planning > grocery lists > shopping > marks items as purchased',
)
const estimatesTotalCost = shopping.tasks[1]
expect(estimatesTotalCost.suite?.fullName).toBe(
'test/task-names.test.ts > meal planning > grocery lists > shopping',
)
expect(estimatesTotalCost.suite?.fullTestName).toBe(
'meal planning > grocery lists > shopping',
)
expect(estimatesTotalCost.fullName).toBe(
'test/task-names.test.ts > meal planning > grocery lists > shopping > estimates total cost',
)
expect(estimatesTotalCost.fullTestName).toBe(
'meal planning > grocery lists > shopping > estimates total cost',
)
const exportsCalendar = mealPlanning.tasks[2]
expect(exportsCalendar.suite?.fullName).toBe(
'test/task-names.test.ts > meal planning',
)
expect(exportsCalendar.suite?.fullTestName).toBe(
'meal planning',
)
expect(exportsCalendar.fullName).toBe(
'test/task-names.test.ts > meal planning > exports calendar',
)
expect(exportsCalendar.fullTestName).toBe(
'meal planning > exports calendar',
)
const nutritionTracking = mealPlanning.tasks[3] as RunnerTestSuite
expect(nutritionTracking.suite?.fullName).toBe(
'test/task-names.test.ts > meal planning',
)
expect(nutritionTracking.suite?.fullTestName).toBe(
'meal planning',
)
expect(nutritionTracking.fullName).toBe(
'test/task-names.test.ts > meal planning > nutrition tracking',
)
expect(nutritionTracking.fullTestName).toBe(
'meal planning > nutrition tracking',
)
expect(nutritionTracking.tasks).toHaveLength(2)
const calculatesCalories = nutritionTracking.tasks[0]
expect(calculatesCalories.suite?.fullName).toBe(
'test/task-names.test.ts > meal planning > nutrition tracking',
)
expect(calculatesCalories.suite?.fullTestName).toBe(
'meal planning > nutrition tracking',
)
expect(calculatesCalories.fullName).toBe(
'test/task-names.test.ts > meal planning > nutrition tracking > calculates daily calories',
)
expect(calculatesCalories.fullTestName).toBe(
'meal planning > nutrition tracking > calculates daily calories',
)
const tracksMacros = nutritionTracking.tasks[1]
expect(tracksMacros.suite?.fullName).toBe(
'test/task-names.test.ts > meal planning > nutrition tracking',
)
expect(tracksMacros.suite?.fullTestName).toBe(
'meal planning > nutrition tracking',
)
expect(tracksMacros.fullName).toBe(
'test/task-names.test.ts > meal planning > nutrition tracking > tracks macros',
)
expect(tracksMacros.fullTestName).toBe(
'meal planning > nutrition tracking > tracks macros',
)
})
// setup
// top-level tests
test('creates new recipe')
test('searches by ingredient')
// single-level suite
describe('recipe management', () => {
test('saves recipe')
test('deletes recipe')
})
// nested suites with mixed patterns
describe('meal planning', () => {
test('generates weekly plan')
describe('grocery lists', () => {
test('calculates ingredients')
test('combines duplicate items')
describe('shopping', () => {
test('marks items as purchased')
test('estimates total cost')
})
})
test('exports calendar')
describe('nutrition tracking', () => {
test('calculates daily calories')
test('tracks macros')
})
})

View File

@ -12,10 +12,13 @@ file.result = {
duration: 145.99284195899963,
}
const suiteName = 'suite'
const suite: RunnerTestSuite = {
id: `${file.id}_0`,
type: 'suite',
name: 'suite',
name: suiteName,
fullName: `${file.fullName} > ${suiteName}`,
fullTestName: `${file.fullTestName} > ${suiteName}`,
mode: 'run',
meta: {},
file,
@ -34,6 +37,8 @@ passedFile.tasks.push({
id: `${file.id}_1`,
type: 'test',
name: 'Math.sqrt()',
fullName: `${suite.fullName} > Math.sqrt()`,
fullTestName: `${suite.fullTestName} > Math.sqrt()`,
mode: 'run',
fails: undefined,
suite,
@ -75,6 +80,8 @@ const tasks: RunnerTestCase[] = [
id: `${suite.id}_0`,
type: 'test',
name: 'Math.sqrt()',
fullName: `${suite.fullName} > Math.sqrt()`,
fullTestName: `${suite.fullTestName} > Math.sqrt()`,
mode: 'run',
fails: undefined,
meta: {},
@ -98,6 +105,8 @@ const tasks: RunnerTestCase[] = [
id: `${suite.id}_1`,
type: 'test',
name: 'JSON',
fullName: `${suite.fullName} > JSON`,
fullTestName: `${suite.fullTestName} > JSON`,
mode: 'run',
annotations: [],
artifacts: [],
@ -113,6 +122,8 @@ const tasks: RunnerTestCase[] = [
id: `${suite.id}_3`,
type: 'test',
name: 'async with timeout',
fullName: `${suite.fullName} > async with timeout`,
fullTestName: `${suite.fullTestName} > async with timeout`,
mode: 'skip',
suite,
fails: undefined,
@ -128,6 +139,8 @@ const tasks: RunnerTestCase[] = [
id: `${suite.id}_4`,
type: 'test',
name: 'timeout',
fullName: `${suite.fullName} > timeout`,
fullTestName: `${suite.fullTestName} > timeout`,
annotations: [],
artifacts: [],
mode: 'run',
@ -143,6 +156,8 @@ const tasks: RunnerTestCase[] = [
id: `${suite.id}_5`,
type: 'test',
name: 'callback setup success ',
fullName: `${suite.fullName} > callback setup success `,
fullTestName: `${suite.fullTestName} > callback setup success `,
mode: 'run',
suite,
fails: undefined,
@ -158,6 +173,8 @@ const tasks: RunnerTestCase[] = [
id: `${suite.id}_6`,
type: 'test',
name: 'callback test success ',
fullName: `${suite.fullName} > callback test success `,
fullTestName: `${suite.fullTestName} > callback test success `,
mode: 'run',
suite,
fails: undefined,
@ -173,6 +190,8 @@ const tasks: RunnerTestCase[] = [
id: `${suite.id}_7`,
type: 'test',
name: 'callback setup success done(false)',
fullName: `${suite.fullName} > callback setup success done(false)`,
fullTestName: `${suite.fullTestName} > callback setup success done(false)`,
mode: 'run',
suite,
fails: undefined,
@ -188,6 +207,8 @@ const tasks: RunnerTestCase[] = [
id: `${suite.id}_8`,
type: 'test',
name: 'callback test success done(false)',
fullName: `${suite.fullName} > callback test success done(false)`,
fullTestName: `${suite.fullTestName} > callback test success done(false)`,
mode: 'run',
suite,
fails: undefined,
@ -211,6 +232,8 @@ const tasks: RunnerTestCase[] = [
id: `${suite.id}_9`,
type: 'test',
name: 'todo test',
fullName: `${suite.fullName} > todo test`,
fullTestName: `${suite.fullTestName} > todo test`,
mode: 'todo',
suite,
timeout: 0,

View File

@ -9,6 +9,7 @@ exports[`html reporter > resolves to "failing" status for test file "json-fail"
"environmentLoad": 0,
"file": [Circular],
"filepath": "<rootDir>/test/reporters/fixtures/json-fail.test.ts",
"fullName": "json-fail.test.ts",
"id": 0,
"importDurations": {},
"meta": {},
@ -28,6 +29,8 @@ exports[`html reporter > resolves to "failing" status for test file "json-fail"
"annotations": [],
"artifacts": [],
"file": [Circular],
"fullName": "json-fail.test.ts > should fail",
"fullTestName": "should fail",
"id": 0,
"location": {
"column": 1,
@ -129,6 +132,7 @@ exports[`html reporter > resolves to "passing" status for test file "all-passing
"environmentLoad": 0,
"file": [Circular],
"filepath": "<rootDir>/test/reporters/fixtures/all-passing-or-skipped.test.ts",
"fullName": "all-passing-or-skipped.test.ts",
"id": 0,
"importDurations": {},
"meta": {},
@ -148,6 +152,8 @@ exports[`html reporter > resolves to "passing" status for test file "all-passing
"annotations": [],
"artifacts": [],
"file": [Circular],
"fullName": "all-passing-or-skipped.test.ts > 2 + 3 = 5",
"fullTestName": "2 + 3 = 5",
"id": 0,
"location": {
"column": 1,
@ -170,6 +176,8 @@ exports[`html reporter > resolves to "passing" status for test file "all-passing
"annotations": [],
"artifacts": [],
"file": [Circular],
"fullName": "all-passing-or-skipped.test.ts > 3 + 3 = 6",
"fullTestName": "3 + 3 = 6",
"id": "1111755131_1",
"location": {
"column": 6,

View File

@ -10,19 +10,26 @@ const root = resolve(import.meta.dirname, '../fixtures')
test('calc the duration used by junit', () => {
const result: RunnerTaskResult = { state: 'pass', duration: 0 }
const file: RunnerTestFile = createFileTask('/test.ts', '/', 'test')
const suiteName
= 'suite'
const suite: RunnerTestSuite = {
id: '1_0',
type: 'suite',
name: 'suite',
name: suiteName,
fullName: `${file.fullName} > ${suiteName}`,
fullTestName: `${file.fullTestName} > ${suiteName}`,
mode: 'run',
tasks: [],
file,
meta: {},
}
const taskName = 'timeout'
const task: RunnerTestCase = {
id: '1_0_0',
type: 'test',
name: 'timeout',
name: taskName,
fullName: `${suite.fullName} > ${suiteName}`,
fullTestName: `${suite.fullTestName} > ${suiteName}`,
mode: 'run',
result,
annotations: [],

View File

@ -286,6 +286,8 @@ function createTest(name: string, file: File): Test {
return {
type: 'test',
name,
fullName: `${file.fullName} > ${name}`,
fullTestName: `${file.fullTestName} > ${name}`,
id: `${file.id}_0`,
mode: 'run',
file,