Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions packages/rspack-test-tools/etc/test-tools.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@ export function createConfigCase(name: string, src: string, dist: string): void;
// @public (undocumented)
export function createDefaultsCase(name: string, src: string): void;

// @public (undocumented)
export function createDevNormalCase(name: string, src: string, dist: string): void;

// @public (undocumented)
export function createDiagnosticCase(name: string, src: string, dist: string): void;

Expand Down Expand Up @@ -134,6 +137,9 @@ export function createNativeWatcher(name: string, src: string, dist: string, tem
// @public (undocumented)
export function createNormalCase(name: string, src: string, dist: string): void;

// @public (undocumented)
export function createProdNormalCase(name: string, src: string, dist: string): void;

// @public (undocumented)
export function createSerialCase(name: string, src: string, dist: string): void;

Expand Down
7 changes: 6 additions & 1 deletion packages/rspack-test-tools/src/case/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,12 @@ export {
export type { TMultiCompilerCaseConfig } from "./multi-compiler";
export { createMultiCompilerCase } from "./multi-compiler";
export { createNativeWatcher } from "./native-watcher";
export { createHotNormalCase, createNormalCase } from "./normal";
export {
createDevNormalCase,
createHotNormalCase,
createNormalCase,
createProdNormalCase
} from "./normal";
export { createSerialCase } from "./serial";
export type { TStatsAPICaseConfig } from "./stats-api";
export { createStatsAPICase } from "./stats-api";
Expand Down
38 changes: 30 additions & 8 deletions packages/rspack-test-tools/src/case/normal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ const NORMAL_CASES_ROOT = path.resolve(
);

const createCaseOptions = (
hot: boolean
hot: boolean,
mode?: "development" | "production"
): IBasicCaseCreatorOptions<ECompilerType> => {
return {
clean: true,
Expand All @@ -30,9 +31,13 @@ const createCaseOptions = (
{
config: async (context: ITestContext) => {
const compiler = getCompiler(context, name);
let options = defaultOptions(context, {
plugins: hot ? [new HotModuleReplacementPlugin()] : []
});
let options = defaultOptions(
context,
{
plugins: hot ? [new HotModuleReplacementPlugin()] : []
},
mode
);
options = await config(
context,
name,
Expand Down Expand Up @@ -74,6 +79,20 @@ export function createHotNormalCase(name: string, src: string, dist: string) {
hotCreator.create(name, src, dist);
}

const devCreator = new BasicCaseCreator(
createCaseOptions(false, "development")
);
export function createDevNormalCase(name: string, src: string, dist: string) {
devCreator.create(name, src, dist);
}

const prodCreator = new BasicCaseCreator(
createCaseOptions(false, "production")
);
export function createProdNormalCase(name: string, src: string, dist: string) {
prodCreator.create(name, src, dist);
}

function findBundle(
context: ITestContext,
options: TCompilerOptions<ECompilerType.Rspack>
Expand All @@ -90,7 +109,8 @@ function findBundle(

function defaultOptions<T extends ECompilerType.Rspack>(
context: ITestContext,
compilerOptions: TCompilerOptions<T>
compilerOptions: TCompilerOptions<T>,
mode?: "development" | "production"
) {
let testConfig: TCompilerOptions<T> = {};
const testConfigPath = path.join(context.getSource(), "test.config.js");
Expand All @@ -107,11 +127,12 @@ function defaultOptions<T extends ECompilerType.Rspack>(
entry: `./${path.relative(NORMAL_CASES_ROOT, context.getSource())}/`,
target: compilerOptions?.target || "async-node",
devtool: compilerOptions?.devtool,
mode: compilerOptions?.mode || "none",
mode: compilerOptions?.mode || mode || "none",
optimization: compilerOptions?.mode
? {
// emitOnErrors: true,
emitOnErrors: true,
minimizer: [terserForTesting],
minimize: false,
...testConfig.optimization
}
: {
Expand All @@ -125,14 +146,15 @@ function defaultOptions<T extends ECompilerType.Rspack>(
usedExports: true,
mangleExports: true,
// CHANGE: rspack does not support `emitOnErrors` yet.
// emitOnErrors: true,
emitOnErrors: true,
concatenateModules: !!testConfig?.optimization?.concatenateModules,
innerGraph: true,
// CHANGE: size is not supported yet
// moduleIds: "size",
// chunkIds: "size",
moduleIds: "named",
chunkIds: "named",
minimize: false,
minimizer: [terserForTesting],
...compilerOptions?.optimization
},
Expand Down
4 changes: 3 additions & 1 deletion packages/rspack-test-tools/src/helper/directory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@ export function describeByWalk(
if (options.exclude) {
if (
options.exclude.some(exclude => {
return exclude.test(folder);
return exclude.test(
path.join(dirname, folder).replace(/\\/g, "/")
);
})
) {
return false;
Expand Down
13 changes: 13 additions & 0 deletions tests/rspack-test/Normal-dev.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
const { createDevNormalCase, describeByWalk } = require("@rspack/test-tools");
const path = require("path");

describeByWalk(__filename, (name, src, dist) => {
createDevNormalCase(name, src, dist);
}, {
source: path.resolve(__dirname, "./normalCases"),
dist: path.resolve(__dirname, `./js/normal-dev`),
exclude: [
/parsing\/harmony-deep-exports/,
/parsing\/asi/
]
});
19 changes: 19 additions & 0 deletions tests/rspack-test/Normal-prod.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
const { createProdNormalCase, describeByWalk } = require("@rspack/test-tools");
const path = require("path");

describeByWalk(__filename, (name, src, dist) => {
createProdNormalCase(name, src, dist);
}, {
source: path.resolve(__dirname, "./normalCases"),
dist: path.resolve(__dirname, `./js/normal-prod`),
// FIXME: these cases throw errors in production
exclude: [
/warnings\/require-as-expression/,
/side-effects\/empty-modules/,
/parsing\/resolve-weak-context/,
/parsing\/issue-7519/,
/parsing\/api/,
/mjs\/cjs-import-default/,
/inner-graph\/simple/
]
});
80 changes: 80 additions & 0 deletions tests/rspack-test/compilerCases/banner-plugin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
const rspack = require("@rspack/core");
const fs = require("fs");

let lastStats = null;
/** @type {import('@rspack/test-tools').TCompilerCaseConfig[]} */
module.exports = [{
description: "should cache assets",
options(context) {
return {
mode: "development",
entry: {
entry1: context.getDist("entry1.js"),
entry2: context.getDist("entry2.js")
},
output: {
path: context.getDist("dist")
},
plugins: [new rspack.BannerPlugin("banner is a string")]
};
},
async compiler(context, compiler) {
compiler.outputFileSystem = fs;
fs.writeFileSync(context.getDist("entry1.js"), "1", "utf-8");
fs.writeFileSync(context.getDist("entry2.js"), "1", "utf-8");
},
async build(context, compiler) {
return new Promise((resolve, reject) => {
compiler.run((err, stats) => {
if (err) return reject(err);
try {
const footerFileResults = fs.readFileSync(context.getDist("dist/entry1.js"), "utf8").split("\n");
expect(footerFileResults[0]).toBe("/*! banner is a string */");
fs.writeFileSync(context.getDist("entry2.js"), "2", "utf-8");
compiler.run((err, stats) => {
if (err) return reject(err);
lastStats = stats;
resolve();
}, {
modifiedFiles: new Set([context.getDist("entry2.js")])
});
} catch (err) {
reject(err);
}

});
});
},
async check() {
const { assets } = lastStats.toJson();
expect(assets.find(as => as.name === "entry1.js").emitted).toBe(false);
expect(assets.find(as => as.name === "entry2.js").emitted).toBe(true);
}
}, {
description: "can place banner as footer",
options(context) {
return {
mode: "development",
entry: {
footerFile: context.getDist("footerFile.js")
},
output: {
path: context.getDist("dist")
},
plugins: [
new rspack.BannerPlugin({
banner: "banner is a string",
footer: true
})
]
};
},
async compiler(context, compiler) {
compiler.outputFileSystem = fs;
fs.writeFileSync(context.getDist("footerFile.js"), "footer", "utf-8");
},
async check({ context }) {
const footerFileResults = fs.readFileSync(context.getDist("dist/footerFile.js"), "utf8").split("\n");
expect(footerFileResults.pop()).toBe("/*! banner is a string */");
}
}];
131 changes: 131 additions & 0 deletions tests/rspack-test/compilerCases/changes-and-removals.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
const fs = require("fs");

const getChanges = (compiler) => {
const modifiedFiles = compiler.modifiedFiles;
const removedFiles = compiler.removedFiles;
return {
removed: removedFiles && [...removedFiles],
modified: modifiedFiles && [...modifiedFiles]
};
};

let changes = null;
/** @type {import('@rspack/test-tools').TCompilerCaseConfig[]} */
module.exports = [{
description: "should not track modified/removed files during initial watchRun",
options(context) {
changes = null;
return {
entry: context.getDist("temp-file.js"),
output: {
path: context.getDist("dist"),
filename: "bundle.js"
},
};
},
async compiler(context, compiler) {
compiler.hooks.watchRun.tap("ChangesAndRemovalsTest", (compiler) => {
changes = getChanges(compiler);
});
},
async build(context, compiler) {
return new Promise((resolve, reject) => {
const watcher = compiler.watch({ aggregateTimeout: 200 }, (err) => {
if (err) reject(err);
watcher.close(resolve);
});
});
},
async check() {
expect(changes).toEqual({
removed: [],
modified: []
});
}
}, {
description: "should track modified files when they've been modified",
options(context) {
changes = null;
return {
entry: context.getDist("temp-file.js"),
output: {
path: context.getDist("dist"),
filename: "bundle.js"
},
};
},
async build(context, compiler) {
let firstWatchRun = true;
let firstDone = true;
return new Promise((resolve, reject) => {
let watcher = null;
compiler.hooks.watchRun.tap("ChangesAndRemovalsTest", (compiler) => {
if (firstWatchRun) {
firstWatchRun = false;
return;
}
changes = getChanges(compiler);
watcher.close(resolve);
});
compiler.hooks.done.tap("ChangesAndRemovalsTest", () => {
if (!firstDone) return;
firstDone = false;
setTimeout(() => {
fs.appendFileSync(context.getDist("temp-file.js"), "\nlet x = 'file modified';");
}, 300);
});
watcher = compiler.watch({ aggregateTimeout: 200 }, (err) => {
if (err) reject(err);
});
});
},
async check({ context }) {
expect(changes).toEqual({
removed: [],
modified: [context.getDist("temp-file.js")]
});
}
}, {
description: "should track removed file when removing file",
options(context) {
changes = null;
return {
entry: context.getDist("temp-file.js"),
output: {
path: context.getDist("dist"),
filename: "bundle.js"
},
};
},
async build(context, compiler) {
let firstWatchRun = true;
let firstDone = true;
return new Promise((resolve, reject) => {
let watcher = null;
compiler.hooks.watchRun.tap("ChangesAndRemovalsTest", (compiler) => {
if (firstWatchRun) {
firstWatchRun = false;
return;
}
changes = getChanges(compiler);
watcher.close(resolve);
});
compiler.hooks.done.tap("ChangesAndRemovalsTest", () => {
if (!firstDone) return;
firstDone = false;
setTimeout(() => {
fs.unlinkSync(context.getDist("temp-file.js"));
}, 300);
});
watcher = compiler.watch({ aggregateTimeout: 200 }, (err) => {
if (err) reject(err);
});
});
},
async check({ context }) {
expect(changes).toEqual({
removed: [context.getDist("temp-file.js")],
modified: []
});
}
}];
Loading
Loading