baseguard 1.0.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.
Files changed (244) hide show
  1. package/.eslintrc.json +25 -0
  2. package/.prettierrc +8 -0
  3. package/README.md +94 -0
  4. package/bin/base.js +494 -0
  5. package/dist/ai/fix-manager.d.ts +67 -0
  6. package/dist/ai/fix-manager.d.ts.map +1 -0
  7. package/dist/ai/fix-manager.js +326 -0
  8. package/dist/ai/fix-manager.js.map +1 -0
  9. package/dist/ai/gemini-analyzer.d.ts +116 -0
  10. package/dist/ai/gemini-analyzer.d.ts.map +1 -0
  11. package/dist/ai/gemini-analyzer.js +572 -0
  12. package/dist/ai/gemini-analyzer.js.map +1 -0
  13. package/dist/ai/index.d.ts +4 -0
  14. package/dist/ai/index.d.ts.map +1 -0
  15. package/dist/ai/index.js +5 -0
  16. package/dist/ai/index.js.map +1 -0
  17. package/dist/ai/jules-implementer.d.ts +115 -0
  18. package/dist/ai/jules-implementer.d.ts.map +1 -0
  19. package/dist/ai/jules-implementer.js +387 -0
  20. package/dist/ai/jules-implementer.js.map +1 -0
  21. package/dist/commands/automation.d.ts +5 -0
  22. package/dist/commands/automation.d.ts.map +1 -0
  23. package/dist/commands/automation.js +305 -0
  24. package/dist/commands/automation.js.map +1 -0
  25. package/dist/commands/check.d.ts +9 -0
  26. package/dist/commands/check.d.ts.map +1 -0
  27. package/dist/commands/check.js +113 -0
  28. package/dist/commands/check.js.map +1 -0
  29. package/dist/commands/config.d.ts +11 -0
  30. package/dist/commands/config.d.ts.map +1 -0
  31. package/dist/commands/config.js +324 -0
  32. package/dist/commands/config.js.map +1 -0
  33. package/dist/commands/fix.d.ts +9 -0
  34. package/dist/commands/fix.d.ts.map +1 -0
  35. package/dist/commands/fix.js +207 -0
  36. package/dist/commands/fix.js.map +1 -0
  37. package/dist/commands/index.d.ts +6 -0
  38. package/dist/commands/index.d.ts.map +1 -0
  39. package/dist/commands/index.js +7 -0
  40. package/dist/commands/index.js.map +1 -0
  41. package/dist/commands/init.d.ts +9 -0
  42. package/dist/commands/init.d.ts.map +1 -0
  43. package/dist/commands/init.js +125 -0
  44. package/dist/commands/init.js.map +1 -0
  45. package/dist/core/api-key-manager.d.ts +83 -0
  46. package/dist/core/api-key-manager.d.ts.map +1 -0
  47. package/dist/core/api-key-manager.js +244 -0
  48. package/dist/core/api-key-manager.js.map +1 -0
  49. package/dist/core/baseguard.d.ts +46 -0
  50. package/dist/core/baseguard.d.ts.map +1 -0
  51. package/dist/core/baseguard.js +132 -0
  52. package/dist/core/baseguard.js.map +1 -0
  53. package/dist/core/baseline-checker.d.ts +63 -0
  54. package/dist/core/baseline-checker.d.ts.map +1 -0
  55. package/dist/core/baseline-checker.js +502 -0
  56. package/dist/core/baseline-checker.js.map +1 -0
  57. package/dist/core/cache-manager.d.ts +88 -0
  58. package/dist/core/cache-manager.d.ts.map +1 -0
  59. package/dist/core/cache-manager.js +213 -0
  60. package/dist/core/cache-manager.js.map +1 -0
  61. package/dist/core/configuration.d.ts +140 -0
  62. package/dist/core/configuration.d.ts.map +1 -0
  63. package/dist/core/configuration.js +474 -0
  64. package/dist/core/configuration.js.map +1 -0
  65. package/dist/core/directory-filter.d.ts +90 -0
  66. package/dist/core/directory-filter.d.ts.map +1 -0
  67. package/dist/core/directory-filter.js +319 -0
  68. package/dist/core/directory-filter.js.map +1 -0
  69. package/dist/core/error-handler.d.ts +110 -0
  70. package/dist/core/error-handler.d.ts.map +1 -0
  71. package/dist/core/error-handler.js +392 -0
  72. package/dist/core/error-handler.js.map +1 -0
  73. package/dist/core/file-processor.d.ts +80 -0
  74. package/dist/core/file-processor.d.ts.map +1 -0
  75. package/dist/core/file-processor.js +259 -0
  76. package/dist/core/file-processor.js.map +1 -0
  77. package/dist/core/gitignore-manager.d.ts +44 -0
  78. package/dist/core/gitignore-manager.d.ts.map +1 -0
  79. package/dist/core/gitignore-manager.js +147 -0
  80. package/dist/core/gitignore-manager.js.map +1 -0
  81. package/dist/core/index.d.ts +13 -0
  82. package/dist/core/index.d.ts.map +1 -0
  83. package/dist/core/index.js +13 -0
  84. package/dist/core/index.js.map +1 -0
  85. package/dist/core/lazy-loader.d.ts +68 -0
  86. package/dist/core/lazy-loader.d.ts.map +1 -0
  87. package/dist/core/lazy-loader.js +260 -0
  88. package/dist/core/lazy-loader.js.map +1 -0
  89. package/dist/core/memory-manager.d.ts +1 -0
  90. package/dist/core/memory-manager.d.ts.map +1 -0
  91. package/dist/core/memory-manager.js +2 -0
  92. package/dist/core/memory-manager.js.map +1 -0
  93. package/dist/core/startup-optimizer.d.ts +45 -0
  94. package/dist/core/startup-optimizer.d.ts.map +1 -0
  95. package/dist/core/startup-optimizer.js +140 -0
  96. package/dist/core/startup-optimizer.js.map +1 -0
  97. package/dist/git/automation-engine.d.ts +58 -0
  98. package/dist/git/automation-engine.d.ts.map +1 -0
  99. package/dist/git/automation-engine.js +318 -0
  100. package/dist/git/automation-engine.js.map +1 -0
  101. package/dist/git/github-manager.d.ts +71 -0
  102. package/dist/git/github-manager.d.ts.map +1 -0
  103. package/dist/git/github-manager.js +226 -0
  104. package/dist/git/github-manager.js.map +1 -0
  105. package/dist/git/hook-manager.d.ts +43 -0
  106. package/dist/git/hook-manager.d.ts.map +1 -0
  107. package/dist/git/hook-manager.js +191 -0
  108. package/dist/git/hook-manager.js.map +1 -0
  109. package/dist/git/index.d.ts +4 -0
  110. package/dist/git/index.d.ts.map +1 -0
  111. package/dist/git/index.js +5 -0
  112. package/dist/git/index.js.map +1 -0
  113. package/dist/index.d.ts +8 -0
  114. package/dist/index.d.ts.map +1 -0
  115. package/dist/index.js +9 -0
  116. package/dist/index.js.map +1 -0
  117. package/dist/parsers/feature-validator.d.ts +60 -0
  118. package/dist/parsers/feature-validator.d.ts.map +1 -0
  119. package/dist/parsers/feature-validator.js +483 -0
  120. package/dist/parsers/feature-validator.js.map +1 -0
  121. package/dist/parsers/index.d.ts +8 -0
  122. package/dist/parsers/index.d.ts.map +1 -0
  123. package/dist/parsers/index.js +9 -0
  124. package/dist/parsers/index.js.map +1 -0
  125. package/dist/parsers/parser-manager.d.ts +103 -0
  126. package/dist/parsers/parser-manager.d.ts.map +1 -0
  127. package/dist/parsers/parser-manager.js +321 -0
  128. package/dist/parsers/parser-manager.js.map +1 -0
  129. package/dist/parsers/parser.d.ts +23 -0
  130. package/dist/parsers/parser.d.ts.map +1 -0
  131. package/dist/parsers/parser.js +6 -0
  132. package/dist/parsers/parser.js.map +1 -0
  133. package/dist/parsers/react-parser.d.ts +22 -0
  134. package/dist/parsers/react-parser.d.ts.map +1 -0
  135. package/dist/parsers/react-parser.js +307 -0
  136. package/dist/parsers/react-parser.js.map +1 -0
  137. package/dist/parsers/svelte-parser.d.ts +33 -0
  138. package/dist/parsers/svelte-parser.d.ts.map +1 -0
  139. package/dist/parsers/svelte-parser.js +408 -0
  140. package/dist/parsers/svelte-parser.js.map +1 -0
  141. package/dist/parsers/vanilla-parser.d.ts +31 -0
  142. package/dist/parsers/vanilla-parser.d.ts.map +1 -0
  143. package/dist/parsers/vanilla-parser.js +590 -0
  144. package/dist/parsers/vanilla-parser.js.map +1 -0
  145. package/dist/parsers/vue-parser.d.ts +9 -0
  146. package/dist/parsers/vue-parser.d.ts.map +1 -0
  147. package/dist/parsers/vue-parser.js +16 -0
  148. package/dist/parsers/vue-parser.js.map +1 -0
  149. package/dist/terminal-header.d.ts +12 -0
  150. package/dist/terminal-header.js +45 -0
  151. package/dist/types/index.d.ts +83 -0
  152. package/dist/types/index.d.ts.map +1 -0
  153. package/dist/types/index.js +5 -0
  154. package/dist/types/index.js.map +1 -0
  155. package/dist/ui/components.d.ts +133 -0
  156. package/dist/ui/components.d.ts.map +1 -0
  157. package/dist/ui/components.js +482 -0
  158. package/dist/ui/components.js.map +1 -0
  159. package/dist/ui/help.d.ts +11 -0
  160. package/dist/ui/help.d.ts.map +1 -0
  161. package/dist/ui/help.js +161 -0
  162. package/dist/ui/help.js.map +1 -0
  163. package/dist/ui/index.d.ts +5 -0
  164. package/dist/ui/index.d.ts.map +1 -0
  165. package/dist/ui/index.js +5 -0
  166. package/dist/ui/index.js.map +1 -0
  167. package/dist/ui/prompts.d.ts +63 -0
  168. package/dist/ui/prompts.d.ts.map +1 -0
  169. package/dist/ui/prompts.js +611 -0
  170. package/dist/ui/prompts.js.map +1 -0
  171. package/dist/ui/terminal-header.d.ts +13 -0
  172. package/dist/ui/terminal-header.d.ts.map +1 -0
  173. package/dist/ui/terminal-header.js +46 -0
  174. package/dist/ui/terminal-header.js.map +1 -0
  175. package/package.json +80 -0
  176. package/src/ai/__tests__/gemini-analyzer.test.ts +181 -0
  177. package/src/ai/fix-manager.ts +362 -0
  178. package/src/ai/gemini-analyzer.ts +671 -0
  179. package/src/ai/index.ts +4 -0
  180. package/src/ai/jules-implementer.ts +459 -0
  181. package/src/commands/automation.ts +344 -0
  182. package/src/commands/check.ts +299 -0
  183. package/src/commands/config.ts +365 -0
  184. package/src/commands/fix.ts +234 -0
  185. package/src/commands/index.ts +6 -0
  186. package/src/commands/init.ts +142 -0
  187. package/src/commands/status.ts +0 -0
  188. package/src/core/api-key-manager.ts +298 -0
  189. package/src/core/baseguard.ts +742 -0
  190. package/src/core/baseline-checker.ts +563 -0
  191. package/src/core/cache-manager.ts +270 -0
  192. package/src/core/configuration-recovery.ts +676 -0
  193. package/src/core/configuration.ts +559 -0
  194. package/src/core/debug-logger.ts +590 -0
  195. package/src/core/directory-filter.ts +421 -0
  196. package/src/core/error-handler.ts +517 -0
  197. package/src/core/file-processor.ts +331 -0
  198. package/src/core/gitignore-manager.ts +169 -0
  199. package/src/core/graceful-degradation-manager.ts +596 -0
  200. package/src/core/index.ts +13 -0
  201. package/src/core/lazy-loader.ts +307 -0
  202. package/src/core/logger.ts +0 -0
  203. package/src/core/memory-manager.ts +294 -0
  204. package/src/core/startup-optimizer.ts +173 -0
  205. package/src/core/system-error-handler.ts +746 -0
  206. package/src/git/automation-engine.ts +361 -0
  207. package/src/git/github-manager.ts +260 -0
  208. package/src/git/hook-manager.ts +210 -0
  209. package/src/git/index.ts +4 -0
  210. package/src/index.ts +8 -0
  211. package/src/parsers/feature-validator.ts +559 -0
  212. package/src/parsers/index.ts +8 -0
  213. package/src/parsers/parser-manager.ts +419 -0
  214. package/src/parsers/parser.ts +26 -0
  215. package/src/parsers/react-parser-optimized.ts +161 -0
  216. package/src/parsers/react-parser.ts +359 -0
  217. package/src/parsers/svelte-parser.ts +506 -0
  218. package/src/parsers/vanilla-parser.ts +682 -0
  219. package/src/parsers/vue-parser.ts +472 -0
  220. package/src/types/index.ts +92 -0
  221. package/src/ui/components.ts +567 -0
  222. package/src/ui/help.ts +193 -0
  223. package/src/ui/index.ts +4 -0
  224. package/src/ui/prompts.ts +688 -0
  225. package/src/ui/terminal-header.ts +59 -0
  226. package/test-config-commands.js +56 -0
  227. package/test-header-simple.js +33 -0
  228. package/test-terminal-header.js +12 -0
  229. package/test-ui.js +29 -0
  230. package/tests/e2e/baseguard.e2e.test.ts +516 -0
  231. package/tests/e2e/cross-platform.e2e.test.ts +420 -0
  232. package/tests/e2e/git-integration.e2e.test.ts +487 -0
  233. package/tests/fixtures/react-project/package.json +14 -0
  234. package/tests/fixtures/react-project/src/App.css +76 -0
  235. package/tests/fixtures/react-project/src/App.tsx +77 -0
  236. package/tests/fixtures/svelte-project/package.json +11 -0
  237. package/tests/fixtures/svelte-project/src/App.svelte +369 -0
  238. package/tests/fixtures/vanilla-project/index.html +76 -0
  239. package/tests/fixtures/vanilla-project/script.js +331 -0
  240. package/tests/fixtures/vanilla-project/styles.css +359 -0
  241. package/tests/fixtures/vue-project/package.json +12 -0
  242. package/tests/fixtures/vue-project/src/App.vue +216 -0
  243. package/tsconfig.json +36 -0
  244. package/vitest.config.ts +10 -0
@@ -0,0 +1,516 @@
1
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
2
+ import { execSync, spawn } from 'child_process';
3
+ import { promises as fs } from 'fs';
4
+ import path from 'path';
5
+ import { fileURLToPath } from 'url';
6
+
7
+ const __filename = fileURLToPath(import.meta.url);
8
+ const __dirname = path.dirname(__filename);
9
+
10
+ // Test configuration
11
+ const TEST_TIMEOUT = 30000; // 30 seconds for E2E tests
12
+ const FIXTURES_DIR = path.join(__dirname, '../fixtures');
13
+ const TEMP_DIR = path.join(__dirname, '../temp');
14
+
15
+ // Helper function to run BaseGuard commands
16
+ async function runBaseGuard(args: string[], cwd: string = TEMP_DIR): Promise<{ stdout: string; stderr: string; exitCode: number }> {
17
+ return new Promise((resolve) => {
18
+ const basePath = path.join(__dirname, '../../bin/base.js');
19
+ const child = spawn('node', [basePath, ...args], {
20
+ cwd,
21
+ stdio: 'pipe',
22
+ env: { ...process.env, NODE_ENV: 'test' }
23
+ });
24
+
25
+ let stdout = '';
26
+ let stderr = '';
27
+
28
+ child.stdout?.on('data', (data) => {
29
+ stdout += data.toString();
30
+ });
31
+
32
+ child.stderr?.on('data', (data) => {
33
+ stderr += data.toString();
34
+ });
35
+
36
+ child.on('close', (code) => {
37
+ resolve({
38
+ stdout,
39
+ stderr,
40
+ exitCode: code || 0
41
+ });
42
+ });
43
+
44
+ // Kill process after timeout
45
+ setTimeout(() => {
46
+ child.kill();
47
+ resolve({
48
+ stdout,
49
+ stderr,
50
+ exitCode: 1
51
+ });
52
+ }, TEST_TIMEOUT);
53
+ });
54
+ }
55
+
56
+ // Helper function to copy fixture to temp directory
57
+ async function copyFixture(fixtureName: string, tempName: string): Promise<string> {
58
+ const sourcePath = path.join(FIXTURES_DIR, fixtureName);
59
+ const destPath = path.join(TEMP_DIR, tempName);
60
+
61
+ await fs.mkdir(destPath, { recursive: true });
62
+ await copyDirectory(sourcePath, destPath);
63
+
64
+ return destPath;
65
+ }
66
+
67
+ // Helper function to recursively copy directory
68
+ async function copyDirectory(src: string, dest: string): Promise<void> {
69
+ const entries = await fs.readdir(src, { withFileTypes: true });
70
+
71
+ for (const entry of entries) {
72
+ const srcPath = path.join(src, entry.name);
73
+ const destPath = path.join(dest, entry.name);
74
+
75
+ if (entry.isDirectory()) {
76
+ await fs.mkdir(destPath, { recursive: true });
77
+ await copyDirectory(srcPath, destPath);
78
+ } else {
79
+ await fs.copyFile(srcPath, destPath);
80
+ }
81
+ }
82
+ }
83
+
84
+ // Helper function to create test configuration
85
+ async function createTestConfig(projectPath: string, config: any): Promise<void> {
86
+ const configPath = path.join(projectPath, '.baseguardrc.json');
87
+ await fs.writeFile(configPath, JSON.stringify(config, null, 2));
88
+ }
89
+
90
+ describe('BaseGuard End-to-End Tests', () => {
91
+ beforeEach(async () => {
92
+ // Clean up temp directory
93
+ try {
94
+ await fs.rm(TEMP_DIR, { recursive: true, force: true });
95
+ } catch (error) {
96
+ // Directory might not exist
97
+ }
98
+ await fs.mkdir(TEMP_DIR, { recursive: true });
99
+ });
100
+
101
+ afterEach(async () => {
102
+ // Clean up temp directory after each test
103
+ try {
104
+ await fs.rm(TEMP_DIR, { recursive: true, force: true });
105
+ } catch (error) {
106
+ // Ignore cleanup errors
107
+ }
108
+ });
109
+
110
+ describe('React Project Testing', () => {
111
+ it('should detect compatibility violations in React project', async () => {
112
+ const projectPath = await copyFixture('react-project', 'react-test');
113
+
114
+ // Create test configuration targeting older browsers
115
+ await createTestConfig(projectPath, {
116
+ version: '1.0.0',
117
+ targets: [
118
+ { browser: 'safari', minVersion: '15' },
119
+ { browser: 'chrome', minVersion: '90' }
120
+ ],
121
+ apiKeys: {
122
+ jules: null,
123
+ gemini: null
124
+ },
125
+ automation: {
126
+ enabled: false,
127
+ trigger: 'pre-commit',
128
+ autoAnalyze: false,
129
+ autoFix: false,
130
+ blockCommit: true
131
+ }
132
+ });
133
+
134
+ const result = await runBaseGuard(['check', '--strict'], projectPath);
135
+
136
+ // Should find violations
137
+ expect(result.exitCode).toBe(1);
138
+ expect(result.stdout).toContain('compatibility violations found');
139
+
140
+ // Should detect specific modern features
141
+ expect(result.stdout).toContain('container-type');
142
+ expect(result.stdout).toContain('dialog');
143
+ expect(result.stdout).toContain('structuredClone');
144
+ expect(result.stdout).toContain('ResizeObserver');
145
+
146
+ // Should show file locations
147
+ expect(result.stdout).toContain('App.tsx');
148
+ expect(result.stdout).toContain('App.css');
149
+ }, TEST_TIMEOUT);
150
+
151
+ it('should pass when targeting modern browsers', async () => {
152
+ const projectPath = await copyFixture('react-project', 'react-modern');
153
+
154
+ // Create configuration targeting modern browsers
155
+ await createTestConfig(projectPath, {
156
+ version: '1.0.0',
157
+ targets: [
158
+ { browser: 'chrome', minVersion: 'baseline' },
159
+ { browser: 'safari', minVersion: 'baseline' },
160
+ { browser: 'firefox', minVersion: 'baseline' }
161
+ ],
162
+ apiKeys: {
163
+ jules: null,
164
+ gemini: null
165
+ }
166
+ });
167
+
168
+ const result = await runBaseGuard(['check'], projectPath);
169
+
170
+ // Should pass with baseline targets
171
+ expect(result.exitCode).toBe(0);
172
+ expect(result.stdout).toContain('No compatibility issues found');
173
+ }, TEST_TIMEOUT);
174
+ });
175
+
176
+ describe('Vue Project Testing', () => {
177
+ it('should detect compatibility violations in Vue project', async () => {
178
+ const projectPath = await copyFixture('vue-project', 'vue-test');
179
+
180
+ await createTestConfig(projectPath, {
181
+ version: '1.0.0',
182
+ targets: [
183
+ { browser: 'safari', minVersion: '14' },
184
+ { browser: 'firefox', minVersion: '85' }
185
+ ]
186
+ });
187
+
188
+ const result = await runBaseGuard(['check', '--strict'], projectPath);
189
+
190
+ expect(result.exitCode).toBe(1);
191
+ expect(result.stdout).toContain('compatibility violations found');
192
+
193
+ // Should detect Vue-specific extractions
194
+ expect(result.stdout).toContain('container-type');
195
+ expect(result.stdout).toContain('App.vue');
196
+
197
+ // Should ignore Vue-specific syntax
198
+ expect(result.stdout).not.toContain('@click');
199
+ expect(result.stdout).not.toContain('v-if');
200
+ }, TEST_TIMEOUT);
201
+
202
+ it('should extract web platform features from Vue SFC', async () => {
203
+ const projectPath = await copyFixture('vue-project', 'vue-extraction');
204
+
205
+ await createTestConfig(projectPath, {
206
+ version: '1.0.0',
207
+ targets: [{ browser: 'safari', minVersion: '15' }]
208
+ });
209
+
210
+ const result = await runBaseGuard(['check'], projectPath);
211
+
212
+ // Should extract from all SFC sections
213
+ expect(result.stdout).toContain('ResizeObserver'); // From script
214
+ expect(result.stdout).toContain('container-type'); // From style
215
+ expect(result.stdout).toContain('dialog'); // From template
216
+ }, TEST_TIMEOUT);
217
+ });
218
+
219
+ describe('Svelte Project Testing', () => {
220
+ it('should detect compatibility violations in Svelte project', async () => {
221
+ const projectPath = await copyFixture('svelte-project', 'svelte-test');
222
+
223
+ await createTestConfig(projectPath, {
224
+ version: '1.0.0',
225
+ targets: [
226
+ { browser: 'safari', minVersion: '14' },
227
+ { browser: 'chrome', minVersion: '88' }
228
+ ]
229
+ });
230
+
231
+ const result = await runBaseGuard(['check', '--strict'], projectPath);
232
+
233
+ expect(result.exitCode).toBe(1);
234
+ expect(result.stdout).toContain('compatibility violations found');
235
+
236
+ // Should detect Svelte-specific extractions
237
+ expect(result.stdout).toContain('App.svelte');
238
+ expect(result.stdout).toContain('OffscreenCanvas');
239
+ expect(result.stdout).toContain('backdrop-filter');
240
+
241
+ // Should ignore Svelte-specific syntax
242
+ expect(result.stdout).not.toContain('bind:this');
243
+ expect(result.stdout).not.toContain('on:click');
244
+ }, TEST_TIMEOUT);
245
+
246
+ it('should handle complex Svelte features', async () => {
247
+ const projectPath = await copyFixture('svelte-project', 'svelte-complex');
248
+
249
+ await createTestConfig(projectPath, {
250
+ version: '1.0.0',
251
+ targets: [{ browser: 'safari', minVersion: '15' }]
252
+ });
253
+
254
+ const result = await runBaseGuard(['check'], projectPath);
255
+
256
+ // Should extract modern web APIs
257
+ expect(result.stdout).toContain('WebGL2RenderingContext');
258
+ expect(result.stdout).toContain('serviceWorker');
259
+ expect(result.stdout).toContain('caches');
260
+ }, TEST_TIMEOUT);
261
+ });
262
+
263
+ describe('Vanilla Project Testing', () => {
264
+ it('should detect all web platform features in vanilla project', async () => {
265
+ const projectPath = await copyFixture('vanilla-project', 'vanilla-test');
266
+
267
+ await createTestConfig(projectPath, {
268
+ version: '1.0.0',
269
+ targets: [
270
+ { browser: 'safari', minVersion: '14' },
271
+ { browser: 'firefox', minVersion: '80' }
272
+ ]
273
+ });
274
+
275
+ const result = await runBaseGuard(['check', '--strict'], projectPath);
276
+
277
+ expect(result.exitCode).toBe(1);
278
+ expect(result.stdout).toContain('compatibility violations found');
279
+
280
+ // Should detect features from all file types
281
+ expect(result.stdout).toContain('index.html');
282
+ expect(result.stdout).toContain('styles.css');
283
+ expect(result.stdout).toContain('script.js');
284
+
285
+ // Should detect comprehensive web platform features
286
+ expect(result.stdout).toContain('container-type'); // CSS
287
+ expect(result.stdout).toContain('dialog'); // HTML
288
+ expect(result.stdout).toContain('structuredClone'); // JavaScript
289
+ expect(result.stdout).toContain('color-mix'); // CSS function
290
+ expect(result.stdout).toContain('OffscreenCanvas'); // Canvas API
291
+ }, TEST_TIMEOUT);
292
+
293
+ it('should handle all modern CSS features', async () => {
294
+ const projectPath = await copyFixture('vanilla-project', 'vanilla-css');
295
+
296
+ await createTestConfig(projectPath, {
297
+ version: '1.0.0',
298
+ targets: [{ browser: 'safari', minVersion: '14' }]
299
+ });
300
+
301
+ const result = await runBaseGuard(['check'], projectPath);
302
+
303
+ // Should detect advanced CSS features
304
+ expect(result.stdout).toContain('backdrop-filter');
305
+ expect(result.stdout).toContain('aspect-ratio');
306
+ expect(result.stdout).toContain(':has');
307
+ expect(result.stdout).toContain('color-scheme');
308
+ expect(result.stdout).toContain('accent-color');
309
+ }, TEST_TIMEOUT);
310
+ });
311
+
312
+ describe('Cross-Framework Testing', () => {
313
+ it('should handle mixed framework project', async () => {
314
+ // Create a project with multiple frameworks
315
+ const projectPath = path.join(TEMP_DIR, 'mixed-project');
316
+ await fs.mkdir(projectPath, { recursive: true });
317
+
318
+ // Copy files from different frameworks
319
+ await fs.copyFile(
320
+ path.join(FIXTURES_DIR, 'react-project/src/App.tsx'),
321
+ path.join(projectPath, 'react-component.tsx')
322
+ );
323
+ await fs.copyFile(
324
+ path.join(FIXTURES_DIR, 'vue-project/src/App.vue'),
325
+ path.join(projectPath, 'vue-component.vue')
326
+ );
327
+ await fs.copyFile(
328
+ path.join(FIXTURES_DIR, 'svelte-project/src/App.svelte'),
329
+ path.join(projectPath, 'svelte-component.svelte')
330
+ );
331
+ await fs.copyFile(
332
+ path.join(FIXTURES_DIR, 'vanilla-project/script.js'),
333
+ path.join(projectPath, 'vanilla-script.js')
334
+ );
335
+
336
+ await createTestConfig(projectPath, {
337
+ version: '1.0.0',
338
+ targets: [{ browser: 'safari', minVersion: '15' }]
339
+ });
340
+
341
+ const result = await runBaseGuard(['check'], projectPath);
342
+
343
+ // Should process all framework files
344
+ expect(result.stdout).toContain('react-component.tsx');
345
+ expect(result.stdout).toContain('vue-component.vue');
346
+ expect(result.stdout).toContain('svelte-component.svelte');
347
+ expect(result.stdout).toContain('vanilla-script.js');
348
+
349
+ // Should find violations in all files
350
+ expect(result.stdout).toContain('compatibility violations found');
351
+ }, TEST_TIMEOUT);
352
+ });
353
+
354
+ describe('Configuration Testing', () => {
355
+ it('should respect different browser targets', async () => {
356
+ const projectPath = await copyFixture('react-project', 'config-test');
357
+
358
+ // Test with very old browsers
359
+ await createTestConfig(projectPath, {
360
+ version: '1.0.0',
361
+ targets: [
362
+ { browser: 'safari', minVersion: '10' },
363
+ { browser: 'chrome', minVersion: '60' }
364
+ ]
365
+ });
366
+
367
+ const oldResult = await runBaseGuard(['check'], projectPath);
368
+ expect(oldResult.stdout).toContain('compatibility violations found');
369
+
370
+ // Test with very new browsers
371
+ await createTestConfig(projectPath, {
372
+ version: '1.0.0',
373
+ targets: [
374
+ { browser: 'safari', minVersion: '17' },
375
+ { browser: 'chrome', minVersion: '120' }
376
+ ]
377
+ });
378
+
379
+ const newResult = await runBaseGuard(['check'], projectPath);
380
+ // Should have fewer or no violations with newer targets
381
+ expect(newResult.exitCode).toBeLessThanOrEqual(oldResult.exitCode);
382
+ }, TEST_TIMEOUT);
383
+
384
+ it('should handle baseline targets correctly', async () => {
385
+ const projectPath = await copyFixture('vanilla-project', 'baseline-test');
386
+
387
+ // Test baseline widely available
388
+ await createTestConfig(projectPath, {
389
+ version: '1.0.0',
390
+ targets: [
391
+ { browser: 'chrome', minVersion: 'baseline' },
392
+ { browser: 'safari', minVersion: 'baseline' }
393
+ ]
394
+ });
395
+
396
+ const result = await runBaseGuard(['check'], projectPath);
397
+
398
+ // Should only flag features that are not baseline
399
+ if (result.exitCode === 1) {
400
+ expect(result.stdout).toContain('baseline');
401
+ }
402
+ }, TEST_TIMEOUT);
403
+ });
404
+
405
+ describe('Error Handling and Edge Cases', () => {
406
+ it('should handle malformed files gracefully', async () => {
407
+ const projectPath = path.join(TEMP_DIR, 'malformed-project');
408
+ await fs.mkdir(projectPath, { recursive: true });
409
+
410
+ // Create malformed files
411
+ await fs.writeFile(path.join(projectPath, 'broken.js'), 'const invalid = {');
412
+ await fs.writeFile(path.join(projectPath, 'broken.css'), '.invalid { color: }');
413
+ await fs.writeFile(path.join(projectPath, 'broken.vue'), '<template><div></template>');
414
+
415
+ await createTestConfig(projectPath, {
416
+ version: '1.0.0',
417
+ targets: [{ browser: 'safari', minVersion: '15' }]
418
+ });
419
+
420
+ const result = await runBaseGuard(['check'], projectPath);
421
+
422
+ // Should not crash and should report parsing issues
423
+ expect(result.exitCode).not.toBe(2); // Not a crash
424
+ expect(result.stderr).toContain('parsing');
425
+ }, TEST_TIMEOUT);
426
+
427
+ it('should handle empty project', async () => {
428
+ const projectPath = path.join(TEMP_DIR, 'empty-project');
429
+ await fs.mkdir(projectPath, { recursive: true });
430
+
431
+ await createTestConfig(projectPath, {
432
+ version: '1.0.0',
433
+ targets: [{ browser: 'safari', minVersion: '15' }]
434
+ });
435
+
436
+ const result = await runBaseGuard(['check'], projectPath);
437
+
438
+ expect(result.exitCode).toBe(0);
439
+ expect(result.stdout).toContain('No files found to check');
440
+ }, TEST_TIMEOUT);
441
+
442
+ it('should handle missing configuration', async () => {
443
+ const projectPath = await copyFixture('react-project', 'no-config');
444
+
445
+ const result = await runBaseGuard(['check'], projectPath);
446
+
447
+ // Should prompt for initialization or use defaults
448
+ expect(result.stderr).toContain('configuration') || expect(result.stdout).toContain('init');
449
+ }, TEST_TIMEOUT);
450
+ });
451
+
452
+ describe('Performance Testing', () => {
453
+ it('should handle large number of files efficiently', async () => {
454
+ const projectPath = path.join(TEMP_DIR, 'large-project');
455
+ await fs.mkdir(projectPath, { recursive: true });
456
+
457
+ // Create many files
458
+ const promises = [];
459
+ for (let i = 0; i < 50; i++) {
460
+ promises.push(
461
+ fs.writeFile(
462
+ path.join(projectPath, `file${i}.js`),
463
+ `
464
+ // Modern JavaScript features
465
+ const data = { test: ${i} };
466
+ const cloned = structuredClone(data);
467
+ const observer = new ResizeObserver(() => {});
468
+ console.log('File ${i}');
469
+ `
470
+ )
471
+ );
472
+ }
473
+ await Promise.all(promises);
474
+
475
+ await createTestConfig(projectPath, {
476
+ version: '1.0.0',
477
+ targets: [{ browser: 'safari', minVersion: '15' }]
478
+ });
479
+
480
+ const startTime = Date.now();
481
+ const result = await runBaseGuard(['check'], projectPath);
482
+ const duration = Date.now() - startTime;
483
+
484
+ // Should complete within reasonable time (10 seconds for 50 files)
485
+ expect(duration).toBeLessThan(10000);
486
+ expect(result.stdout).toContain('structuredClone');
487
+ expect(result.stdout).toContain('ResizeObserver');
488
+ }, TEST_TIMEOUT);
489
+ });
490
+
491
+ describe('CLI Interface Testing', () => {
492
+ it('should show help information', async () => {
493
+ const result = await runBaseGuard(['--help']);
494
+
495
+ expect(result.exitCode).toBe(0);
496
+ expect(result.stdout).toContain('BaseGuard');
497
+ expect(result.stdout).toContain('check');
498
+ expect(result.stdout).toContain('init');
499
+ expect(result.stdout).toContain('fix');
500
+ }, TEST_TIMEOUT);
501
+
502
+ it('should show version information', async () => {
503
+ const result = await runBaseGuard(['--version']);
504
+
505
+ expect(result.exitCode).toBe(0);
506
+ expect(result.stdout).toMatch(/\d+\.\d+\.\d+/);
507
+ }, TEST_TIMEOUT);
508
+
509
+ it('should handle invalid commands gracefully', async () => {
510
+ const result = await runBaseGuard(['invalid-command']);
511
+
512
+ expect(result.exitCode).toBe(1);
513
+ expect(result.stderr).toContain('Unknown command') || expect(result.stdout).toContain('help');
514
+ }, TEST_TIMEOUT);
515
+ });
516
+ });