it("should be able to use eager mode", function () {
	function load(name) {
		return import(/* webpackMode: "eager" */ "./dir1/" + name);
	}
	return testChunkLoading(load, true, true);
});

it("should be able to use lazy-once mode", function () {
	function load(name) {
		return import(/* webpackMode: "lazy-once" */ "./dir2/" + name);
	}
	return testChunkLoading(load, false, true);
});

it("should be able to use lazy-once mode with name", function () {
	function load(name) {
		return import(
			/* webpackMode: "lazy-once", webpackChunkName: "name-lazy-once" */ "./dir3/" +
				name
		);
	}
	return testChunkLoading(load, false, true);
});

it("should be able to use lazy mode", function () {
	function load(name) {
		return import(/* webpackMode: "lazy" */ "./dir4/" + name);
	}
	return testChunkLoading(load, false, false);
});

it("should be able to use lazy mode with name", function () {
	function load(name) {
		return import(
			/* webpackMode: "lazy", webpackChunkName: "name-lazy" */ "./dir5/" + name
		);
	}
	return testChunkLoading(load, false, false);
});

it("should be able to use lazy mode with name and placeholder", function () {
	function load(name) {
		return import(
			/* webpackMode: "lazy", webpackChunkName: "name-lazy-[request]" */ "./dir6/" +
				name
		);
	}
	return testChunkLoading(load, false, false);
});

it("should be able to combine chunks by name", function () {
	function load(name) {
		switch (name) {
			case "a":
				return import(/* webpackMode: "eager" */ "./dir7/a");
			case "b":
				return import(/* webpackChunkName: "name-3" */ "./dir7/b");
			case "c":
				return import(/* webpackChunkName: "name-3" */ "./dir7/c");
			case "d":
				return import(/* webpackChunkName: "name-3" */ "./dir7/d");
			default:
				throw new Error("Unexpected test data");
		}
	}
	return testChunkLoading(load, false, true);
});

it("should be able to use weak mode", function () {
	function load(name) {
		return import(/* webpackMode: "weak" */ "./dir8/" + name);
	}
	require("./dir8/a"); // chunks served manually by the user
	require("./dir8/b");
	require("./dir8/c");
	return testChunkLoading(load, true, true);
});

it("should be able to use weak mode (without context)", function () {
	function load(name) {
		switch (name) {
			case "a":
				return import(/* webpackMode: "weak" */ "./dir9/a");
			case "b":
				return import(/* webpackMode: "weak" */ "./dir9/b");
			case "c":
				return import(/* webpackMode: "weak" */ "./dir9/c");
			default:
				throw new Error("Unexpected test data");
		}
	}
	require("./dir9/a"); // chunks served manually by the user
	require("./dir9/b");
	require("./dir9/c");
	return testChunkLoading(load, true, true);
});

it("should not find module when mode is weak and chunk not served elsewhere", function () {
	var name = "a";
	return import(/* webpackMode: "weak" */ "./dir10/" + name).catch(function (
		e
	) {
		expect(e).toMatchObject({
			message: /not available/,
			code: /MODULE_NOT_FOUND/
		});
	});
});

it("should not find module when mode is weak and chunk not served elsewhere (without context)", function () {
	return import(/* webpackMode: "weak" */ "./dir11/a").catch(function (e) {
		expect(e).toMatchObject({
			message: /not available/,
			code: /MODULE_NOT_FOUND/
		});
	});
});

