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( }.css = ${runtimeTemplate.basicFunction(
"chunkIds, removedChunks, removedModules, promises, applyHandlers, updatedModulesList", "chunkIds, removedChunks, removedModules, promises, applyHandlers, updatedModulesList",
[ [
isNeutralPlatform
? "if (typeof document === 'undefined') return;"
: "",
"applyHandlers.push(applyHandler);", "applyHandlers.push(applyHandler);",
`chunkIds.forEach(${runtimeTemplate.basicFunction("chunkId", [ `chunkIds.forEach(${runtimeTemplate.basicFunction("chunkId", [
`var filename = ${RuntimeGlobals.getChunkCssFilename}(chunkId);`, `var filename = ${RuntimeGlobals.getChunkCssFilename}(chunkId);`,

View File

@ -378,14 +378,14 @@ class CssModulesPlugin {
const hmrCode = Template.asString([ const hmrCode = Template.asString([
"", "",
`var exports = ${stringifiedExports};`, `var __webpack_css_exports__ = ${stringifiedExports};`,
"// only invalidate when locals change", "// 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();"), Template.indent("module.hot.invalidate();"),
"} else {", "} else {",
Template.indent("module.hot.accept();"), 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)); return new ConcatSource(source, "\n", new RawSource(hmrCode));

View File

@ -97,6 +97,17 @@ const describeCases = config => {
new webpack.LoaderOptionsPlugin(fakeUpdateLoaderOptions) new webpack.LoaderOptionsPlugin(fakeUpdateLoaderOptions)
); );
if (!options.recordsPath) options.recordsPath = recordsPath; 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 = webpack(options);
compiler.run((err, stats) => { compiler.run((err, stats) => {
if (err) return done(err); if (err) return done(err);
@ -139,6 +150,7 @@ const describeCases = config => {
return `./${url}`; return `./${url}`;
}; };
const window = { const window = {
_elements: [],
fetch: async url => { fetch: async url => {
try { try {
const buffer = await new Promise((resolve, reject) => { const buffer = await new Promise((resolve, reject) => {
@ -169,30 +181,67 @@ const describeCases = config => {
createElement(type) { createElement(type) {
return { return {
_type: type, _type: type,
_attrs: {}, sheet: {},
getAttribute(name) {
return this[name];
},
setAttribute(name, value) { setAttribute(name, value) {
this._attrs[name] = value; this[name] = value;
},
removeAttribute(name) {
delete this[name];
}, },
parentNode: { parentNode: {
removeChild(node) { removeChild(node) {
// ok window._elements = window._elements.filter(
item => item !== node
);
} }
} }
}; };
}, },
head: { head: {
appendChild(element) { appendChild(element) {
window._elements.push(element);
if (element._type === "script") { if (element._type === "script") {
// run it // run it
Promise.resolve().then(() => { Promise.resolve().then(() => {
_require(urlToRelativePath(element.src)); _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) { getElementsByTagName(name) {
if (name === "head") return [this.head]; 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"); 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) { function _next(callback) {
fakeUpdateLoaderOptions.updateIndex++; fakeUpdateLoaderOptions.updateIndex++;
compiler.run((err, stats) => { compiler.run((err, stats) => {
@ -249,6 +306,9 @@ const describeCases = config => {
function _require(module) { function _require(module) {
if (module.startsWith("./")) { if (module.startsWith("./")) {
const p = path.join(outputDirectory, module); const p = path.join(outputDirectory, module);
if (module.endsWith(".css")) {
return fs.readFileSync(p, "utf-8");
}
if (module.endsWith(".json")) { if (module.endsWith(".json")) {
return JSON.parse(fs.readFileSync(p, "utf-8")); 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
}
};