specweave 0.23.14 → 0.23.18

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 (119) hide show
  1. package/.claude-plugin/marketplace.json +11 -0
  2. package/CLAUDE.md +77 -7
  3. package/dist/plugins/specweave-github/lib/github-spec-content-sync.d.ts.map +1 -1
  4. package/dist/plugins/specweave-github/lib/github-spec-content-sync.js +57 -0
  5. package/dist/plugins/specweave-github/lib/github-spec-content-sync.js.map +1 -1
  6. package/dist/src/cli/commands/sync-spec-content.js +3 -0
  7. package/dist/src/cli/commands/sync-spec-content.js.map +1 -1
  8. package/dist/src/core/progress/progress-tracker.d.ts +4 -1
  9. package/dist/src/core/progress/progress-tracker.d.ts.map +1 -1
  10. package/dist/src/core/progress/progress-tracker.js +33 -4
  11. package/dist/src/core/progress/progress-tracker.js.map +1 -1
  12. package/dist/src/core/spec-content-sync.d.ts +1 -1
  13. package/dist/src/core/spec-content-sync.d.ts.map +1 -1
  14. package/dist/src/core/spec-detector.d.ts +5 -0
  15. package/dist/src/core/spec-detector.d.ts.map +1 -1
  16. package/dist/src/core/spec-detector.js +91 -33
  17. package/dist/src/core/spec-detector.js.map +1 -1
  18. package/dist/src/integrations/ado/ado-dependency-loader.d.ts +1 -1
  19. package/dist/src/integrations/ado/ado-dependency-loader.d.ts.map +1 -1
  20. package/dist/src/integrations/ado/ado-dependency-loader.js +39 -7
  21. package/dist/src/integrations/ado/ado-dependency-loader.js.map +1 -1
  22. package/package.json +1 -1
  23. package/plugins/specweave/hooks/lib/migrate-increment-work.sh +1 -1
  24. package/plugins/specweave/hooks/lib/migrate-increment-work.sh.bak +245 -0
  25. package/plugins/specweave/hooks/lib/sync-spec-content.sh +2 -2
  26. package/plugins/specweave/hooks/lib/sync-spec-content.sh.bak +149 -0
  27. package/plugins/specweave/hooks/lib/update-status-line.sh +34 -4
  28. package/plugins/specweave/hooks/lib/validate-spec-status.sh +1 -1
  29. package/plugins/specweave/hooks/lib/validate-spec-status.sh.bak +163 -0
  30. package/plugins/specweave/hooks/post-first-increment.sh +1 -1
  31. package/plugins/specweave/hooks/post-first-increment.sh.bak +61 -0
  32. package/plugins/specweave/hooks/post-spec-update.sh +1 -1
  33. package/plugins/specweave/hooks/post-spec-update.sh.bak +158 -0
  34. package/plugins/specweave/hooks/post-user-story-complete.sh +1 -1
  35. package/plugins/specweave/hooks/post-user-story-complete.sh.bak +179 -0
  36. package/plugins/specweave/hooks/pre-command-deduplication.sh +1 -1
  37. package/plugins/specweave/hooks/pre-command-deduplication.sh.bak +83 -0
  38. package/plugins/specweave/hooks/user-prompt-submit.sh +1 -1
  39. package/plugins/specweave/hooks/user-prompt-submit.sh.bak +386 -0
  40. package/plugins/specweave/skills/specweave-framework/SKILL.md +1 -1
  41. package/plugins/specweave-ado/agents/ado-manager/AGENT.md +23 -0
  42. package/plugins/specweave-ado/agents/ado-multi-project-mapper/AGENT.md +23 -0
  43. package/plugins/specweave-ado/agents/ado-sync-judge/AGENT.md +23 -0
  44. package/plugins/specweave-backend/agents/database-optimizer/AGENT.md +23 -0
  45. package/plugins/specweave-confluent/agents/confluent-architect/AGENT.md +23 -0
  46. package/plugins/specweave-diagrams/agents/diagrams-architect/AGENT.md +23 -0
  47. package/plugins/specweave-github/.claude-plugin/plugin.json +15 -1
  48. package/plugins/specweave-github/agents/github-manager/AGENT.md +23 -0
  49. package/plugins/specweave-github/agents/github-task-splitter/AGENT.md +25 -0
  50. package/plugins/specweave-github/agents/user-story-updater/AGENT.md +25 -0
  51. package/plugins/specweave-github/hooks/.specweave/logs/hooks-debug.log +16 -0
  52. package/plugins/specweave-github/hooks/post-task-completion.sh +53 -0
  53. package/plugins/specweave-github/lib/github-spec-content-sync.js +49 -0
  54. package/plugins/specweave-github/lib/github-spec-content-sync.ts +67 -0
  55. package/plugins/specweave-infrastructure/agents/devops/AGENT.md +26 -0
  56. package/plugins/specweave-infrastructure/agents/network-engineer/AGENT.md +26 -0
  57. package/plugins/specweave-infrastructure/agents/observability-engineer/AGENT.md +26 -0
  58. package/plugins/specweave-infrastructure/agents/performance-engineer/AGENT.md +26 -0
  59. package/plugins/specweave-infrastructure/agents/sre/AGENT.md +26 -0
  60. package/plugins/specweave-jira/agents/jira-manager/AGENT.md +26 -0
  61. package/plugins/specweave-kafka/agents/kafka-architect/AGENT.md +26 -0
  62. package/plugins/specweave-kafka/agents/kafka-devops/AGENT.md +26 -0
  63. package/plugins/specweave-kafka/agents/kafka-observability/AGENT.md +26 -0
  64. package/plugins/specweave-kubernetes/agents/kubernetes-architect/AGENT.md +26 -0
  65. package/plugins/specweave-ml/.claude-plugin/plugin.json +2 -2
  66. package/plugins/specweave-ml/agents/data-scientist/AGENT.md +26 -0
  67. package/plugins/specweave-ml/agents/ml-engineer/AGENT.md +26 -0
  68. package/plugins/specweave-ml/agents/mlops-engineer/AGENT.md +26 -0
  69. package/plugins/specweave-mobile/agents/mobile-architect/AGENT.md +26 -0
  70. package/plugins/specweave-payments/agents/payment-integration/AGENT.md +26 -0
  71. package/plugins/specweave-plugin-dev/.claude-plugin/plugin.json +19 -0
  72. package/plugins/specweave-plugin-dev/skills/plugin-expert/SKILL.md +1231 -0
  73. package/plugins/specweave-release/agents/release-manager/AGENT.md +27 -0
  74. package/plugins/specweave-release/hooks/.specweave/logs/dora-tracking.log +24 -0
  75. package/plugins/specweave/skills/plugin-expert/SKILL.md +0 -340
  76. package/plugins/specweave-alternatives/.claude-plugin/plugin.json +0 -21
  77. package/plugins/specweave-alternatives/skills/bmad-method-expert/SKILL.md +0 -626
  78. package/plugins/specweave-alternatives/skills/bmad-method-expert/scripts/analyze-project.js +0 -318
  79. package/plugins/specweave-alternatives/skills/bmad-method-expert/scripts/check-setup.js +0 -208
  80. package/plugins/specweave-alternatives/skills/bmad-method-expert/scripts/generate-template.js +0 -1149
  81. package/plugins/specweave-alternatives/skills/bmad-method-expert/scripts/validate-documents.js +0 -340
  82. package/plugins/specweave-alternatives/skills/spec-kit-expert/SKILL.md +0 -1010
  83. package/plugins/specweave-cost-optimizer/.claude-plugin/plugin.json +0 -20
  84. package/plugins/specweave-cost-optimizer/skills/cost-optimizer/SKILL.md +0 -190
  85. package/plugins/specweave-docs/.claude-plugin/plugin.json +0 -19
  86. package/plugins/specweave-docs/skills/docusaurus/SKILL.md +0 -613
  87. package/plugins/specweave-docs/skills/spec-driven-brainstorming/README.md +0 -264
  88. package/plugins/specweave-docs/skills/spec-driven-brainstorming/SKILL.md +0 -439
  89. package/plugins/specweave-docs/skills/spec-driven-debugging/README.md +0 -479
  90. package/plugins/specweave-docs/skills/spec-driven-debugging/SKILL.md +0 -652
  91. package/plugins/specweave-figma/.claude-plugin/.mcp.json +0 -12
  92. package/plugins/specweave-figma/.claude-plugin/plugin.json +0 -20
  93. package/plugins/specweave-figma/ARCHITECTURE.md +0 -453
  94. package/plugins/specweave-figma/README.md +0 -728
  95. package/plugins/specweave-figma/skills/figma-to-code/SKILL.md +0 -632
  96. package/plugins/specweave-figma/skills/figma-to-code/test-1-token-generation.yaml +0 -29
  97. package/plugins/specweave-figma/skills/figma-to-code/test-2-component-generation.yaml +0 -27
  98. package/plugins/specweave-figma/skills/figma-to-code/test-3-typescript-generation.yaml +0 -28
  99. package/plugins/specweave-frontend/.claude-plugin/plugin.json +0 -21
  100. package/plugins/specweave-frontend/skills/design-system-architect/SKILL.md +0 -107
  101. package/plugins/specweave-frontend/skills/frontend/SKILL.md +0 -177
  102. package/plugins/specweave-frontend/skills/nextjs/SKILL.md +0 -176
  103. package/plugins/specweave-testing/.claude-plugin/plugin.json +0 -20
  104. package/plugins/specweave-testing/skills/e2e-playwright/README.md +0 -506
  105. package/plugins/specweave-testing/skills/e2e-playwright/SKILL.md +0 -457
  106. package/plugins/specweave-testing/skills/e2e-playwright/execute.js +0 -373
  107. package/plugins/specweave-testing/skills/e2e-playwright/lib/utils.js +0 -514
  108. package/plugins/specweave-testing/skills/e2e-playwright/package.json +0 -33
  109. package/plugins/specweave-tooling/.claude-plugin/plugin.json +0 -19
  110. package/plugins/specweave-tooling/skills/skill-creator/LICENSE.txt +0 -202
  111. package/plugins/specweave-tooling/skills/skill-creator/SKILL.md +0 -209
  112. package/plugins/specweave-tooling/skills/skill-creator/scripts/init_skill.py +0 -303
  113. package/plugins/specweave-tooling/skills/skill-creator/scripts/package_skill.py +0 -110
  114. package/plugins/specweave-tooling/skills/skill-creator/scripts/quick_validate.py +0 -65
  115. package/plugins/specweave-tooling/skills/skill-router/SKILL.md +0 -479
  116. package/plugins/specweave-ui/.claude-plugin/plugin.json +0 -26
  117. package/plugins/specweave-ui/.mcp.json +0 -10
  118. package/plugins/specweave-ui/README.md +0 -492
  119. package/plugins/specweave-ui/skills/browser-automation/SKILL.md +0 -676
@@ -1,514 +0,0 @@
1
- /**
2
- * Playwright Helper Utilities for SpecWeave
3
- *
4
- * Collection of helper functions for common Playwright testing patterns.
5
- * SpecWeave-aware utilities for enhanced testing workflows.
6
- */
7
-
8
- const { execSync } = require('child_process');
9
- const fs = require('fs');
10
- const path = require('path');
11
-
12
- /**
13
- * Detect running development servers on common ports
14
- *
15
- * @returns {Promise<Array<{port: number, url: string, name: string}>>}
16
- */
17
- async function detectServers() {
18
- const commonPorts = [3000, 3001, 3002, 3010, 4000, 5000, 5173, 8000, 8080, 8888];
19
- const servers = [];
20
-
21
- for (const port of commonPorts) {
22
- try {
23
- // Use lsof to check if port is in use (macOS/Linux)
24
- const result = execSync(`lsof -i :${port} -sTCP:LISTEN -t`, {
25
- encoding: 'utf8',
26
- stdio: ['pipe', 'pipe', 'ignore']
27
- });
28
-
29
- if (result.trim()) {
30
- servers.push({
31
- port,
32
- url: `http://localhost:${port}`,
33
- name: guessServerName(port)
34
- });
35
- }
36
- } catch (e) {
37
- // Port not in use, continue
38
- }
39
- }
40
-
41
- return servers;
42
- }
43
-
44
- /**
45
- * Guess server name based on common port conventions
46
- */
47
- function guessServerName(port) {
48
- const nameMap = {
49
- 3000: 'Next.js / React Dev',
50
- 3001: 'Secondary Dev Server',
51
- 5173: 'Vite',
52
- 4000: 'Express / Backend',
53
- 8000: 'Python / Django',
54
- 8080: 'Java / Spring Boot'
55
- };
56
-
57
- return nameMap[port] || 'Dev Server';
58
- }
59
-
60
- /**
61
- * Safe click with automatic wait and retry
62
- *
63
- * @param {Page} page - Playwright page object
64
- * @param {string} selector - CSS selector
65
- * @param {object} options - Click options
66
- */
67
- async function safeClick(page, selector, options = {}) {
68
- const timeout = options.timeout || 10000;
69
- const retries = options.retries || 3;
70
-
71
- for (let i = 0; i < retries; i++) {
72
- try {
73
- await page.waitForSelector(selector, { timeout, state: 'visible' });
74
- await page.click(selector, { timeout });
75
- return;
76
- } catch (error) {
77
- if (i === retries - 1) {
78
- throw new Error(`Failed to click "${selector}" after ${retries} attempts: ${error.message}`);
79
- }
80
- // Wait before retry
81
- await page.waitForTimeout(1000);
82
- }
83
- }
84
- }
85
-
86
- /**
87
- * Safe type with automatic focus and validation
88
- *
89
- * @param {Page} page - Playwright page object
90
- * @param {string} selector - CSS selector
91
- * @param {string} text - Text to type
92
- * @param {object} options - Type options
93
- */
94
- async function safeType(page, selector, text, options = {}) {
95
- const timeout = options.timeout || 10000;
96
- const clearFirst = options.clear !== false; // Default true
97
-
98
- await page.waitForSelector(selector, { timeout, state: 'visible' });
99
-
100
- // Focus the input
101
- await page.focus(selector);
102
-
103
- // Clear existing value if requested
104
- if (clearFirst) {
105
- await page.fill(selector, '');
106
- }
107
-
108
- // Type with slight delay for realism
109
- await page.type(selector, text, { delay: options.delay || 50 });
110
-
111
- // Verify text was entered (optional)
112
- if (options.verify !== false) {
113
- const value = await page.inputValue(selector);
114
- if (value !== text && !options.partial) {
115
- throw new Error(`Failed to type into "${selector}". Expected "${text}", got "${value}"`);
116
- }
117
- }
118
- }
119
-
120
- /**
121
- * Capture timestamped screenshot
122
- *
123
- * @param {Page} page - Playwright page object
124
- * @param {string} name - Base name for screenshot
125
- * @param {object} options - Screenshot options
126
- * @returns {string} Path to screenshot
127
- */
128
- async function captureScreenshot(page, name, options = {}) {
129
- const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, -5);
130
- const filename = `${name}-${timestamp}.png`;
131
- const filepath = path.join(options.dir || '/tmp', filename);
132
-
133
- await page.screenshot({
134
- path: filepath,
135
- fullPage: options.fullPage !== false, // Default true
136
- ...options
137
- });
138
-
139
- console.log(`📸 Screenshot saved: ${filepath}`);
140
- return filepath;
141
- }
142
-
143
- /**
144
- * Handle common cookie consent banners
145
- *
146
- * @param {Page} page - Playwright page object
147
- */
148
- async function handleCookieBanner(page) {
149
- const commonSelectors = [
150
- 'button:has-text("Accept")',
151
- 'button:has-text("Accept All")',
152
- 'button:has-text("Agree")',
153
- 'button:has-text("OK")',
154
- 'button:has-text("I Agree")',
155
- 'button[id*="accept"]',
156
- 'button[class*="accept"]',
157
- 'button[class*="cookie"]',
158
- '[data-testid="cookie-accept"]'
159
- ];
160
-
161
- for (const selector of commonSelectors) {
162
- try {
163
- const element = await page.locator(selector).first();
164
- if (await element.isVisible({ timeout: 2000 })) {
165
- await element.click();
166
- console.log('✅ Cookie banner dismissed');
167
- return true;
168
- }
169
- } catch (e) {
170
- // Continue to next selector
171
- }
172
- }
173
-
174
- return false;
175
- }
176
-
177
- /**
178
- * Extract data from HTML table
179
- *
180
- * @param {Page} page - Playwright page object
181
- * @param {string} selector - Table selector
182
- * @returns {Array<object>} Array of row objects
183
- */
184
- async function extractTableData(page, selector) {
185
- return await page.evaluate((sel) => {
186
- const table = document.querySelector(sel);
187
- if (!table) return [];
188
-
189
- const headers = Array.from(table.querySelectorAll('thead th')).map(th => th.textContent.trim());
190
- const rows = Array.from(table.querySelectorAll('tbody tr'));
191
-
192
- return rows.map(row => {
193
- const cells = Array.from(row.querySelectorAll('td'));
194
- const rowData = {};
195
- cells.forEach((cell, index) => {
196
- rowData[headers[index] || `column${index}`] = cell.textContent.trim();
197
- });
198
- return rowData;
199
- });
200
- }, selector);
201
- }
202
-
203
- /**
204
- * Wait for DOM to stabilize (no changes for specified duration)
205
- *
206
- * @param {Page} page - Playwright page object
207
- * @param {number} stabilityTime - Time in ms to wait for stability
208
- */
209
- async function waitForStableDOM(page, stabilityTime = 1000) {
210
- let lastMutationTime = Date.now();
211
- let stabilityTimeout;
212
-
213
- return new Promise((resolve) => {
214
- const observer = page.evaluateHandle((ms) => {
215
- return new Promise((res) => {
216
- let lastChange = Date.now();
217
- let timeout;
218
-
219
- const checkStability = () => {
220
- if (Date.now() - lastChange >= ms) {
221
- observer.disconnect();
222
- res();
223
- }
224
- };
225
-
226
- const observer = new MutationObserver(() => {
227
- lastChange = Date.now();
228
- clearTimeout(timeout);
229
- timeout = setTimeout(checkStability, ms);
230
- });
231
-
232
- observer.observe(document.body, {
233
- childList: true,
234
- subtree: true,
235
- attributes: true
236
- });
237
-
238
- // Initial stability check
239
- timeout = setTimeout(checkStability, ms);
240
- });
241
- }, stabilityTime);
242
-
243
- observer.then(() => resolve());
244
- });
245
- }
246
-
247
- /**
248
- * Basic accessibility checks
249
- *
250
- * @param {Page} page - Playwright page object
251
- * @returns {Array<{type: string, element: string, message: string}>}
252
- */
253
- async function checkAccessibility(page) {
254
- return await page.evaluate(() => {
255
- const issues = [];
256
-
257
- // Check for images without alt text
258
- document.querySelectorAll('img').forEach(img => {
259
- if (!img.alt) {
260
- issues.push({
261
- type: 'missing-alt',
262
- element: img.outerHTML.substring(0, 100),
263
- message: 'Image missing alt text'
264
- });
265
- }
266
- });
267
-
268
- // Check for form inputs without labels
269
- document.querySelectorAll('input, textarea, select').forEach(input => {
270
- if (input.type === 'hidden') return;
271
-
272
- const hasLabel = !!input.closest('label') ||
273
- !!document.querySelector(`label[for="${input.id}"]`) ||
274
- !!input.getAttribute('aria-label') ||
275
- !!input.getAttribute('aria-labelledby');
276
-
277
- if (!hasLabel) {
278
- issues.push({
279
- type: 'missing-label',
280
- element: input.outerHTML.substring(0, 100),
281
- message: 'Form input missing label or ARIA label'
282
- });
283
- }
284
- });
285
-
286
- // Check for buttons without accessible text
287
- document.querySelectorAll('button').forEach(button => {
288
- const hasText = button.textContent.trim() ||
289
- button.getAttribute('aria-label') ||
290
- button.querySelector('img')?.alt;
291
-
292
- if (!hasText) {
293
- issues.push({
294
- type: 'missing-button-text',
295
- element: button.outerHTML.substring(0, 100),
296
- message: 'Button missing accessible text'
297
- });
298
- }
299
- });
300
-
301
- // Check for links without text
302
- document.querySelectorAll('a').forEach(link => {
303
- const hasText = link.textContent.trim() ||
304
- link.getAttribute('aria-label') ||
305
- link.querySelector('img')?.alt;
306
-
307
- if (!hasText) {
308
- issues.push({
309
- type: 'missing-link-text',
310
- element: link.outerHTML.substring(0, 100),
311
- message: 'Link missing accessible text'
312
- });
313
- }
314
- });
315
-
316
- return issues;
317
- });
318
- }
319
-
320
- /**
321
- * Generate SpecWeave test report
322
- *
323
- * @param {object} results - Test results object
324
- * @param {string} incrementId - Increment ID (e.g., "0003-user-auth")
325
- * @returns {string} Report content in Markdown
326
- */
327
- function generateTestReport(results, incrementId) {
328
- const {
329
- tests = [],
330
- summary = {},
331
- performance = {},
332
- accessibility = [],
333
- recommendations = []
334
- } = results;
335
-
336
- const date = new Date().toISOString().split('T')[0];
337
- const status = summary.failed === 0 ? '✅ Passed' : '❌ Failed';
338
-
339
- let report = `# E2E Test Report - Increment ${incrementId}\n\n`;
340
- report += `**Date**: ${date}\n`;
341
- report += `**Duration**: ${summary.duration || 'N/A'}\n`;
342
- report += `**Status**: ${status}\n\n`;
343
-
344
- report += `## Test Summary\n\n`;
345
- report += `- Total Tests: ${summary.total || 0}\n`;
346
- report += `- Passed: ${summary.passed || 0}\n`;
347
- report += `- Failed: ${summary.failed || 0}\n`;
348
- report += `- Skipped: ${summary.skipped || 0}\n\n`;
349
-
350
- if (tests.length > 0) {
351
- report += `## Test Results\n\n`;
352
- tests.forEach(test => {
353
- report += `### ${test.name}\n`;
354
- report += `- **Status**: ${test.status}\n`;
355
- report += `- **Duration**: ${test.duration}\n`;
356
- if (test.screenshot) {
357
- report += `- **Screenshot**: \`${test.screenshot}\`\n`;
358
- }
359
- if (test.error) {
360
- report += `- **Error**: ${test.error}\n`;
361
- }
362
- report += `\n`;
363
- });
364
- }
365
-
366
- if (Object.keys(performance).length > 0) {
367
- report += `## Performance Metrics\n\n`;
368
- Object.entries(performance).forEach(([key, value]) => {
369
- report += `- ${key}: ${value}\n`;
370
- });
371
- report += `\n`;
372
- }
373
-
374
- if (accessibility.length > 0) {
375
- report += `## Accessibility Issues\n\n`;
376
- const grouped = accessibility.reduce((acc, issue) => {
377
- acc[issue.type] = (acc[issue.type] || 0) + 1;
378
- return acc;
379
- }, {});
380
-
381
- Object.entries(grouped).forEach(([type, count]) => {
382
- report += `- ${type}: ${count} instance${count > 1 ? 's' : ''}\n`;
383
- });
384
- report += `\n`;
385
- }
386
-
387
- if (recommendations.length > 0) {
388
- report += `## Recommendations\n\n`;
389
- recommendations.forEach((rec, i) => {
390
- report += `${i + 1}. ${rec}\n`;
391
- });
392
- report += `\n`;
393
- }
394
-
395
- report += `---\n`;
396
- report += `*Generated by e2e-playwright skill*\n`;
397
-
398
- return report;
399
- }
400
-
401
- /**
402
- * Save test report to SpecWeave increment folder
403
- *
404
- * @param {string} reportContent - Markdown report content
405
- * @param {string} incrementPath - Path to increment folder
406
- * @param {string} filename - Report filename
407
- */
408
- function saveTestReport(reportContent, incrementPath, filename = 'e2e-test-report.md') {
409
- const reportsDir = path.join(incrementPath, 'reports');
410
-
411
- // Create reports directory if it doesn't exist
412
- if (!fs.existsSync(reportsDir)) {
413
- fs.mkdirSync(reportsDir, { recursive: true });
414
- }
415
-
416
- const reportPath = path.join(reportsDir, filename);
417
- fs.writeFileSync(reportPath, reportContent, 'utf8');
418
-
419
- console.log(`📄 Test report saved: ${reportPath}`);
420
- return reportPath;
421
- }
422
-
423
- /**
424
- * Wait for network to be idle
425
- *
426
- * @param {Page} page - Playwright page object
427
- * @param {number} timeout - Timeout in ms
428
- */
429
- async function waitForNetworkIdle(page, timeout = 30000) {
430
- try {
431
- await page.waitForLoadState('networkidle', { timeout });
432
- } catch (e) {
433
- console.warn('⚠️ Network idle timeout - continuing anyway');
434
- }
435
- }
436
-
437
- /**
438
- * Scroll to element
439
- *
440
- * @param {Page} page - Playwright page object
441
- * @param {string} selector - CSS selector
442
- */
443
- async function scrollToElement(page, selector) {
444
- await page.locator(selector).scrollIntoViewIfNeeded();
445
- }
446
-
447
- /**
448
- * Wait for element to be visible
449
- *
450
- * @param {Page} page - Playwright page object
451
- * @param {string} selector - CSS selector
452
- * @param {number} timeout - Timeout in ms
453
- */
454
- async function waitForVisible(page, selector, timeout = 10000) {
455
- await page.waitForSelector(selector, { state: 'visible', timeout });
456
- }
457
-
458
- /**
459
- * Check if element exists
460
- *
461
- * @param {Page} page - Playwright page object
462
- * @param {string} selector - CSS selector
463
- * @returns {boolean}
464
- */
465
- async function elementExists(page, selector) {
466
- try {
467
- await page.waitForSelector(selector, { timeout: 1000 });
468
- return true;
469
- } catch {
470
- return false;
471
- }
472
- }
473
-
474
- /**
475
- * Get text content of element
476
- *
477
- * @param {Page} page - Playwright page object
478
- * @param {string} selector - CSS selector
479
- * @returns {string}
480
- */
481
- async function getText(page, selector) {
482
- return await page.locator(selector).textContent();
483
- }
484
-
485
- /**
486
- * Get all matching elements count
487
- *
488
- * @param {Page} page - Playwright page object
489
- * @param {string} selector - CSS selector
490
- * @returns {number}
491
- */
492
- async function countElements(page, selector) {
493
- return await page.locator(selector).count();
494
- }
495
-
496
- // Export all utilities
497
- module.exports = {
498
- detectServers,
499
- safeClick,
500
- safeType,
501
- captureScreenshot,
502
- handleCookieBanner,
503
- extractTableData,
504
- waitForStableDOM,
505
- checkAccessibility,
506
- generateTestReport,
507
- saveTestReport,
508
- waitForNetworkIdle,
509
- scrollToElement,
510
- waitForVisible,
511
- elementExists,
512
- getText,
513
- countElements
514
- };
@@ -1,33 +0,0 @@
1
- {
2
- "name": "e2e-playwright-skill",
3
- "version": "1.0.0",
4
- "description": "End-to-end browser automation and testing skill for SpecWeave using Playwright",
5
- "main": "execute.js",
6
- "scripts": {
7
- "setup": "npm install && npx playwright install chromium",
8
- "install-browsers": "npx playwright install",
9
- "test": "node execute.js --version",
10
- "clean": "rm -f /tmp/e2e-execution-*.js /tmp/e2e-test-*.js"
11
- },
12
- "keywords": [
13
- "playwright",
14
- "e2e",
15
- "testing",
16
- "browser-automation",
17
- "specweave",
18
- "claude-code",
19
- "skill"
20
- ],
21
- "author": "SpecWeave",
22
- "license": "MIT",
23
- "dependencies": {
24
- "playwright": "^1.48.0"
25
- },
26
- "engines": {
27
- "node": ">=14.0.0"
28
- },
29
- "repository": {
30
- "type": "git",
31
- "url": "https://github.com/anton-abyzov/specweave"
32
- }
33
- }
@@ -1,19 +0,0 @@
1
- {
2
- "name": "specweave-tooling",
3
- "description": "SpecWeave skill development and orchestration tools. Create new skills with proper structure, test cases, and activation triggers. Includes skill router for intelligent skill activation based on context. Meta-tooling for extending SpecWeave.",
4
- "version": "0.22.14",
5
- "author": {
6
- "name": "SpecWeave Team",
7
- "url": "https://spec-weave.com"
8
- },
9
- "homepage": "https://spec-weave.com",
10
- "repository": "https://github.com/anton-abyzov/specweave",
11
- "license": "MIT",
12
- "keywords": [
13
- "tooling",
14
- "skills",
15
- "skill-creation",
16
- "development",
17
- "specweave"
18
- ]
19
- }