if (process.env.NODE_ENV === "production") {
	it("should contain only one export from webpackExports from module", function () {
		return import(/* webpackExports: "usedExports" */ "./dir12/a?1").then(
			module => {
				expect(module.usedExports).toEqual(["usedExports"]);
			}
		);
	});

	it("should contain only webpackExports from module", function () {
		return import(
			/* webpackExports: ["usedExports"] */ "./dir12/a?2"
		).then(module => {
			expect(module.usedExports).toEqual(["usedExports"]);
		});
	});

	it("should contain only webpackExports from module in eager mode", function () {
		return import(
			/*
			webpackMode: "eager",
			webpackExports: ["usedExports"]
		*/ "./dir12/a?3"
		).then(module => {
			expect(module.usedExports).toEqual(["usedExports"]);
		});
	});

	it("should contain webpackExports from module in weak mode", function () {
		require.resolve("./dir12/a?4");
		return import(
			/*
			webpackMode: "weak",
			webpackExports: ["usedExports"]
		*/ "./dir12/a?4"
		).then(module => {
			expect(module.usedExports).toEqual(["usedExports"]);
		});
	});

	it("should not mangle webpackExports from module", function () {
		return import(/* webpackExports: "longnameforexport" */ "./dir12/a?5").then(
			module => {
				expect(module).toHaveProperty("longnameforexport");
			}
		);
	});

	it("should not mangle default webpackExports from module", function () {
		return import(/* webpackExports: "default" */ "./dir12/a?6").then(
			module => {
				expect(module).toHaveProperty("default");
			}
		);
	});

	it("should contain only webpackExports from module in context mode", function () {
		const x = "b";
		return import(/* webpackExports: "usedExports" */ `./dir13/${x}`).then(
			module => {
				expect(module.usedExports).toEqual(["usedExports"]);
			}
		);
	});

	it("should be able to load with webpackFetchPriority high, low and auto", function () {
		return Promise.all([
			import(/* webpackFetchPriority: "high"*/ "./dir14/a"),
			import(/* webpackFetchPriority: "low"*/ "./dir14/b"),
			import(/* webpackFetchPriority: "auto"*/ "./dir14/c"),
		])
	})

	it("should not tree-shake default export for exportsType=default module", async function () {
		const jsonObject = await import(/* webpackExports: ["default"] */ "./dir15/json/object.json");
		const jsonArray = await import(/* webpackExports: ["default"] */ "./dir15/json/array.json");
		const jsonPrimitive = await import(/* webpackExports: ["default"] */ "./dir15/json/primitive.json");
		expect(jsonObject.default).toEqual({ a: 1 });
		expect(jsonObject.a).toEqual(1);
		expect(jsonArray.default).toEqual(["a"]);
		expect(jsonArray[0]).toBe("a");
		expect(jsonPrimitive.default).toBe("a");
		const a = await import(/* webpackExports: ["default"] */"./dir15/a");
		expect(a.default).toEqual({ a: 1, b: 2 });
		expect(a.a).toBe(1);
		expect(a.b).toBe(2);
	})

	it("should not tree-shake default export for exportsType=default context module", async function () {
		const dir = "json";
		const jsonObject = await import(/* webpackExports: ["default"] */ `./dir16/${dir}/object.json`);
		const jsonArray = await import(/* webpackExports: ["default"] */ `./dir16/${dir}/array.json`);
		const jsonPrimitive = await import(/* webpackExports: ["default"] */ `./dir16/${dir}/primitive.json`);
		expect(jsonObject.default).toEqual({ a: 1 });
		expect(jsonObject.a).toEqual(1);
		expect(jsonArray.default).toEqual(["a"]);
		expect(jsonArray[0]).toBe("a");
		expect(jsonPrimitive.default).toBe("a");
		const file = "a";
		const a = await import(/* webpackExports: ["default"] */`./dir16/${file}`);
		expect(a.default).toEqual({ a: 1, b: 2 });
		expect(a.a).toBe(1);
		expect(a.b).toBe(2);
	})
}

function testChunkLoading(load, expectedSyncInitial, expectedSyncRequested) {
	var sync = false;
	var syncInitial = true;
	var p = Promise.all([load("a"), load("b")]).then(function () {
		expect(syncInitial).toBe(expectedSyncInitial);
		sync = true;
		var p = Promise.all([
			load("a").then(function (a) {
				expect(a).toEqual(
					nsObj({
						default: "a"
					})
				);
				expect(sync).toBe(true);
			}),
			load("c").then(function (c) {
				expect(c).toEqual(
					nsObj({
						default: "c"
					})
				);
				expect(sync).toBe(expectedSyncRequested);
			})
		]);
		Promise.resolve()
			.then(function () {})
			.then(function () {})
			.then(function () {})
			.then(function () {
				sync = false;
			});
		return p;
	});
	Promise.resolve()
		.then(function () {})
		.then(function () {})
		.then(function () {})
		.then(function () {
			syncInitial = false;
		});
	return p;
}
