Probably less important: Setup is done with webpack Encore which generates a webpack config file, we use yarn
as a package manager, so vitest
is installed with yarn
.
Here is a simplified problem:
// vitest.config.js
import path from 'path';
export default {
resolve: {
alias: {
Common: path.resolve(__dirname, 'assets/packages')
}
}
};
// MyFooUsejq.js
import $ from 'jquery';
export default class MyFooUsejq {
#$myDiv;
constructor(selector) {
this.#$myDiv = $(selector);
}
get innerHtml() {
return this.#$myDiv.html();
}
}
// MyFooUsejq.test.js
import { expect, test } from 'vitest';
import MyFooUsejq from 'Common/MyFooUsejq'; // Common is an alias configured with webpack.
import { JSDOM } from 'jsdom';
test('use jquery', () => {
const jsdom = new JSDOM(`<!DOCTYPE html><html lang="en"><body><div id="foo">hello</div></body></html>`);
global.window = jsdom.window;
global.document = jsdom.window.document;
const foo = new MyFooUsejq('#foo');
expect(foo.innerHtml).toBe('hello');
});
Running yarn vitest --config=vitest.config.js MyFooUsejq.test.js
gives error:
Error: jQuery requires a window with a document
According to https://stackoverflow.com/a/52589859/5233188 setting a global window object should work for jQuery to detect it.
How can I keep import $ from 'jquery';
and set a window for jQuery in MyFooUsejq
?
As Heretic Monkey advised, jQuery needs to be loaded AFTER setting the global window
, but instead of using dynamic imports in all modules that import
jQuery, I added a dynamic import inside the test for Common/MyFooUsejq
. But I also think I set global.window
and global.document
wrong.
Working test:
// MyFooUsejq.test.js
import { expect, test } from 'vitest';
import { JSDOM } from 'jsdom';
test('use jquery', async () => {
const jsdom = new JSDOM(`<!DOCTYPE html><html lang="en"><body><div id="foo">hello</div></body></html>`);
global.window = jsdom.window;
const { default: MyFooUsejq } = await import('Pupil/Common/MyFooUsejq');
const foo = new MyFooUsejq('#foo');
expect(foo.innerHtml).toBe('hello');
});