@kcconfigs/vitest 0.0.1 → 0.1.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,114 @@
1
+ /** biome-ignore-all lint/complexity/useLiteralKeys: Conflict with ts(4111) */
2
+
3
+ import { describe, expect, test } from "vitest";
4
+ import { defineRoot } from "./defineRoot";
5
+
6
+ describe("defineRoot", () => {
7
+ test("should return a configuration object", () => {
8
+ const config = defineRoot();
9
+
10
+ expect(config).toBeDefined();
11
+ expect(typeof config).toBe("object");
12
+ });
13
+
14
+ test("should include base root configuration", () => {
15
+ const config = defineRoot();
16
+
17
+ expect(config.test).toBeDefined();
18
+ expect(config.test?.environment).toBe("node");
19
+ expect(config.test?.restoreMocks).toBe(true);
20
+ expect(config.test?.mockReset).toBe(true);
21
+ expect(config.test?.clearMocks).toBe(true);
22
+ });
23
+
24
+ test("should merge custom configuration", () => {
25
+ const config = defineRoot({
26
+ test: {
27
+ environment: "jsdom",
28
+ },
29
+ });
30
+
31
+ expect(config.test?.environment).toBe("jsdom");
32
+ });
33
+
34
+ test("should preserve base configuration when merging", () => {
35
+ const config = defineRoot({
36
+ test: {
37
+ environment: "jsdom",
38
+ },
39
+ });
40
+
41
+ expect(config.test?.restoreMocks).toBe(true);
42
+ expect(config.test?.mockReset).toBe(true);
43
+ });
44
+
45
+ test("should handle multiple configuration overrides", () => {
46
+ const config = defineRoot(
47
+ {
48
+ test: {
49
+ environment: "jsdom",
50
+ },
51
+ },
52
+ {
53
+ test: {
54
+ globals: true,
55
+ },
56
+ },
57
+ );
58
+
59
+ expect(config.test?.environment).toBe("jsdom");
60
+ expect(config.test?.globals).toBe(true);
61
+ expect(config.test?.restoreMocks).toBe(true);
62
+ });
63
+
64
+ test("should include coverage configuration", () => {
65
+ const config = defineRoot();
66
+
67
+ expect(config.test?.coverage).toBeDefined();
68
+ expect(config.test?.coverage?.enabled).toBe(true);
69
+ expect(config.test?.coverage?.provider).toBe("v8");
70
+ });
71
+
72
+ test("should include reporter configuration", () => {
73
+ const config = defineRoot();
74
+
75
+ expect(config.test?.reporters).toBeDefined();
76
+ expect(config.test?.reporters).toContain("default");
77
+ expect(config.test?.reporters).toContain("html");
78
+ expect(config.test?.reporters).toContain("junit");
79
+ });
80
+
81
+ test("should include output file configuration", () => {
82
+ const config = defineRoot();
83
+
84
+ expect(config.test?.outputFile).toBeDefined();
85
+ if (typeof config.test?.outputFile !== "string") {
86
+ expect(config.test?.outputFile?.["html"]).toContain(
87
+ "reports/test-results",
88
+ );
89
+ expect(config.test?.outputFile?.["junit"]).toContain(
90
+ "reports/test-results",
91
+ );
92
+ }
93
+ });
94
+
95
+ test("should handle undefined configuration", () => {
96
+ const config = defineRoot(undefined);
97
+
98
+ expect(config).toBeDefined();
99
+ expect(config.test?.environment).toBe("node");
100
+ });
101
+
102
+ test("should override coverage settings", () => {
103
+ const config = defineRoot({
104
+ test: {
105
+ coverage: {
106
+ enabled: false,
107
+ },
108
+ },
109
+ });
110
+
111
+ expect(config.test?.coverage?.enabled).toBe(false);
112
+ expect(config.test?.coverage?.provider).toBe("v8");
113
+ });
114
+ });
@@ -0,0 +1,16 @@
1
+ import { baseRootConfig } from "../constants";
2
+ import type { UserConfig } from "../models";
3
+ import { defineEmptyRoot } from "./defineEmptyRoot";
4
+
5
+ /**
6
+ * Defines the root Vitest configuration for the workspace.
7
+ * Merges the base root configuration with any provided user configuration.
8
+ *
9
+ * @param config - Optional user-provided Vitest configuration overrides
10
+ * @returns The merged root Vitest configuration
11
+ *
12
+ * @includeExample
13
+ */
14
+ export const defineRoot = (...config: Optional<UserConfig>[]): UserConfig => {
15
+ return defineEmptyRoot(baseRootConfig, ...config);
16
+ };
@@ -0,0 +1,126 @@
1
+ import { describe, expect, test } from "vitest";
2
+ import type { AnyConfig, UserConfig } from "../models";
3
+ import { mergeConfig } from "./mergeConfig";
4
+
5
+ describe("mergeConfig", () => {
6
+ test("should merge two simple configurations", () => {
7
+ const defaults: AnyConfig = { a: 1, b: 2 };
8
+ const addon: AnyConfig = { b: 3, c: 4 };
9
+
10
+ const result = mergeConfig(defaults, addon);
11
+
12
+ expect(result).toEqual({ a: 1, b: 3, c: 4 });
13
+ });
14
+
15
+ test("should merge multiple configurations", () => {
16
+ const defaults: AnyConfig = { a: 1, b: 2 };
17
+ const addon1: AnyConfig = { b: 3, c: 4 };
18
+ const addon2: AnyConfig = { c: 5, d: 6 };
19
+
20
+ const result = mergeConfig(defaults, addon1, addon2);
21
+
22
+ expect(result).toEqual({ a: 1, b: 3, c: 5, d: 6 });
23
+ });
24
+
25
+ test("should handle nested configurations", () => {
26
+ const defaults = { test: { timeout: 1000, retry: 0 } };
27
+ const addon = { test: { timeout: 5000 } };
28
+
29
+ const result = mergeConfig(defaults, addon);
30
+
31
+ expect(result).toEqual({
32
+ test: { timeout: 5000, retry: 0 },
33
+ });
34
+ });
35
+
36
+ test("should filter out undefined addons", () => {
37
+ const defaults: AnyConfig = { a: 1, b: 2 };
38
+ const addon1: AnyConfig = { b: 3 };
39
+ const addon2 = undefined;
40
+ const addon3: AnyConfig = { c: 4 };
41
+
42
+ const result = mergeConfig(defaults, addon1, addon2, addon3);
43
+
44
+ expect(result).toEqual({ a: 1, b: 3, c: 4 });
45
+ });
46
+
47
+ test("should filter out null addons", () => {
48
+ const defaults: AnyConfig = { a: 1, b: 2 };
49
+ const addon1: AnyConfig = { b: 3 };
50
+ const addon2 = null;
51
+ const addon3: AnyConfig = { c: 4 };
52
+
53
+ const result = mergeConfig(defaults, addon1, addon2, addon3);
54
+
55
+ expect(result).toEqual({ a: 1, b: 3, c: 4 });
56
+ });
57
+
58
+ test("should not mutate original configurations", () => {
59
+ const defaults: AnyConfig = { a: 1, b: 2 };
60
+ const addon: AnyConfig = { b: 3, c: 4 };
61
+
62
+ mergeConfig(defaults, addon);
63
+
64
+ expect(defaults).toEqual({ a: 1, b: 2 });
65
+ expect(addon).toEqual({ b: 3, c: 4 });
66
+ });
67
+
68
+ test("should handle empty defaults", () => {
69
+ const defaults: AnyConfig = {};
70
+ const addon: AnyConfig = { a: 1, b: 2 };
71
+
72
+ const result = mergeConfig(defaults, addon);
73
+
74
+ expect(result).toEqual({ a: 1, b: 2 });
75
+ });
76
+
77
+ test("should handle empty addons", () => {
78
+ const defaults: AnyConfig = { a: 1, b: 2 };
79
+
80
+ const result = mergeConfig(defaults);
81
+
82
+ expect(result).toEqual({ a: 1, b: 2 });
83
+ });
84
+
85
+ test("should merge array values", () => {
86
+ const defaults: UserConfig = { test: { reporters: ["default"] } };
87
+ const addon: AnyConfig = { test: { reporters: ["html", "junit"] } };
88
+
89
+ const result = mergeConfig<UserConfig>(defaults, addon);
90
+
91
+ expect(result.test?.reporters).toEqual(["default", "html", "junit"]);
92
+ });
93
+
94
+ test("should handle complex vitest configuration", () => {
95
+ const defaults: AnyConfig = {
96
+ test: {
97
+ environment: "node",
98
+ coverage: {
99
+ enabled: true,
100
+ provider: "v8",
101
+ },
102
+ },
103
+ };
104
+ const addon: AnyConfig = {
105
+ test: {
106
+ environment: "jsdom",
107
+ coverage: {
108
+ reporter: ["text", "html"],
109
+ },
110
+ },
111
+ };
112
+
113
+ const result = mergeConfig(defaults, addon);
114
+
115
+ expect(result).toEqual({
116
+ test: {
117
+ environment: "jsdom",
118
+ coverage: {
119
+ enabled: true,
120
+ provider: "v8",
121
+ reporter: ["text", "html"],
122
+ },
123
+ },
124
+ });
125
+ });
126
+ });
@@ -0,0 +1,29 @@
1
+ import { mergeConfig as _mergeConfig } from "vitest/config";
2
+ import type { AnyConfig } from "../models";
3
+
4
+ /**
5
+ * Merges multiple configuration objects into a single configuration.
6
+ * later addons taking precedence over earlier ones.
7
+ *
8
+ * No object will be mutated during this process.
9
+ *
10
+ * @template C - The configuration object type that extends a Record with string keys
11
+ * @param defaults - The default configuration object
12
+ * @param addons - One or more configuration objects to merge into the defaults
13
+ * @returns The merged configuration object
14
+ */
15
+ export const mergeConfig = <C extends AnyConfig>(
16
+ defaults: C,
17
+ ...addons: Optional<C>[]
18
+ ): C => {
19
+ return addons
20
+ .filter((addon) => addon !== undefined && addon !== null)
21
+ .reduce(
22
+ (merged, addon) =>
23
+ _mergeConfig(
24
+ merged as Record<string, unknown>,
25
+ addon as Record<string, unknown>,
26
+ ) as C,
27
+ defaults,
28
+ );
29
+ };
@@ -0,0 +1,81 @@
1
+ import { describe, expect, test } from "vitest";
2
+ import { setupMocks } from "./setupMocks";
3
+
4
+ describe("setupMocks", () => {
5
+ test("should return empty array when no flags are set", () => {
6
+ const result = setupMocks({
7
+ fs: undefined,
8
+ });
9
+
10
+ expect(result).toEqual([]);
11
+ });
12
+
13
+ test("should return fs mock path when fs flag is true", () => {
14
+ const result = setupMocks({ fs: true });
15
+
16
+ expect(result).toHaveLength(1);
17
+ expect(result[0]).toContain("__mocks__");
18
+ expect(result[0]).toContain("fs.ts");
19
+ });
20
+
21
+ test("should return fsPromises mock path when fsPromises flag is true", () => {
22
+ const result = setupMocks({ fsPromises: true });
23
+
24
+ expect(result).toHaveLength(1);
25
+ expect(result[0]).toContain("__mocks__");
26
+ expect(result[0]).toContain("fsPromises.ts");
27
+ });
28
+
29
+ test("should return process mock path when process flag is true", () => {
30
+ const result = setupMocks({ process: true });
31
+
32
+ expect(result).toHaveLength(1);
33
+ expect(result[0]).toContain("__mocks__");
34
+ expect(result[0]).toContain("process.ts");
35
+ });
36
+
37
+ test("should return os mock path when os flag is true", () => {
38
+ const result = setupMocks({ os: true, fs: undefined });
39
+
40
+ expect(result).toHaveLength(1);
41
+ expect(result[0]).toContain("__mocks__");
42
+ expect(result[0]).toContain("os.ts");
43
+ });
44
+
45
+ test("should return multiple mock paths when multiple flags are true", () => {
46
+ const result = setupMocks({ fs: true, process: true });
47
+
48
+ expect(result).toHaveLength(2);
49
+ expect(result.some((path) => path.includes("fs.ts"))).toBe(true);
50
+ expect(result.some((path) => path.includes("process.ts"))).toBe(true);
51
+ });
52
+
53
+ test("should return all mock paths when all flags are true", () => {
54
+ const result = setupMocks({
55
+ fs: true,
56
+ fsPromises: true,
57
+ process: true,
58
+ os: true,
59
+ });
60
+
61
+ expect(result).toHaveLength(4);
62
+ expect(result.some((path) => path.includes("fs.ts"))).toBe(true);
63
+ expect(result.some((path) => path.includes("fsPromises.ts"))).toBe(true);
64
+ expect(result.some((path) => path.includes("process.ts"))).toBe(true);
65
+ expect(result.some((path) => path.includes("os.ts"))).toBe(true);
66
+ });
67
+
68
+ test("should ignore flags that are not true", () => {
69
+ const result = setupMocks({ fs: true });
70
+
71
+ expect(result).toHaveLength(1);
72
+ expect(result[0]).toContain("fs.ts");
73
+ });
74
+
75
+ test("should resolve paths to __mocks__ directory", () => {
76
+ const result = setupMocks({ fs: true });
77
+
78
+ expect(result[0]).toContain("__mocks__");
79
+ expect(result[0]).toContain("fs.ts");
80
+ });
81
+ });
@@ -0,0 +1,22 @@
1
+ import { join } from "node:path";
2
+
3
+ export interface MockFlag {
4
+ fs?: true;
5
+ fsPromises?: true;
6
+ process?: true;
7
+ os?: true;
8
+ }
9
+
10
+ export type MockFlagKey = keyof MockFlag;
11
+
12
+ const resolvePath = (name: string) => {
13
+ // import.meta.dirname is resolved to `dist` directory
14
+ return join(import.meta.dirname, "..", "__mocks__", `${name}.ts`);
15
+ };
16
+
17
+ export const setupMocks = (flag: MockFlag): string[] => {
18
+ const keys = Object.keys(flag) as MockFlagKey[];
19
+ return keys
20
+ .map((key) => (flag[key] === true ? resolvePath(key) : undefined))
21
+ .filter((path) => path !== undefined);
22
+ };