-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Passing serializable data from globalSetup to tests #4025
Comments
I think it might be nice to have some kind of // globalSetup.js
export function setup({ provide }) {
provide('router', { port: 3000, hostname: 'localhost' })
} // inject.test.js
import { vi, expect } from 'vitest'
expect(vi.inject('router')).toEqual({ port: 3000, hostname: 'localhost' }) It can be also used in reporters or during other lifecycle hooks (like in reporters) for usage by libraries (@nicojs do you think this might also be useful for you?): export default {
test: {
reporters: [
{
onInit(ctx) { ctx.provide('some-data', { data: true }) }
}
]
}
} |
Do you want the injection to be explicit? Is there a downside of injecting it by default on worker init (like config is currently being injected)? I would greatly appreciate an ability to extend the types (via |
The user explicitly defines what should be injected, and then it will initiated in the worker init phase.
Sure, it can be typed like: interface VitestProvide {
router: { port: number }
}
vi.inject('router') // { port: number }
I don't understand what you mean. The return value is a teardown function. |
I mean the
👍
Yep, that's why I mention breaking change. // global.setup.ts
export default async () => {
// setup
return {
teardown: async () => {...},
data: { ... } // this is provided data
}
} This will break having multiple global setups though, so I don't think it will work. |
But why limit the usage only to a test method? What if you need to access it outside of the test? In
I don't like this because it's a very limited solution and it doesn't really explain what |
Absolutely agree.
Is there a reason to not have test context there (maybe a suite context)? |
Because context is created for each test individually, but |
It does make sense. // first beforeAll
beforeAll(async (context) => {
// sets context.beforeAllFirstData
})
// last beforeAll
beforeAll(async (context) => {
// uses context.beforeAllFirstData
// sets context.beforeAllLastData
})
// first beforeEach
beforeEach(async (context) => {
// uses context.beforeAllFirstData
// uses context.beforeAllLastData
// sets context.beforeEachFirst
})
// last beforeEach
beforeEach(async (context) => {
// uses context.beforeAllFirstData
// uses context.beforeAllLastData
// uses context.beforeEachFirst
// sets context.beforeEachLast
})
test(async () => {
// uses context.beforeAllFirstData
// uses context.beforeAllLastData
// uses context.beforeEachFirst
// uses context.beforeEachLast
});
// .. and the same with afterEach / afterAll This is kinda out of the scope for this issue though, do you want me to open a separate discussion on that topic? |
As I said, this is not possible since context is unique to a test (and it creates a new one for before each test) and doesn't exist outside of it, so you don't have access to it in these hooks. |
@sheremet-va |
Do you mean inject/provide? Yes, should be straightforward to implement. |
Great, do you (or someone else among maintainers) have capacity to implement it or plan to leave for the community? |
Clear and concise description of the problem
The problem
I would like to use a single resource (say, a server with a DB) for all the tests, but I need to pass that server (in a form of hostname / port) to the tests.
I'm aware that passing actual instances to a worker is somewhere between smelly and impossible, so I want to pass a small bit of serializeable data, hostname and port in my case.
globalSetup and the data
Unfortunately,
globalSetup
files don't get any data from the outside world (Jest counterparty does actually getglobalConfig
andprojectConfig
as arguments), so I made a tiny patch to fix that:Passing data to the test
I found that I can pass
environmentOptions
to the environment which later can inject whatever needs to be injected directly in the global scope of the test (as well as setup file, I believe it is the same global scope).I didn't find a way to modify those
environmentOptions
other way than adding those toconfigOverrides
prop of the project config, so I ended up doing that.My setup to achieve data passing around looked like this:
vitest.config.ts
global.setup.ts
environment.ts
tests.setup.ts
Cutting the (environment) middleman
I didn't like that I used environment as a middleman to just pass the data to the test, so I started digging.
I found that
ResolvedConfig
could actually be found inglobalThis.__vitest_worker__.config
in the global scope of a worker, so I removed the environment and a final version oftests.setup.ts
looks like this:Suggested solution
I believe the main idea behind not letting data pass between a Vitest global scope and test worker global scope was to prevent leaking.
The data flow between those two scopes is not hard to do (considering Vitest not passing any data to
globalSetup
is a quirk, not a reasonable decision), so I suggest we can implement a more user-friendly way to pass it around (maybe a serializeability check can be added to add more precautionary measures).Alternative
Keep my hacky solution as it is.
Additional context
There was an issue similar to this one and the solution provided was using filesystem to pass serializable data around (
jest-puppeteer
made this suggestion popular).I believe that's not the way (it adds one more point of potential errors), managing resources should be easier.
I don't have much experience using workers and VM contexts, but it even could be a way to pass handles around so we can have a strictly typed messaging system between Vitest global scope and test worker global scope or pass actual object handles around.
Validations
The text was updated successfully, but these errors were encountered: