@codihaus/claude-skills 1.6.28 → 1.7.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.
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: dev-test
3
- description: Automated testing after implementation using Playwright
4
- version: 1.0.0
3
+ description: Automated UI testing using Playwright browser tools. Use when: (1) After completing feature implementation, (2) After fixing bugs, (3) Before code review, (4) Verifying acceptance criteria from specs
4
+ version: 1.1.0
5
5
  ---
6
6
 
7
7
  # /dev-test - Implementation Testing
@@ -113,134 +113,13 @@ Test report showing whether implementation works correctly.
113
113
 
114
114
  ## Test Patterns
115
115
 
116
- Available as reference in original SKILL.md:
117
- - Form submission
118
- - Navigation flow
119
- - API response validation
120
- - Error state testing
116
+ See `references/test-patterns.md` for code examples:
117
+ - Form submission, navigation flow, API response validation, error state testing
118
+ - Test data conventions
119
+ - Common issues and solutions (page not loading, element not found, intermittent failures)
121
120
 
122
121
  Use Playwright MCP tools to interact with browser.
123
122
 
124
- ## Test Patterns
125
-
126
- ### Form Submission
127
-
128
- ```typescript
129
- // 1. Fill form
130
- await browser_fill_form({
131
- fields: [
132
- { name: 'Email', type: 'textbox', ref: 'input-email', value: 'test@test.com' },
133
- { name: 'Password', type: 'textbox', ref: 'input-password', value: 'password123' }
134
- ]
135
- });
136
-
137
- // 2. Submit and wait
138
- await browser_click({ element: 'Submit button', ref: 'btn-submit' });
139
- await browser_wait_for({ text: 'Success' });
140
-
141
- // 3. Check for errors
142
- const errors = await browser_console_messages({ level: 'error' });
143
- ```
144
-
145
- ### Navigation Flow
146
-
147
- ```typescript
148
- // 1. Start at page A
149
- await browser_navigate({ url: '/dashboard' });
150
-
151
- // 2. Click to page B
152
- await browser_click({ element: 'Settings link', ref: 'nav-settings' });
153
- await browser_wait_for({ text: 'Settings' });
154
-
155
- // 3. Verify correct page
156
- const snapshot = await browser_snapshot({});
157
- // Check snapshot contains expected elements
158
- ```
159
-
160
- ### API Response Validation
161
-
162
- ```typescript
163
- // 1. Trigger API call (via form submit or button)
164
- await browser_click({ element: 'Load data', ref: 'btn-load' });
165
- await browser_wait_for({ time: 2 });
166
-
167
- // 2. Check network requests
168
- const requests = await browser_network_requests({});
169
-
170
- // 3. Find the API call
171
- const apiCall = requests.find(r => r.url.includes('/api/data'));
172
-
173
- // 4. Validate
174
- if (apiCall.status >= 400) {
175
- // Report error
176
- }
177
- ```
178
-
179
- ### Error State Testing
180
-
181
- ```typescript
182
- // Test error handling by submitting invalid data
183
- await browser_type({
184
- element: 'email',
185
- ref: 'input-email',
186
- text: 'invalid-email' // No @ symbol
187
- });
188
-
189
- await browser_click({ element: 'Submit', ref: 'btn-submit' });
190
-
191
- // Verify error message appears
192
- const snapshot = await browser_snapshot({});
193
- // Check for validation error in snapshot
194
- ```
195
-
196
- ## Test Data
197
-
198
- Use predictable test data:
199
-
200
- ```typescript
201
- const TEST_DATA = {
202
- validEmail: 'test@example.com',
203
- validPassword: 'Test123!@#',
204
- invalidEmail: 'not-an-email',
205
- shortPassword: '123',
206
- };
207
- ```
208
-
209
- For existing data, check spec or use API to fetch valid IDs.
210
-
211
- ## Common Issues & Solutions
212
-
213
- ### Issue: Page Not Loading
214
-
215
- ```
216
- Symptom: Navigation fails or times out
217
- Check:
218
- 1. Is dev server running? (npm run dev)
219
- 2. Correct port? (3000, 3001, etc.)
220
- 3. Any build errors?
221
- ```
222
-
223
- ### Issue: Element Not Found
224
-
225
- ```
226
- Symptom: Click/type fails with "element not found"
227
- Check:
228
- 1. Take snapshot to see current state
229
- 2. Is element conditionally rendered?
230
- 3. Has ref changed since snapshot?
231
- 4. Is page still loading?
232
- ```
233
-
234
- ### Issue: Intermittent Failures
235
-
236
- ```
237
- Symptom: Test passes sometimes, fails sometimes
238
- Check:
239
- 1. Add wait_for before interactions
240
- 2. Check for race conditions
241
- 3. Increase timeout for slow APIs
242
- ```
243
-
244
123
  ## Integration with /dev-coding
245
124
 
246
125
  When `/dev-coding` completes:
@@ -0,0 +1,119 @@
1
+ # Test Patterns & Common Issues
2
+
3
+ ## Form Submission
4
+
5
+ ```typescript
6
+ // 1. Fill form
7
+ await browser_fill_form({
8
+ fields: [
9
+ { name: 'Email', type: 'textbox', ref: 'input-email', value: 'test@test.com' },
10
+ { name: 'Password', type: 'textbox', ref: 'input-password', value: 'password123' }
11
+ ]
12
+ });
13
+
14
+ // 2. Submit and wait
15
+ await browser_click({ element: 'Submit button', ref: 'btn-submit' });
16
+ await browser_wait_for({ text: 'Success' });
17
+
18
+ // 3. Check for errors
19
+ const errors = await browser_console_messages({ level: 'error' });
20
+ ```
21
+
22
+ ## Navigation Flow
23
+
24
+ ```typescript
25
+ // 1. Start at page A
26
+ await browser_navigate({ url: '/dashboard' });
27
+
28
+ // 2. Click to page B
29
+ await browser_click({ element: 'Settings link', ref: 'nav-settings' });
30
+ await browser_wait_for({ text: 'Settings' });
31
+
32
+ // 3. Verify correct page
33
+ const snapshot = await browser_snapshot({});
34
+ // Check snapshot contains expected elements
35
+ ```
36
+
37
+ ## API Response Validation
38
+
39
+ ```typescript
40
+ // 1. Trigger API call (via form submit or button)
41
+ await browser_click({ element: 'Load data', ref: 'btn-load' });
42
+ await browser_wait_for({ time: 2 });
43
+
44
+ // 2. Check network requests
45
+ const requests = await browser_network_requests({});
46
+
47
+ // 3. Find the API call
48
+ const apiCall = requests.find(r => r.url.includes('/api/data'));
49
+
50
+ // 4. Validate
51
+ if (apiCall.status >= 400) {
52
+ // Report error
53
+ }
54
+ ```
55
+
56
+ ## Error State Testing
57
+
58
+ ```typescript
59
+ // Test error handling by submitting invalid data
60
+ await browser_type({
61
+ element: 'email',
62
+ ref: 'input-email',
63
+ text: 'invalid-email' // No @ symbol
64
+ });
65
+
66
+ await browser_click({ element: 'Submit', ref: 'btn-submit' });
67
+
68
+ // Verify error message appears
69
+ const snapshot = await browser_snapshot({});
70
+ // Check for validation error in snapshot
71
+ ```
72
+
73
+ ## Test Data
74
+
75
+ Use predictable test data:
76
+
77
+ ```typescript
78
+ const TEST_DATA = {
79
+ validEmail: 'test@example.com',
80
+ validPassword: 'Test123!@#',
81
+ invalidEmail: 'not-an-email',
82
+ shortPassword: '123',
83
+ };
84
+ ```
85
+
86
+ For existing data, check spec or use API to fetch valid IDs.
87
+
88
+ ## Common Issues & Solutions
89
+
90
+ ### Page Not Loading
91
+
92
+ ```
93
+ Symptom: Navigation fails or times out
94
+ Check:
95
+ 1. Is dev server running? (npm run dev)
96
+ 2. Correct port? (3000, 3001, etc.)
97
+ 3. Any build errors?
98
+ ```
99
+
100
+ ### Element Not Found
101
+
102
+ ```
103
+ Symptom: Click/type fails with "element not found"
104
+ Check:
105
+ 1. Take snapshot to see current state
106
+ 2. Is element conditionally rendered?
107
+ 3. Has ref changed since snapshot?
108
+ 4. Is page still loading?
109
+ ```
110
+
111
+ ### Intermittent Failures
112
+
113
+ ```
114
+ Symptom: Test passes sometimes, fails sometimes
115
+ Check:
116
+ 1. Add wait_for before interactions
117
+ 2. Check for race conditions
118
+ 3. Increase timeout for slow APIs
119
+ ```
@@ -9,6 +9,7 @@ import ora from 'ora';
9
9
  import inquirer from 'inquirer';
10
10
  import path from 'path';
11
11
  import fs from 'fs-extra';
12
+ import { execSync } from 'child_process';
12
13
 
13
14
  import {
14
15
  checkGlobalDeps,
@@ -24,7 +25,9 @@ import {
24
25
  getInstalledSkills,
25
26
  copySkillsToProject,
26
27
  copyKnowledgeToProject,
27
- copyScriptsToProject
28
+ copyScriptsToProject,
29
+ checkForUpdates,
30
+ cleanupOldSkills
28
31
  } from '../utils/skills.js';
29
32
  import {
30
33
  setupSettings,
@@ -124,8 +127,88 @@ export async function init(options) {
124
127
  }
125
128
 
126
129
  if (action === 'update') {
127
- // TODO: Implement update logic
128
- console.log(chalk.cyan('Updating skills...'));
130
+ console.log('');
131
+
132
+ // Check for CLI package updates first
133
+ const packageSpinner = ora('Checking npm for latest CLI version...').start();
134
+ try {
135
+ const currentVersion = await getCurrentPackageVersion();
136
+ const latestVersion = await getLatestNpmVersion();
137
+
138
+ if (currentVersion !== latestVersion) {
139
+ packageSpinner.info(`CLI update available: ${currentVersion} → ${latestVersion}`);
140
+
141
+ // Auto-update the CLI package
142
+ const updateSpinner = ora('Updating CLI package...').start();
143
+ try {
144
+ execSync('npm install -g @codihaus/claude-skills@latest', {
145
+ encoding: 'utf8',
146
+ stdio: 'pipe'
147
+ });
148
+ updateSpinner.succeed(`CLI package updated to ${latestVersion}`);
149
+ console.log(chalk.green(`\n✅ Please re-run init to update skills with the new CLI version.\n`));
150
+ process.exit(0);
151
+ } catch (updateErr) {
152
+ updateSpinner.fail('Failed to update CLI package');
153
+ console.log(chalk.yellow(`\nTo update manually, run:\n npm install -g @codihaus/claude-skills@latest\n`));
154
+ }
155
+ } else {
156
+ packageSpinner.succeed(`CLI package is up to date (${currentVersion})`);
157
+ }
158
+ } catch (e) {
159
+ packageSpinner.warn('Could not check for CLI updates');
160
+ }
161
+
162
+ console.log('');
163
+
164
+ // Check for skill updates
165
+ const skillSpinner = ora('Checking for skill updates...').start();
166
+ const updates = await checkForUpdates(projectPath);
167
+ skillSpinner.stop();
168
+
169
+ if (updates.length === 0) {
170
+ console.log(chalk.green('✅ All skills are up to date!\n'));
171
+ process.exit(0);
172
+ }
173
+
174
+ console.log(chalk.cyan(`Found ${updates.length} skill update(s) available:\n`));
175
+
176
+ for (const update of updates) {
177
+ console.log(` ${update.name}`);
178
+ console.log(chalk.gray(` ${update.current} → ${update.available}`));
179
+ console.log('');
180
+ }
181
+
182
+ // Apply skill updates
183
+ const updateSkillsSpinner = ora('Updating skills...').start();
184
+
185
+ try {
186
+ const skillNames = updates.map(u => u.name);
187
+
188
+ // Clean up old files first
189
+ updateSkillsSpinner.text = 'Cleaning up old skill files...';
190
+ await cleanupOldSkills(projectPath, skillNames);
191
+
192
+ // Copy new versions
193
+ updateSkillsSpinner.text = 'Installing updated skills...';
194
+ const { copied, errors } = await copySkillsToProject(projectPath, skillNames);
195
+
196
+ if (errors.length > 0) {
197
+ updateSkillsSpinner.warn(`Updated ${copied.length} skills with ${errors.length} errors`);
198
+ for (const err of errors) {
199
+ console.log(chalk.red(` ✗ ${err.name}: ${err.error}`));
200
+ }
201
+ } else {
202
+ updateSkillsSpinner.succeed(`Updated ${copied.length} skills`);
203
+ }
204
+ } catch (e) {
205
+ updateSkillsSpinner.fail('Update failed');
206
+ console.error(chalk.red(e.message));
207
+ process.exit(1);
208
+ }
209
+
210
+ console.log(chalk.green('\n✅ Update complete!\n'));
211
+ process.exit(0);
129
212
  }
130
213
  }
131
214
 
@@ -409,3 +492,30 @@ export async function init(options) {
409
492
  console.log('');
410
493
  }
411
494
  }
495
+
496
+ /**
497
+ * Get current package version
498
+ */
499
+ async function getCurrentPackageVersion() {
500
+ try {
501
+ const packageJson = await fs.readJson(path.join(import.meta.dirname, '../../package.json'));
502
+ return packageJson.version;
503
+ } catch (e) {
504
+ return 'unknown';
505
+ }
506
+ }
507
+
508
+ /**
509
+ * Get latest version from npm
510
+ */
511
+ async function getLatestNpmVersion() {
512
+ try {
513
+ const result = execSync('npm view @codihaus/claude-skills version', {
514
+ encoding: 'utf8',
515
+ stdio: ['pipe', 'pipe', 'ignore']
516
+ });
517
+ return result.trim();
518
+ } catch (e) {
519
+ throw new Error('Could not fetch latest version from npm');
520
+ }
521
+ }
@@ -25,7 +25,21 @@ export async function update(options) {
25
25
 
26
26
  if (currentVersion !== latestVersion) {
27
27
  packageSpinner.info(`Package update available: ${currentVersion} → ${latestVersion}`);
28
- console.log(chalk.yellow(`\nTo update the CLI package, run:\n npm install -g @codihaus/claude-skills@latest\n`));
28
+
29
+ // Auto-update the CLI package
30
+ const updateSpinner = ora('Updating CLI package...').start();
31
+ try {
32
+ execSync('npm install -g @codihaus/claude-skills@latest', {
33
+ encoding: 'utf8',
34
+ stdio: 'pipe'
35
+ });
36
+ updateSpinner.succeed(`CLI package updated to ${latestVersion}`);
37
+ console.log(chalk.green(`\n✅ Please re-run this command to update skills with the new CLI version.\n`));
38
+ process.exit(0);
39
+ } catch (updateErr) {
40
+ updateSpinner.fail('Failed to update CLI package');
41
+ console.log(chalk.yellow(`\nTo update manually, run:\n npm install -g @codihaus/claude-skills@latest\n`));
42
+ }
29
43
  } else {
30
44
  packageSpinner.succeed(`CLI package is up to date (${currentVersion})`);
31
45
  }