test: added

This commit is contained in:
alexander.akait 2024-11-29 20:35:09 +03:00
parent d5f19bf9a4
commit 5e2abae79e
16 changed files with 232 additions and 7 deletions

View File

@ -453,6 +453,9 @@ class CssLoadingRuntimeModule extends RuntimeModule {
}.css = ${runtimeTemplate.basicFunction(
"chunkIds, removedChunks, removedModules, promises, applyHandlers, updatedModulesList",
[
isNeutralPlatform
? "if (typeof document === 'undefined') return;"
: "",
"applyHandlers.push(applyHandler);",
`chunkIds.forEach(${runtimeTemplate.basicFunction("chunkId", [
`var filename = ${RuntimeGlobals.getChunkCssFilename}(chunkId);`,

View File

@ -378,14 +378,14 @@ class CssModulesPlugin {
const hmrCode = Template.asString([
"",
`var exports = ${stringifiedExports};`,
`var __webpack_css_exports__ = ${stringifiedExports};`,
"// only invalidate when locals change",
"if (module.hot.data && module.hot.data.exports && module.hot.data.exports != exports) {",
"if (module.hot.data && module.hot.data.__webpack_css_exports__ && module.hot.data.__webpack_css_exports__ != __webpack_css_exports__) {",
Template.indent("module.hot.invalidate();"),
"} else {",
Template.indent("module.hot.accept();"),
"}",
"module.hot.dispose(function(data) { data.exports = exports; });"
"module.hot.dispose(function(data) { data.__webpack_css_exports__ = __webpack_css_exports__; });"
]);
return new ConcatSource(source, "\n", new RawSource(hmrCode));

View File

@ -97,6 +97,17 @@ const describeCases = config => {
new webpack.LoaderOptionsPlugin(fakeUpdateLoaderOptions)
);
if (!options.recordsPath) options.recordsPath = recordsPath;
let testConfig = {};
try {
// try to load a test file
testConfig = Object.assign(
testConfig,
require(path.join(testDirectory, "test.config.js"))
);
} catch (_err) {
// ignored
}
compiler = webpack(options);
compiler.run((err, stats) => {
if (err) return done(err);
@ -139,6 +150,7 @@ const describeCases = config => {
return `./${url}`;
};
const window = {
_elements: [],
fetch: async url => {
try {
const buffer = await new Promise((resolve, reject) => {
@ -169,30 +181,67 @@ const describeCases = config => {
createElement(type) {
return {
_type: type,
_attrs: {},
sheet: {},
getAttribute(name) {
return this[name];
},
setAttribute(name, value) {
this._attrs[name] = value;
this[name] = value;
},
removeAttribute(name) {
delete this[name];
},
parentNode: {
removeChild(node) {
// ok
window._elements = window._elements.filter(
item => item !== node
);
}
}
};
},
head: {
appendChild(element) {
window._elements.push(element);
if (element._type === "script") {
// run it
Promise.resolve().then(() => {
_require(urlToRelativePath(element.src));
});
} else if (element._type === "link") {
Promise.resolve().then(() => {
if (element.onload) {
// run it
element.onload({ type: "load" });
}
});
}
},
insertBefore(element, before) {
window._elements.push(element);
if (element._type === "script") {
// run it
Promise.resolve().then(() => {
_require(urlToRelativePath(element.src));
});
} else if (element._type === "link") {
// run it
Promise.resolve().then(() => {
element.onload({ type: "load" });
});
}
}
},
getElementsByTagName(name) {
if (name === "head") return [this.head];
if (name === "script") return [];
if (name === "script" || name === "link") {
return window._elements.filter(
item => item._type === name
);
}
throw new Error("Not supported");
}
},
@ -209,6 +258,14 @@ const describeCases = config => {
}
};
const moduleScope = {
window
};
if (testConfig.moduleScope) {
testConfig.moduleScope(moduleScope, options);
}
function _next(callback) {
fakeUpdateLoaderOptions.updateIndex++;
compiler.run((err, stats) => {
@ -249,6 +306,9 @@ const describeCases = config => {
function _require(module) {
if (module.startsWith("./")) {
const p = path.join(outputDirectory, module);
if (module.endsWith(".css")) {
return fs.readFileSync(p, "utf-8");
}
if (module.endsWith(".json")) {
return JSON.parse(fs.readFileSync(p, "utf-8"));
}

View File

@ -0,0 +1,28 @@
import * as styles from "./style.module.css";
it("should work", async function (done) {
expect(styles).toMatchObject({ class: "_style_module_css-class" });
const styles2 = await import("./style2.module.css");
expect(styles2).toMatchObject({
foo: "_style2_module_css-foo"
});
module.hot.accept(["./style.module.css", "./style2.module.css"], () => {
expect(styles).toMatchObject({
"class-other": "_style_module_css-class-other"
});
import("./style2.module.css").then(styles2 => {
expect(styles2).toMatchObject({
"bar": "_style2_module_css-bar"
});
done();
});
});
NEXT(require("../../update")(done));
});
module.hot.accept();

View File

@ -0,0 +1,7 @@
.class {
color: red;
}
---
.class-other {
color: blue;
}

View File

@ -0,0 +1,7 @@
.foo {
color: red;
}
---
.bar {
color: blue;
}

View File

@ -0,0 +1,8 @@
module.exports = {
moduleScope(scope) {
const link = scope.window.document.createElement("link");
link.rel = "stylesheet";
link.href = "https://test.cases/path/bundle.css";
scope.window.document.head.appendChild(link);
}
};

View File

@ -0,0 +1,8 @@
/** @type {import("../../../../").Configuration} */
module.exports = {
mode: "development",
devtool: false,
experiments: {
css: true
}
};

View File

@ -0,0 +1,25 @@
it("should work", async function (done) {
const styles = await import(/* webpackFetchPriority: "high" */ "./style.module.css");
expect(styles).toMatchObject({
class: "_style_module_css-class"
});
module.hot.accept("./style.module.css", () => {
import("./style.module.css").then(styles => {
expect(styles).toMatchObject({
"class-other": "_style_module_css-class-other"
});
expect(
window.document.getElementsByTagName('link')[0].getAttribute('fetchpriority')
).toBe('high')
done();
});
});
NEXT(require("../../update")(done));
});
module.hot.accept();

View File

@ -0,0 +1,7 @@
.class {
color: red;
}
---
.class-other {
color: blue;
}

View File

@ -0,0 +1,8 @@
/** @type {import("../../../../").Configuration} */
module.exports = {
mode: "development",
devtool: false,
experiments: {
css: true
}
};

View File

@ -0,0 +1,28 @@
import "./style.css";
const getFile = name =>
__non_webpack_require__("fs").readFileSync(
__non_webpack_require__("path").join(__dirname, name),
"utf-8"
);
it("should work", async function (done) {
const style = getFile("bundle.css");
expect(style).toContain("color: red;");
await import("./style2.css");
const style2 = getFile("style2_css.css");
expect(style2).toContain("color: red;");
NEXT(require("../../update")(done, true, () => {
const style = getFile("bundle.css");
expect(style).toContain("color: blue;");
const style2 = getFile("style2_css.css");
expect(style2).toContain("color: blue;");
done();
}));
});
module.hot.accept();

View File

@ -0,0 +1,7 @@
.class {
color: red;
}
---
.class-other {
color: blue;
}

View File

@ -0,0 +1,7 @@
.foo {
color: red;
}
---
.bar {
color: blue;
}

View File

@ -0,0 +1,8 @@
module.exports = {
moduleScope(scope) {
const link = scope.window.document.createElement("link");
link.rel = "stylesheet";
link.href = "https://test.cases/path/bundle.css";
scope.window.document.head.appendChild(link);
}
};

View File

@ -0,0 +1,14 @@
/** @type {import("../../../../").Configuration} */
module.exports = {
mode: "development",
devtool: false,
output: {
cssChunkFilename: "[name].css"
},
node: {
__dirname: false
},
experiments: {
css: true
}
};