vitest icon indicating copy to clipboard operation
vitest copied to clipboard

`task` fixture is undefined in file-scoped fixtures

Open JQuezada0 opened this issue 4 months ago • 2 comments

Describe the bug

When using test.extend() with scope: "file", the task fixture is undefined. The same fixture definition works correctly without the file scope.

Expected behavior

task should be defined and accessible in file-scoped fixtures, at minimum providing task.file so fixtures can access file-level metadata like the filepath.

Actual behavior

task is undefined when the fixture has scope: "file".

Apologies if this is intentional, I couldn't find anything in the docs that suggests the built-in task fixture should ever be undefined.

Reproduction

https://stackblitz.com/edit/vitest-dev-vitest-ggimrrx6?file=test%2Frepro.test.ts

import { it as vitestIt, describe, expect } from "vitest"

const itFails = vitestIt.extend<{ foobar: string }>({
  foobar: [
    async ({ task }, use) => {
      // Worth noting that `expect` when taken from the dependencies is also undefined, so this uses global expect
      expect(task).toBeDefined()
      await use("foobar")
    },
    { scope: "file", auto: true },
  ]
})

const itWorks = vitestIt.extend<{ foobar: string }>({
  foobar: async ({ task, expect }, use) => {
    // But here expect is defined and works
    expect(task).toBeDefined()
    await use("foobar")
  }
})

describe("file-scope-fixture-repro", () => {
  itFails("should work", async ({ foobar, expect }) => {
    expect(foobar).toBe("foobar")
  })

  itWorks("should work", async ({ foobar, expect }) => {
    expect(foobar).toBe("foobar")
  })
})

System Info

System:
    OS: macOS 15.7.1
    CPU: (10) arm64 Apple M4
    Memory: 138.77 MB / 16.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 22.14.0 - /opt/homebrew/opt/node@22/bin/node
    Yarn: 1.22.22 - /opt/homebrew/bin/yarn
    npm: 10.9.3 - /Users/johnilquezada/Development/prismock/node_modules/.bin/npm
    bun: 1.2.16 - /opt/homebrew/bin/bun
  Browsers:
    Chrome: 142.0.7444.176
    Safari: 18.6
  npmPackages:
    @vitest/coverage-v8: 4.0.14 => 4.0.14 
    vitest: 4.0.15 => 4.0.15 
    vitest-mock-extended: 3.1.0 => 3.1.0

Used Package Manager

npm

Validations

JQuezada0 avatar Dec 04 '25 15:12 JQuezada0

Fixture with { scope: "file", auto: true } means that itFails/foobar to be invoked before any test case (i.e. task) starts, so there's no well defined meaning for task there. Can you explain your use case of using task in { scope: "file", auto: true } fixture?

hi-ogawa avatar Dec 05 '25 08:12 hi-ogawa

@hi-ogawa Hey there, I was hoping to be able to access file-level metadata, i.e. task.file. I specifically wanted to get the file path. But, since I'm using it.extend in a separate file, import.meta.url doesn't reflect the test file that's actually running. That said, I stumbled upon another way to get the path.

import { expect } from "vitest"

const testFilePath = expect.getState().testPath

It may also be interesting to be able to access the list of tests in the file via task.file.tasks, but in terms of concrete use-cases this isn't a blocker for me anymore, and sounds like it's not exactly a "bug" either so I think this can be closed.

One suggestion may be to call this out in the docs. It wasn't immediately obvious that task.file wouldn't be available in the file scope, but in hindsight the naming task implies that it's strictly task-scoped.

JQuezada0 avatar Dec 05 '25 15:12 JQuezada0