Skip to content

Support scoped fixtures with dependencies defined in the outer scope #9305

@ari-bou

Description

@ari-bou

Clear and concise description of the problem

Currently, vitest doesn't appear to support scoped fixtures that depend on fixtures defined in the outer scope.

import { test as baseTest, describe, expect } from "vitest";

interface Fixtures {
    a: number,
    b: number,
    numbers: number[]
}

const test = baseTest.extend<Fixtures>({
    a: 1,
    b: 2,
    numbers: async ({ a }, use) => use([a]),
});

describe("suite fails", () => {
    test.scoped({
        numbers: async ({ a, b }, use) => use([a, b]),
    });

    test("test fails", async ({ numbers }) => {
        expect(numbers).toStrictEqual([1, 2]); // fails because numbers is [undefined, undefined]
    });
});

If I redefine the a and b fixtures in the narrower scope, then the test passes.

describe("suite passes", () => {
    test.scoped({
        // setting the dependencies resolves the issue
        a: 1,
        b: 2,
        numbers: async ({ a, b }, use) => use([a, b]),
    });

    test("test passes", async ({ numbers }) => {
        expect(numbers).toStrictEqual([1, 2]);
    });
});

While this is a valid workaround, it can be quite tedious to redefine fixtures that have already been defined in the outer scope. This is especially true for large dependency graphs where every upstream fixture would have to be redefined.

Suggested solution

Scoped fixtures should be able to use any of the fixtures that were previously defined in the outer scope. (This behaviour is in-line with pytest.)

Alternative

An alternative would be to have users adopt the following approach:

import { test as baseTest, describe, expect } from "vitest";

interface Fixtures {
    a: number,
    b: number,
    numbers: number[]
}

const fixtures = {
    a: 1,
    b: 2,
    numbers: async ({ a }, use) => use([a]),
};

const test = baseTest.extend<Fixtures>(fixtures);

describe("suite passes", () => {
    test.scoped({
        ...fixtures,
        numbers: async ({ a, b }, use) => use([a, b]),
    });

    test("test passes", async ({ numbers }) => {
        expect(numbers).toStrictEqual([1, 2]);
    });
});

Additional context

No response

Validations

Metadata

Metadata

Assignees

No one assigned

    Labels

    p3-minor-bugAn edge case that only affects very specific usage (priority)

    Type

    Projects

    Status

    Approved

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions