Skip to content

Commit 55bbf5a

Browse files
committed
feat: add vite support
1 parent e951554 commit 55bbf5a

3 files changed

Lines changed: 173 additions & 63 deletions

File tree

src/eslint/configs/imports.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ export function imports({
6565
"knip.*",
6666
"next.config.*",
6767
"commitlint.config.*",
68+
"vite.config.*",
6869
".releaserc.*",
6970
"vitest.config.*",
7071
"postcss.config.*",

tests/integration.test.ts

Lines changed: 118 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -14,48 +14,46 @@ describe("Next.js Integration Tests", () => {
1414
env?.cleanup();
1515
});
1616

17-
describe("Fresh Next.js App Setup", () => {
18-
it("should create a Next.js app and install @solvro/config", async () => {
19-
const appPath = await env.createNextjsApp("test-app");
17+
it("should create a Next.js app and install @solvro/config", async () => {
18+
const appPath = await env.createNextjsApp("test-app");
2019

21-
await env.installSolvroConfig(appPath);
22-
await env.initGitRepo(appPath);
20+
await env.installSolvroConfig(appPath);
21+
await env.initGitRepo(appPath);
2322

24-
const output = await env.runSolvroConfig(appPath, ["--all", "--force"]);
25-
expect(output).toContain("Configuration completed successfully");
23+
const output = await env.runSolvroConfig(appPath, ["--all", "--force"]);
24+
expect(output).toContain("Configuration completed successfully");
2625

27-
// Format code first
28-
const prettierResult = await env.runPrettier(appPath, true);
29-
expect(prettierResult.success).toBe(true);
26+
// Format code first
27+
const prettierResult = await env.runPrettier(appPath, true);
28+
expect(prettierResult.success).toBe(true);
3029

31-
// Then run ESLint
32-
const eslintResult = await env.runESLint(appPath);
33-
expect(eslintResult.success).toBe(true);
30+
// Then run ESLint
31+
const eslintResult = await env.runESLint(appPath);
32+
expect(eslintResult.success).toBe(true);
3433

35-
// Verify ESLint config
36-
expect(env.fileExists(appPath, "eslint.config.js")).toBe(true);
34+
// Verify ESLint config
35+
expect(env.fileExists(appPath, "eslint.config.js")).toBe(true);
3736

38-
// Verify Prettier config
39-
expect(env.hasPackageJsonField(appPath, "prettier")).toBe(true);
37+
// Verify Prettier config
38+
expect(env.hasPackageJsonField(appPath, "prettier")).toBe(true);
4039

41-
// Verify the app was created
42-
expect(env.fileExists(appPath, "package.json")).toBe(true);
43-
expect(env.fileExists(appPath, "next.config.ts")).toBe(true);
40+
// Verify the app was created
41+
expect(env.fileExists(appPath, "package.json")).toBe(true);
42+
expect(env.fileExists(appPath, "next.config.ts")).toBe(true);
4443

45-
// Verify @solvro/config is installed
46-
const packageJson = env.readFile(appPath, "package.json");
47-
expect(packageJson).toContain("@solvro/config");
44+
// Verify @solvro/config is installed
45+
const packageJson = env.readFile(appPath, "package.json");
46+
expect(packageJson).toContain("@solvro/config");
4847

49-
const buildResult = await env.buildNextjsApp(appPath);
50-
expect(buildResult.success).toBe(true);
51-
expect(buildResult.output).toContain("Compiled successfully");
48+
const buildResult = await env.buildNextjsApp(appPath);
49+
expect(buildResult.success).toBe(true);
50+
expect(buildResult.output).toContain("Compiled successfully");
5251

53-
const eslintConfig = env.readFile(appPath, "eslint.config.js");
54-
expect(eslintConfig).toContain("@solvro/config/eslint");
55-
expect(eslintConfig).toContain("solvro()");
52+
const eslintConfig = env.readFile(appPath, "eslint.config.js");
53+
expect(eslintConfig).toContain("@solvro/config/eslint");
54+
expect(eslintConfig).toContain("solvro()");
5655

57-
expect(packageJson).toContain('"prettier": "@solvro/config/prettier"');
58-
});
56+
expect(packageJson).toContain('"prettier": "@solvro/config/prettier"');
5957
});
6058
});
6159

@@ -71,48 +69,105 @@ describe("NestJS Integration Tests", () => {
7169
env?.cleanup();
7270
});
7371

74-
describe("Fresh NestJS App Setup", () => {
75-
it("should create a NestJS app and install @solvro/config", async () => {
76-
const appPath = await env.createNestjsApp("test-app");
72+
it("should create a NestJS app and install @solvro/config", async () => {
73+
const appPath = await env.createNestjsApp("test-app");
7774

78-
await env.installSolvroConfig(appPath);
79-
await env.initGitRepo(appPath);
75+
await env.installSolvroConfig(appPath);
76+
await env.initGitRepo(appPath);
8077

81-
const output = await env.runSolvroConfig(appPath, ["--all", "--force"]);
82-
expect(output).toContain("Configuration completed successfully");
78+
const output = await env.runSolvroConfig(appPath, ["--all", "--force"]);
79+
expect(output).toContain("Configuration completed successfully");
8380

84-
// Format code first
85-
const prettierResult = await env.runPrettier(appPath, true);
86-
expect(prettierResult.success).toBe(true);
81+
// Format code first
82+
const prettierResult = await env.runPrettier(appPath, true);
83+
expect(prettierResult.success).toBe(true);
8784

88-
// Then run ESLint
89-
const eslintResult = await env.runESLint(appPath);
90-
expect(eslintResult.success).toBe(true);
85+
// Then run ESLint
86+
const eslintResult = await env.runESLint(appPath);
87+
expect(eslintResult.success).toBe(true);
9188

92-
// Verify ESLint config
93-
expect(env.fileExists(appPath, "eslint.config.mjs")).toBe(true);
89+
// Verify ESLint config
90+
expect(env.fileExists(appPath, "eslint.config.mjs")).toBe(true);
9491

95-
// Verify Prettier config
96-
expect(env.hasPackageJsonField(appPath, "prettier")).toBe(true);
92+
// Verify Prettier config
93+
expect(env.hasPackageJsonField(appPath, "prettier")).toBe(true);
9794

98-
// Verify the app was created
99-
expect(env.fileExists(appPath, "package.json")).toBe(true);
100-
expect(env.fileExists(appPath, "tsconfig.json")).toBe(true);
95+
// Verify the app was created
96+
expect(env.fileExists(appPath, "package.json")).toBe(true);
97+
expect(env.fileExists(appPath, "tsconfig.json")).toBe(true);
10198

102-
// Verify @solvro/config is installed
103-
const packageJson = env.readFile(appPath, "package.json");
104-
expect(packageJson).toContain("@solvro/config");
99+
// Verify @solvro/config is installed
100+
const packageJson = env.readFile(appPath, "package.json");
101+
expect(packageJson).toContain("@solvro/config");
105102

106-
// Build the app
107-
const buildResult = await env.buildNestjsApp(appPath);
108-
expect(buildResult.success).toBe(true);
109-
expect(env.fileExists(appPath, "dist/main.js")).toBe(true);
103+
// Build the app
104+
const buildResult = await env.buildNestjsApp(appPath);
105+
expect(buildResult.success).toBe(true);
106+
expect(env.fileExists(appPath, "dist/main.js")).toBe(true);
110107

111-
const eslintConfig = env.readFile(appPath, "eslint.config.mjs");
112-
expect(eslintConfig).toContain("@solvro/config/eslint");
113-
expect(eslintConfig).toContain("solvro()");
108+
const eslintConfig = env.readFile(appPath, "eslint.config.mjs");
109+
expect(eslintConfig).toContain("@solvro/config/eslint");
110+
expect(eslintConfig).toContain("solvro()");
114111

115-
expect(packageJson).toContain('"prettier": "@solvro/config/prettier"');
116-
});
112+
expect(packageJson).toContain('"prettier": "@solvro/config/prettier"');
113+
});
114+
});
115+
116+
describe("Vite Integration Tests", () => {
117+
let env: TestEnvironment;
118+
119+
beforeAll(async () => {
120+
env = new TestEnvironment("vite-integration");
121+
await env.setup();
122+
});
123+
124+
afterAll(() => {
125+
env?.cleanup();
126+
});
127+
128+
it("should create a Vite React app and install @solvro/config", async () => {
129+
const appPath = await env.createViteApp("test-app-react", "react-ts");
130+
131+
await env.installSolvroConfig(appPath);
132+
await env.initGitRepo(appPath);
133+
134+
const output = await env.runSolvroConfig(appPath, ["--all", "--force"]);
135+
expect(output).toContain("Configuration completed successfully");
136+
137+
// Format code first
138+
const prettierResult = await env.runPrettier(appPath, true);
139+
expect(prettierResult.success).toBe(true);
140+
141+
// Then run ESLint
142+
const eslintResult = await env.runESLint(appPath);
143+
144+
// Vite default template don't play well with eslint config
145+
expect(eslintResult.output).toContain("Filename is not in kebab case");
146+
147+
// Verify ESLint config
148+
expect(env.fileExists(appPath, "eslint.config.js")).toBe(true);
149+
150+
// Verify Prettier config
151+
expect(env.hasPackageJsonField(appPath, "prettier")).toBe(true);
152+
153+
// Verify the app was created
154+
expect(env.fileExists(appPath, "package.json")).toBe(true);
155+
expect(env.fileExists(appPath, "vite.config.ts")).toBe(true);
156+
expect(env.fileExists(appPath, "index.html")).toBe(true);
157+
expect(env.fileExists(appPath, "src/App.tsx")).toBe(true);
158+
159+
// Verify @solvro/config is installed
160+
const packageJson = env.readFile(appPath, "package.json");
161+
expect(packageJson).toContain("@solvro/config");
162+
163+
const buildResult = await env.buildViteApp(appPath);
164+
expect(buildResult.success).toBe(true);
165+
expect(buildResult.output).toContain("built in");
166+
167+
const eslintConfig = env.readFile(appPath, "eslint.config.js");
168+
expect(eslintConfig).toContain("@solvro/config/eslint");
169+
expect(eslintConfig).toContain("solvro()");
170+
171+
expect(packageJson).toContain('"prettier": "@solvro/config/prettier"');
117172
});
118173
});

tests/utils/test-environment.ts

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,35 @@ export class TestEnvironment {
173173
return appPath;
174174
}
175175

176+
/**
177+
* Create a Vite application using create-vite CLI.
178+
*/
179+
async createViteApp(appName: string, template = "react-ts"): Promise<string> {
180+
const appPath = join(this.testDir, appName);
181+
await execWithLogging(
182+
"npm",
183+
["create", "vite@latest", appName, "--", "--template", template],
184+
{
185+
cwd: this.testDir,
186+
timeout: 120_000, // 2 minutes for project creation
187+
},
188+
"create-vite",
189+
);
190+
191+
// Install dependencies
192+
await execWithLogging(
193+
"npm",
194+
["install"],
195+
{
196+
cwd: appPath,
197+
timeout: 120_000, // 2 minutes for dependency installation
198+
},
199+
"npm-install-deps",
200+
);
201+
202+
return appPath;
203+
}
204+
176205
async installSolvroConfig(appPath: string): Promise<void> {
177206
// Copy package to app directory
178207
await execWithLogging(
@@ -345,6 +374,31 @@ export class TestEnvironment {
345374
}
346375
}
347376

377+
/**
378+
* Build a Vite application by running its build script.
379+
*/
380+
async buildViteApp(
381+
appPath: string,
382+
): Promise<{ success: boolean; output: string }> {
383+
try {
384+
const { stdout, stderr } = await execWithLogging(
385+
"npm",
386+
["run", "build"],
387+
{
388+
cwd: appPath,
389+
timeout: 180_000, // 3 minutes for build
390+
},
391+
"vite-build",
392+
);
393+
return { success: true, output: stdout + stderr };
394+
} catch (error: any) {
395+
return {
396+
success: false,
397+
output: (error.stdout || "") + (error.stderr || ""),
398+
};
399+
}
400+
}
401+
348402
fileExists(appPath: string, filePath: string): boolean {
349403
return existsSync(join(appPath, filePath));
350404
}

0 commit comments

Comments
 (0)