@wundr.io/cli 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 (213) hide show
  1. package/README.md +551 -0
  2. package/bin/wundr.js +39 -0
  3. package/dist/ai/ai-service.d.ts +152 -0
  4. package/dist/ai/ai-service.d.ts.map +1 -0
  5. package/dist/ai/ai-service.js +430 -0
  6. package/dist/ai/ai-service.js.map +1 -0
  7. package/dist/ai/claude-client.d.ts +130 -0
  8. package/dist/ai/claude-client.d.ts.map +1 -0
  9. package/dist/ai/claude-client.js +339 -0
  10. package/dist/ai/claude-client.js.map +1 -0
  11. package/dist/ai/conversation-manager.d.ts +164 -0
  12. package/dist/ai/conversation-manager.d.ts.map +1 -0
  13. package/dist/ai/conversation-manager.js +612 -0
  14. package/dist/ai/conversation-manager.js.map +1 -0
  15. package/dist/ai/index.d.ts +5 -0
  16. package/dist/ai/index.d.ts.map +1 -0
  17. package/dist/ai/index.js +8 -0
  18. package/dist/ai/index.js.map +1 -0
  19. package/dist/cli.d.ts +36 -0
  20. package/dist/cli.d.ts.map +1 -0
  21. package/dist/cli.js +173 -0
  22. package/dist/cli.js.map +1 -0
  23. package/dist/commands/ai.d.ts +89 -0
  24. package/dist/commands/ai.d.ts.map +1 -0
  25. package/dist/commands/ai.js +735 -0
  26. package/dist/commands/ai.js.map +1 -0
  27. package/dist/commands/analyze-optimized.d.ts +14 -0
  28. package/dist/commands/analyze-optimized.d.ts.map +1 -0
  29. package/dist/commands/analyze-optimized.js +437 -0
  30. package/dist/commands/analyze-optimized.js.map +1 -0
  31. package/dist/commands/analyze.d.ts +65 -0
  32. package/dist/commands/analyze.d.ts.map +1 -0
  33. package/dist/commands/analyze.js +435 -0
  34. package/dist/commands/analyze.js.map +1 -0
  35. package/dist/commands/batch.d.ts +71 -0
  36. package/dist/commands/batch.d.ts.map +1 -0
  37. package/dist/commands/batch.js +738 -0
  38. package/dist/commands/batch.js.map +1 -0
  39. package/dist/commands/chat.d.ts +71 -0
  40. package/dist/commands/chat.d.ts.map +1 -0
  41. package/dist/commands/chat.js +674 -0
  42. package/dist/commands/chat.js.map +1 -0
  43. package/dist/commands/claude-init.d.ts +28 -0
  44. package/dist/commands/claude-init.d.ts.map +1 -0
  45. package/dist/commands/claude-init.js +587 -0
  46. package/dist/commands/claude-init.js.map +1 -0
  47. package/dist/commands/claude-setup.d.ts +32 -0
  48. package/dist/commands/claude-setup.d.ts.map +1 -0
  49. package/dist/commands/claude-setup.js +570 -0
  50. package/dist/commands/claude-setup.js.map +1 -0
  51. package/dist/commands/computer-setup-commands.d.ts +39 -0
  52. package/dist/commands/computer-setup-commands.d.ts.map +1 -0
  53. package/dist/commands/computer-setup-commands.js +563 -0
  54. package/dist/commands/computer-setup-commands.js.map +1 -0
  55. package/dist/commands/computer-setup.d.ts +7 -0
  56. package/dist/commands/computer-setup.d.ts.map +1 -0
  57. package/dist/commands/computer-setup.js +481 -0
  58. package/dist/commands/computer-setup.js.map +1 -0
  59. package/dist/commands/create-command.d.ts +7 -0
  60. package/dist/commands/create-command.d.ts.map +1 -0
  61. package/dist/commands/create-command.js +158 -0
  62. package/dist/commands/create-command.js.map +1 -0
  63. package/dist/commands/create.d.ts +74 -0
  64. package/dist/commands/create.d.ts.map +1 -0
  65. package/dist/commands/create.js +556 -0
  66. package/dist/commands/create.js.map +1 -0
  67. package/dist/commands/dashboard.d.ts +91 -0
  68. package/dist/commands/dashboard.d.ts.map +1 -0
  69. package/dist/commands/dashboard.js +537 -0
  70. package/dist/commands/dashboard.js.map +1 -0
  71. package/dist/commands/govern.d.ts +70 -0
  72. package/dist/commands/govern.d.ts.map +1 -0
  73. package/dist/commands/govern.js +480 -0
  74. package/dist/commands/govern.js.map +1 -0
  75. package/dist/commands/init.d.ts +55 -0
  76. package/dist/commands/init.d.ts.map +1 -0
  77. package/dist/commands/init.js +584 -0
  78. package/dist/commands/init.js.map +1 -0
  79. package/dist/commands/performance-optimizer.d.ts +30 -0
  80. package/dist/commands/performance-optimizer.d.ts.map +1 -0
  81. package/dist/commands/performance-optimizer.js +649 -0
  82. package/dist/commands/performance-optimizer.js.map +1 -0
  83. package/dist/commands/plugins.d.ts +87 -0
  84. package/dist/commands/plugins.d.ts.map +1 -0
  85. package/dist/commands/plugins.js +685 -0
  86. package/dist/commands/plugins.js.map +1 -0
  87. package/dist/commands/setup.d.ts +29 -0
  88. package/dist/commands/setup.d.ts.map +1 -0
  89. package/dist/commands/setup.js +399 -0
  90. package/dist/commands/setup.js.map +1 -0
  91. package/dist/commands/test-init.d.ts +9 -0
  92. package/dist/commands/test-init.d.ts.map +1 -0
  93. package/dist/commands/test-init.js +222 -0
  94. package/dist/commands/test-init.js.map +1 -0
  95. package/dist/commands/test.d.ts +25 -0
  96. package/dist/commands/test.d.ts.map +1 -0
  97. package/dist/commands/test.js +217 -0
  98. package/dist/commands/test.js.map +1 -0
  99. package/dist/commands/watch.d.ts +76 -0
  100. package/dist/commands/watch.d.ts.map +1 -0
  101. package/dist/commands/watch.js +610 -0
  102. package/dist/commands/watch.js.map +1 -0
  103. package/dist/context/context-manager.d.ts +155 -0
  104. package/dist/context/context-manager.d.ts.map +1 -0
  105. package/dist/context/context-manager.js +383 -0
  106. package/dist/context/context-manager.js.map +1 -0
  107. package/dist/context/index.d.ts +3 -0
  108. package/dist/context/index.d.ts.map +1 -0
  109. package/dist/context/index.js +6 -0
  110. package/dist/context/index.js.map +1 -0
  111. package/dist/context/session-manager.d.ts +207 -0
  112. package/dist/context/session-manager.d.ts.map +1 -0
  113. package/dist/context/session-manager.js +682 -0
  114. package/dist/context/session-manager.js.map +1 -0
  115. package/dist/index.d.ts +8 -0
  116. package/dist/index.d.ts.map +1 -0
  117. package/dist/index.js +51 -0
  118. package/dist/index.js.map +1 -0
  119. package/dist/interactive/interactive-mode.d.ts +76 -0
  120. package/dist/interactive/interactive-mode.d.ts.map +1 -0
  121. package/dist/interactive/interactive-mode.js +730 -0
  122. package/dist/interactive/interactive-mode.js.map +1 -0
  123. package/dist/nlp/command-mapper.d.ts +174 -0
  124. package/dist/nlp/command-mapper.d.ts.map +1 -0
  125. package/dist/nlp/command-mapper.js +623 -0
  126. package/dist/nlp/command-mapper.js.map +1 -0
  127. package/dist/nlp/command-parser.d.ts +106 -0
  128. package/dist/nlp/command-parser.d.ts.map +1 -0
  129. package/dist/nlp/command-parser.js +416 -0
  130. package/dist/nlp/command-parser.js.map +1 -0
  131. package/dist/nlp/index.d.ts +5 -0
  132. package/dist/nlp/index.d.ts.map +1 -0
  133. package/dist/nlp/index.js +8 -0
  134. package/dist/nlp/index.js.map +1 -0
  135. package/dist/nlp/intent-classifier.d.ts +59 -0
  136. package/dist/nlp/intent-classifier.d.ts.map +1 -0
  137. package/dist/nlp/intent-classifier.js +384 -0
  138. package/dist/nlp/intent-classifier.js.map +1 -0
  139. package/dist/nlp/intent-parser.d.ts +152 -0
  140. package/dist/nlp/intent-parser.d.ts.map +1 -0
  141. package/dist/nlp/intent-parser.js +739 -0
  142. package/dist/nlp/intent-parser.js.map +1 -0
  143. package/dist/plugins/plugin-manager.d.ts +120 -0
  144. package/dist/plugins/plugin-manager.d.ts.map +1 -0
  145. package/dist/plugins/plugin-manager.js +595 -0
  146. package/dist/plugins/plugin-manager.js.map +1 -0
  147. package/dist/types/index.d.ts +224 -0
  148. package/dist/types/index.d.ts.map +1 -0
  149. package/dist/types/index.js +3 -0
  150. package/dist/types/index.js.map +1 -0
  151. package/dist/utils/config-manager.d.ts +73 -0
  152. package/dist/utils/config-manager.d.ts.map +1 -0
  153. package/dist/utils/config-manager.js +339 -0
  154. package/dist/utils/config-manager.js.map +1 -0
  155. package/dist/utils/error-handler.d.ts +46 -0
  156. package/dist/utils/error-handler.d.ts.map +1 -0
  157. package/dist/utils/error-handler.js +169 -0
  158. package/dist/utils/error-handler.js.map +1 -0
  159. package/dist/utils/logger.d.ts +25 -0
  160. package/dist/utils/logger.d.ts.map +1 -0
  161. package/dist/utils/logger.js +94 -0
  162. package/dist/utils/logger.js.map +1 -0
  163. package/package.json +119 -0
  164. package/src/ai/ai-service.ts +595 -0
  165. package/src/ai/claude-client.ts +490 -0
  166. package/src/ai/conversation-manager.ts +907 -0
  167. package/src/ai/index.ts +8 -0
  168. package/src/cli.ts +202 -0
  169. package/src/commands/ai.ts +995 -0
  170. package/src/commands/analyze-optimized.ts +641 -0
  171. package/src/commands/analyze.ts +576 -0
  172. package/src/commands/batch.ts +935 -0
  173. package/src/commands/chat.ts +876 -0
  174. package/src/commands/claude-init.ts +715 -0
  175. package/src/commands/claude-setup.ts +697 -0
  176. package/src/commands/computer-setup-commands.ts +709 -0
  177. package/src/commands/computer-setup.ts +565 -0
  178. package/src/commands/create-command.ts +175 -0
  179. package/src/commands/create.ts +727 -0
  180. package/src/commands/dashboard.ts +691 -0
  181. package/src/commands/govern.ts +635 -0
  182. package/src/commands/init.ts +677 -0
  183. package/src/commands/performance-optimizer.ts +864 -0
  184. package/src/commands/plugins.ts +848 -0
  185. package/src/commands/setup.ts +508 -0
  186. package/src/commands/test-init.ts +242 -0
  187. package/src/commands/test.ts +264 -0
  188. package/src/commands/watch.ts +755 -0
  189. package/src/context/context-manager.ts +546 -0
  190. package/src/context/index.ts +9 -0
  191. package/src/context/session-manager.ts +1019 -0
  192. package/src/index.ts +64 -0
  193. package/src/interactive/interactive-mode.ts +830 -0
  194. package/src/nlp/command-mapper.ts +885 -0
  195. package/src/nlp/command-parser.ts +564 -0
  196. package/src/nlp/index.ts +4 -0
  197. package/src/nlp/intent-classifier.ts +458 -0
  198. package/src/nlp/intent-parser.ts +1101 -0
  199. package/src/plugins/plugin-manager.ts +744 -0
  200. package/src/types/index.ts +252 -0
  201. package/src/types/modules.d.ts +56 -0
  202. package/src/utils/config-manager.ts +391 -0
  203. package/src/utils/error-handler.ts +192 -0
  204. package/src/utils/logger.ts +104 -0
  205. package/templates/batch/ci-cd.yaml +62 -0
  206. package/templates/component/{{fileName}}.test.tsx +17 -0
  207. package/templates/component/{{fileName}}.tsx +21 -0
  208. package/templates/service/{{fileName}}.ts +98 -0
  209. package/templates/wundr-test.config.js +0 -0
  210. package/test-suites/api/health.spec.ts +134 -0
  211. package/test-suites/helpers/test-config.ts +84 -0
  212. package/test-suites/ui/accessibility.spec.ts +102 -0
  213. package/test-suites/ui/smoke.spec.ts +92 -0
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Portable test configuration
3
+ * Can be customized via wundr-test.config.js in the target project
4
+ */
5
+
6
+ export interface TestConfig {
7
+ baseURL: string;
8
+ timeout: number;
9
+ retries: number;
10
+ headless: boolean;
11
+ slowMo?: number;
12
+ screenshot: 'off' | 'on' | 'only-on-failure';
13
+ video: 'off' | 'on' | 'retain-on-failure';
14
+ trace: 'off' | 'on' | 'on-first-retry';
15
+
16
+ // Custom selectors for specific apps
17
+ selectors?: {
18
+ navigation?: string;
19
+ mainContent?: string;
20
+ footer?: string;
21
+ searchInput?: string;
22
+ loginButton?: string;
23
+ };
24
+
25
+ // API configuration
26
+ api?: {
27
+ baseURL?: string;
28
+ headers?: Record<string, string>;
29
+ timeout?: number;
30
+ };
31
+
32
+ // Test data
33
+ testData?: {
34
+ validUser?: {
35
+ username: string;
36
+ password: string;
37
+ };
38
+ searchTerms?: string[];
39
+ };
40
+ }
41
+
42
+ export const defaultConfig: TestConfig = {
43
+ baseURL: process.env.TEST_BASE_URL || 'http://localhost:3000',
44
+ timeout: 30000,
45
+ retries: 2,
46
+ headless: true,
47
+ screenshot: 'only-on-failure',
48
+ video: 'retain-on-failure',
49
+ trace: 'on-first-retry',
50
+
51
+ selectors: {
52
+ navigation: 'nav, [role="navigation"], header',
53
+ mainContent: 'main, [role="main"], #content',
54
+ footer: 'footer, [role="contentinfo"]',
55
+ searchInput: 'input[type="search"], input[placeholder*="search" i]',
56
+ loginButton: 'button[type="submit"], button:has-text("Login"), button:has-text("Sign in")'
57
+ },
58
+
59
+ api: {
60
+ timeout: 10000
61
+ }
62
+ };
63
+
64
+ /**
65
+ * Load configuration from project or use defaults
66
+ */
67
+ export function loadConfig(customConfig?: Partial<TestConfig>): TestConfig {
68
+ return {
69
+ ...defaultConfig,
70
+ ...customConfig,
71
+ selectors: {
72
+ ...defaultConfig.selectors,
73
+ ...customConfig?.selectors
74
+ },
75
+ api: {
76
+ ...defaultConfig.api,
77
+ ...customConfig?.api
78
+ },
79
+ testData: {
80
+ ...defaultConfig.testData,
81
+ ...customConfig?.testData
82
+ }
83
+ };
84
+ }
@@ -0,0 +1,102 @@
1
+ import { test, expect } from '@playwright/test';
2
+ import AxeBuilder from '@axe-core/playwright';
3
+
4
+ /**
5
+ * Portable accessibility tests using axe-core
6
+ */
7
+
8
+ test.describe('Accessibility Tests', () => {
9
+ test('homepage meets WCAG standards', async ({ page }) => {
10
+ await page.goto('/');
11
+
12
+ const accessibilityScanResults = await new AxeBuilder({ page })
13
+ .withTags(['wcag2a', 'wcag2aa', 'wcag21a', 'wcag21aa'])
14
+ .analyze();
15
+
16
+ expect(accessibilityScanResults.violations).toEqual([]);
17
+ });
18
+
19
+ test('all images have alt text', async ({ page }) => {
20
+ await page.goto('/');
21
+
22
+ const images = await page.locator('img').all();
23
+
24
+ for (const img of images) {
25
+ const alt = await img.getAttribute('alt');
26
+ const role = await img.getAttribute('role');
27
+
28
+ // Images should have alt text or be marked as decorative
29
+ expect(alt !== null || role === 'presentation').toBeTruthy();
30
+ }
31
+ });
32
+
33
+ test('forms have proper labels', async ({ page }) => {
34
+ await page.goto('/');
35
+
36
+ const inputs = await page.locator('input, select, textarea').all();
37
+
38
+ for (const input of inputs) {
39
+ const id = await input.getAttribute('id');
40
+ const ariaLabel = await input.getAttribute('aria-label');
41
+ const ariaLabelledBy = await input.getAttribute('aria-labelledby');
42
+
43
+ if (id) {
44
+ // Check for associated label
45
+ const label = await page.locator(`label[for="${id}"]`).count();
46
+ const hasLabel = label > 0 || ariaLabel !== null || ariaLabelledBy !== null;
47
+ expect(hasLabel).toBeTruthy();
48
+ }
49
+ }
50
+ });
51
+
52
+ test('focus is visible and logical', async ({ page }) => {
53
+ await page.goto('/');
54
+
55
+ // Tab through interactive elements
56
+ await page.keyboard.press('Tab');
57
+
58
+ // Check if focused element has visible outline
59
+ const focusedElement = await page.evaluateHandle(() => document.activeElement);
60
+ const hasOutline = await focusedElement.evaluate((el) => {
61
+ if (!el) return false;
62
+ const styles = window.getComputedStyle(el as Element);
63
+ return styles.outlineStyle !== 'none' || styles.boxShadow !== 'none';
64
+ });
65
+
66
+ expect(hasOutline).toBeTruthy();
67
+ });
68
+
69
+ test('color contrast meets standards', async ({ page }) => {
70
+ await page.goto('/');
71
+
72
+ const accessibilityScanResults = await new AxeBuilder({ page })
73
+ .withTags(['color-contrast'])
74
+ .analyze();
75
+
76
+ expect(accessibilityScanResults.violations).toEqual([]);
77
+ });
78
+
79
+ test('page has proper heading structure', async ({ page }) => {
80
+ await page.goto('/');
81
+
82
+ // Check for h1
83
+ const h1Count = await page.locator('h1').count();
84
+ expect(h1Count).toBeGreaterThan(0);
85
+
86
+ // Check heading hierarchy
87
+ const headings = await page.evaluate(() => {
88
+ const headingElements = document.querySelectorAll('h1, h2, h3, h4, h5, h6');
89
+ return Array.from(headingElements).map(h => ({
90
+ level: parseInt(h.tagName[1]),
91
+ text: h.textContent
92
+ }));
93
+ });
94
+
95
+ // Verify no skipped heading levels
96
+ let previousLevel = 0;
97
+ for (const heading of headings) {
98
+ expect(heading.level - previousLevel).toBeLessThanOrEqual(1);
99
+ previousLevel = heading.level;
100
+ }
101
+ });
102
+ });
@@ -0,0 +1,92 @@
1
+ import { test, expect } from '@playwright/test';
2
+
3
+ /**
4
+ * Portable smoke tests that can be run against any web application
5
+ * These tests are generic and work with most web apps
6
+ */
7
+
8
+ test.describe('Portable Smoke Tests', () => {
9
+ test('homepage loads without errors', async ({ page }) => {
10
+ const jsErrors: string[] = [];
11
+
12
+ page.on('pageerror', (error) => {
13
+ jsErrors.push(error.message);
14
+ });
15
+
16
+ await page.goto('/');
17
+ await page.waitForLoadState('networkidle');
18
+
19
+ // Basic structure should be present
20
+ await expect(page.locator('body')).toBeVisible();
21
+
22
+ // Should not have critical JavaScript errors
23
+ const criticalErrors = jsErrors.filter(error =>
24
+ error.includes('Cannot read') ||
25
+ error.includes('undefined is not') ||
26
+ error.includes('Uncaught')
27
+ );
28
+
29
+ expect(criticalErrors.length).toBe(0);
30
+ });
31
+
32
+ test('navigation elements are present', async ({ page }) => {
33
+ await page.goto('/');
34
+
35
+ // Check for common navigation patterns
36
+ const hasNavigation = await page.locator('nav, [role="navigation"], header').count() > 0;
37
+ expect(hasNavigation).toBeTruthy();
38
+ });
39
+
40
+ test('interactive elements are clickable', async ({ page }) => {
41
+ await page.goto('/');
42
+
43
+ // Find clickable elements
44
+ const buttons = await page.locator('button:visible, a:visible').all();
45
+
46
+ if (buttons.length > 0) {
47
+ // Test first button/link
48
+ const firstElement = buttons[0];
49
+ await expect(firstElement).toBeEnabled();
50
+ }
51
+ });
52
+
53
+ test('forms accept input', async ({ page }) => {
54
+ await page.goto('/');
55
+
56
+ // Look for form inputs
57
+ const inputs = await page.locator('input:visible, textarea:visible').all();
58
+
59
+ if (inputs.length > 0) {
60
+ const firstInput = inputs[0];
61
+ await firstInput.fill('test');
62
+ const value = await firstInput.inputValue();
63
+ expect(value).toBe('test');
64
+ }
65
+ });
66
+
67
+ test('responsive layout works', async ({ page }) => {
68
+ await page.goto('/');
69
+
70
+ // Test mobile viewport
71
+ await page.setViewportSize({ width: 375, height: 667 });
72
+
73
+ // Should not have horizontal scroll
74
+ const hasHorizontalScroll = await page.evaluate(() => {
75
+ return document.documentElement.scrollWidth > document.documentElement.clientWidth;
76
+ });
77
+
78
+ expect(hasHorizontalScroll).toBeFalsy();
79
+ });
80
+
81
+ test('page has proper metadata', async ({ page }) => {
82
+ await page.goto('/');
83
+
84
+ // Check for title
85
+ const title = await page.title();
86
+ expect(title).toBeTruthy();
87
+
88
+ // Check for language attribute
89
+ const lang = await page.locator('html').getAttribute('lang');
90
+ expect(lang).toBeTruthy();
91
+ });
92
+ });