twd-cli 1.0.1
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.
- package/.github/ISSUE_TEMPLATE/bug_report.md +63 -0
- package/.github/ISSUE_TEMPLATE/feature_request.md +52 -0
- package/.github/pull_request_template.md +43 -0
- package/.github/workflows/publish.yml +28 -0
- package/LICENSE +21 -0
- package/README.md +82 -0
- package/bin/twd-cli.js +25 -0
- package/package.json +30 -0
- package/src/config.js +29 -0
- package/src/index.js +78 -0
- package/twd.config.example.json +9 -0
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Bug Report
|
|
3
|
+
about: Create a report to help us improve TWD
|
|
4
|
+
title: '[BUG] '
|
|
5
|
+
labels: bug
|
|
6
|
+
assignees: ''
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Description
|
|
10
|
+
|
|
11
|
+
A clear and concise description of what the bug is.
|
|
12
|
+
|
|
13
|
+
## Environment Information
|
|
14
|
+
|
|
15
|
+
Please provide the following information to help us reproduce the issue:
|
|
16
|
+
|
|
17
|
+
### Framework & Build Tool
|
|
18
|
+
- **Framework**: [e.g., React, Astro, Remix]
|
|
19
|
+
- **Build Tool**: [e.g., Vite, Webpack, Create React App]
|
|
20
|
+
- **Framework Version**: [e.g., React 18.2.0]
|
|
21
|
+
|
|
22
|
+
### Runtime Environment
|
|
23
|
+
- **Node Version**: [e.g., 20.10.0]
|
|
24
|
+
- **npm/yarn/pnpm Version**: [e.g., npm 10.2.0]
|
|
25
|
+
- **Browser**: [e.g., Chrome 120, Firefox 121, Safari 17]
|
|
26
|
+
- **Browser Version**: [e.g., 120.0.6099.109]
|
|
27
|
+
|
|
28
|
+
### TWD Version
|
|
29
|
+
- **twd-js Version**: [e.g., 1.2.3]
|
|
30
|
+
|
|
31
|
+
## How to Reproduce
|
|
32
|
+
|
|
33
|
+
1. How do you run your tests? [e.g., `npm run dev`, `vite`, `npm start`]
|
|
34
|
+
2. What command do you use to start your development server?
|
|
35
|
+
3. Steps to reproduce the behavior:
|
|
36
|
+
- Step 1: ...
|
|
37
|
+
- Step 2: ...
|
|
38
|
+
- Step 3: ...
|
|
39
|
+
|
|
40
|
+
## Test Code
|
|
41
|
+
|
|
42
|
+
**Please paste your complete test file(s) here:**
|
|
43
|
+
|
|
44
|
+
## Expected Behavior
|
|
45
|
+
|
|
46
|
+
A clear and concise description of what you expected to happen.
|
|
47
|
+
|
|
48
|
+
## Actual Behavior
|
|
49
|
+
|
|
50
|
+
A clear and concise description of what actually happened.
|
|
51
|
+
|
|
52
|
+
## Screenshots
|
|
53
|
+
|
|
54
|
+
If applicable, add screenshots to help explain your problem. Screenshots are **highly appreciated** and help us understand the issue better.
|
|
55
|
+
|
|
56
|
+
## Additional Context
|
|
57
|
+
|
|
58
|
+
Add any other context about the problem here. For example:
|
|
59
|
+
|
|
60
|
+
## Possible Solution
|
|
61
|
+
|
|
62
|
+
If you have ideas on how to fix this, please share them here (optional).
|
|
63
|
+
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Feature Request
|
|
3
|
+
about: Suggest an idea for TWD cli
|
|
4
|
+
title: '[FEATURE] '
|
|
5
|
+
labels: enhancement
|
|
6
|
+
assignees: ''
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Feature Description
|
|
10
|
+
|
|
11
|
+
A clear and concise description of the feature you'd like to see.
|
|
12
|
+
|
|
13
|
+
## Why is this feature needed?
|
|
14
|
+
|
|
15
|
+
Explain the problem or use case this feature would solve. What pain point does it address?
|
|
16
|
+
|
|
17
|
+
## Proposed Solution
|
|
18
|
+
|
|
19
|
+
Describe how you envision this feature working. Be as detailed as possible.
|
|
20
|
+
|
|
21
|
+
### API/Interface Design
|
|
22
|
+
|
|
23
|
+
How would developers use this feature? Please provide example code:
|
|
24
|
+
|
|
25
|
+
### Implementation Approach
|
|
26
|
+
|
|
27
|
+
If you have ideas on how this could be implemented, please share them here.
|
|
28
|
+
|
|
29
|
+
## Breaking Changes
|
|
30
|
+
|
|
31
|
+
- [ ] This feature would introduce breaking changes
|
|
32
|
+
- [ ] This feature would be backward compatible
|
|
33
|
+
|
|
34
|
+
If breaking changes are involved, please explain:
|
|
35
|
+
- What would break?
|
|
36
|
+
- How would migration work?
|
|
37
|
+
- What's the deprecation path?
|
|
38
|
+
|
|
39
|
+
## Testing Strategy
|
|
40
|
+
|
|
41
|
+
How would this feature be tested? Please describe:
|
|
42
|
+
- What test scenarios should be covered?
|
|
43
|
+
- How would we verify it works correctly?
|
|
44
|
+
- Are there edge cases to consider?
|
|
45
|
+
|
|
46
|
+
## Benefits
|
|
47
|
+
|
|
48
|
+
What benefits would this feature bring to TWD users?
|
|
49
|
+
- Performance improvements?
|
|
50
|
+
- Better developer experience?
|
|
51
|
+
- New capabilities?
|
|
52
|
+
- Easier testing workflows?
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
## Description
|
|
2
|
+
|
|
3
|
+
Please include a summary of the changes and the related issue. Include relevant motivation and context.
|
|
4
|
+
|
|
5
|
+
Fixes # (issue)
|
|
6
|
+
|
|
7
|
+
## Type of Change
|
|
8
|
+
|
|
9
|
+
Please delete options that are not relevant:
|
|
10
|
+
|
|
11
|
+
- [ ] Bug fix (non-breaking change which fixes an issue)
|
|
12
|
+
- [ ] New feature (non-breaking change which adds functionality)
|
|
13
|
+
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
|
|
14
|
+
- [ ] Documentation update
|
|
15
|
+
- [ ] Code refactoring
|
|
16
|
+
- [ ] Performance improvement
|
|
17
|
+
- [ ] Test addition or update
|
|
18
|
+
|
|
19
|
+
## Testing
|
|
20
|
+
|
|
21
|
+
- [ ] I have added tests that prove my fix is effective or that my feature works
|
|
22
|
+
- [ ] All existing tests pass
|
|
23
|
+
- [ ] New and existing unit tests pass locally
|
|
24
|
+
- [ ] I have tested this change manually
|
|
25
|
+
|
|
26
|
+
**Note**: Pull requests without tests will not be reviewed. Please ensure you've added appropriate test coverage.
|
|
27
|
+
|
|
28
|
+
### Test Details
|
|
29
|
+
|
|
30
|
+
Describe the tests you've added or updated:
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
## Documentation
|
|
34
|
+
|
|
35
|
+
- [ ] I have updated the documentation accordingly
|
|
36
|
+
- [ ] I have added/updated code comments where necessary
|
|
37
|
+
- [ ] The changes are reflected in the relevant documentation files
|
|
38
|
+
|
|
39
|
+
**Note**: If your change affects the public API or adds new features, documentation updates are required.
|
|
40
|
+
|
|
41
|
+
## Screenshots (if applicable)
|
|
42
|
+
|
|
43
|
+
If your changes affect the UI or add visual features, please add screenshots:
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
name: Publish
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
publish:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
|
|
11
|
+
steps:
|
|
12
|
+
- name: Checkout repo
|
|
13
|
+
uses: actions/checkout@v5
|
|
14
|
+
|
|
15
|
+
- name: Setup Node.js
|
|
16
|
+
uses: actions/setup-node@v5
|
|
17
|
+
with:
|
|
18
|
+
node-version: 24
|
|
19
|
+
registry-url: https://registry.npmjs.org/
|
|
20
|
+
cache: npm
|
|
21
|
+
|
|
22
|
+
- name: Install dependencies
|
|
23
|
+
run: npm ci
|
|
24
|
+
|
|
25
|
+
- name: Publish to npm
|
|
26
|
+
run: npm publish --access public
|
|
27
|
+
env:
|
|
28
|
+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 BRIKEV
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# twd-cli
|
|
2
|
+
|
|
3
|
+
CLI tool for running TWD (Test with Documentation) tests using Puppeteer in CI/CD environments.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install twd-cli
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Or use directly with npx:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npx twd-cli run
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Usage
|
|
18
|
+
|
|
19
|
+
### Basic Usage
|
|
20
|
+
|
|
21
|
+
Run tests with default configuration:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npx twd-cli run
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### Configuration
|
|
28
|
+
|
|
29
|
+
Create a `twd.config.json` file in your project root to customize settings:
|
|
30
|
+
|
|
31
|
+
```json
|
|
32
|
+
{
|
|
33
|
+
"url": "http://localhost:5173",
|
|
34
|
+
"timeout": 10000,
|
|
35
|
+
"coverage": true,
|
|
36
|
+
"coverageDir": "./coverage",
|
|
37
|
+
"nycOutputDir": "./.nyc_output",
|
|
38
|
+
"headless": true,
|
|
39
|
+
"puppeteerArgs": ["--no-sandbox", "--disable-setuid-sandbox"]
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Configuration Options
|
|
44
|
+
|
|
45
|
+
| Option | Type | Default | Description |
|
|
46
|
+
|--------|------|---------|-------------|
|
|
47
|
+
| `url` | string | `"http://localhost:5173"` | The URL of your development server |
|
|
48
|
+
| `timeout` | number | `10000` | Timeout in milliseconds for page load |
|
|
49
|
+
| `coverage` | boolean | `true` | Enable/disable code coverage collection |
|
|
50
|
+
| `coverageDir` | string | `"./coverage"` | Directory to store coverage reports |
|
|
51
|
+
| `nycOutputDir` | string | `"./.nyc_output"` | Directory for NYC output |
|
|
52
|
+
| `headless` | boolean | `true` | Run browser in headless mode |
|
|
53
|
+
| `puppeteerArgs` | string[] | `["--no-sandbox", "--disable-setuid-sandbox"]` | Additional Puppeteer launch arguments |
|
|
54
|
+
|
|
55
|
+
## How It Works
|
|
56
|
+
|
|
57
|
+
1. Launches a Puppeteer browser instance
|
|
58
|
+
2. Navigates to your specified URL
|
|
59
|
+
3. Waits for your app to be ready
|
|
60
|
+
4. Executes all TWD tests via `window.__testRunner`
|
|
61
|
+
5. Collects and reports test results
|
|
62
|
+
6. Optionally collects code coverage data
|
|
63
|
+
7. Exits with appropriate code (0 for success, 1 for failures)
|
|
64
|
+
|
|
65
|
+
## CI/CD Integration
|
|
66
|
+
|
|
67
|
+
The CLI exits with code 1 if any tests fail, making it perfect for CI/CD pipelines:
|
|
68
|
+
|
|
69
|
+
```yaml
|
|
70
|
+
# Example GitHub Actions workflow
|
|
71
|
+
- name: Run TWD Tests
|
|
72
|
+
run: npx twd-cli run
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Requirements
|
|
76
|
+
|
|
77
|
+
- Node.js >= 18.0.0
|
|
78
|
+
- A running development server with TWD tests
|
|
79
|
+
|
|
80
|
+
## License
|
|
81
|
+
|
|
82
|
+
ISC
|
package/bin/twd-cli.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { runTests } from '../src/index.js';
|
|
4
|
+
|
|
5
|
+
const command = process.argv[2];
|
|
6
|
+
|
|
7
|
+
if (command === 'run') {
|
|
8
|
+
try {
|
|
9
|
+
await runTests();
|
|
10
|
+
} catch (error) {
|
|
11
|
+
console.error('Error running tests:', error);
|
|
12
|
+
process.exit(1);
|
|
13
|
+
}
|
|
14
|
+
} else {
|
|
15
|
+
console.log(`
|
|
16
|
+
twd-cli - Test runner for TWD tests
|
|
17
|
+
|
|
18
|
+
Usage:
|
|
19
|
+
npx twd-cli run Run all tests
|
|
20
|
+
|
|
21
|
+
Options:
|
|
22
|
+
Create a twd.config.json file in your project root to customize settings.
|
|
23
|
+
`);
|
|
24
|
+
process.exit(command ? 1 : 0);
|
|
25
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "twd-cli",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "CLI tool for running TWD tests with Puppeteer",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "src/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"twd-cli": "./bin/twd-cli.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
|
12
|
+
"execute:cli": "node ./bin/twd-cli.js"
|
|
13
|
+
},
|
|
14
|
+
"keywords": [
|
|
15
|
+
"twd",
|
|
16
|
+
"testing",
|
|
17
|
+
"cli",
|
|
18
|
+
"puppeteer",
|
|
19
|
+
"browser-testing"
|
|
20
|
+
],
|
|
21
|
+
"author": "",
|
|
22
|
+
"license": "ISC",
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"puppeteer": "^24.31.0",
|
|
25
|
+
"twd-js": "^1.2.0"
|
|
26
|
+
},
|
|
27
|
+
"engines": {
|
|
28
|
+
"node": ">=18.0.0"
|
|
29
|
+
}
|
|
30
|
+
}
|
package/src/config.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
|
|
4
|
+
const DEFAULT_CONFIG = {
|
|
5
|
+
url: 'http://localhost:5173',
|
|
6
|
+
timeout: 10000,
|
|
7
|
+
coverage: true,
|
|
8
|
+
coverageDir: './coverage',
|
|
9
|
+
nycOutputDir: './.nyc_output',
|
|
10
|
+
headless: true,
|
|
11
|
+
puppeteerArgs: ['--no-sandbox', '--disable-setuid-sandbox'],
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export function loadConfig() {
|
|
15
|
+
const configPath = path.resolve(process.cwd(), 'twd.config.json');
|
|
16
|
+
|
|
17
|
+
if (fs.existsSync(configPath)) {
|
|
18
|
+
try {
|
|
19
|
+
const configFile = fs.readFileSync(configPath, 'utf-8');
|
|
20
|
+
const userConfig = JSON.parse(configFile);
|
|
21
|
+
return { ...DEFAULT_CONFIG, ...userConfig };
|
|
22
|
+
} catch (error) {
|
|
23
|
+
console.warn('Warning: Could not parse twd.config.json, using defaults:', error.message);
|
|
24
|
+
return DEFAULT_CONFIG;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return DEFAULT_CONFIG;
|
|
29
|
+
}
|
package/src/index.js
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import puppeteer from 'puppeteer';
|
|
4
|
+
import { reportResults, executeTests } from 'twd-js/runner-ci';
|
|
5
|
+
import { loadConfig } from './config.js';
|
|
6
|
+
|
|
7
|
+
export async function runTests() {
|
|
8
|
+
const config = loadConfig();
|
|
9
|
+
const workingDir = process.cwd();
|
|
10
|
+
|
|
11
|
+
console.log('Starting TWD test runner...');
|
|
12
|
+
console.log('Configuration:', JSON.stringify(config, null, 2));
|
|
13
|
+
|
|
14
|
+
const browser = await puppeteer.launch({
|
|
15
|
+
headless: config.headless,
|
|
16
|
+
args: config.puppeteerArgs,
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
const page = await browser.newPage();
|
|
20
|
+
console.time('Total Test Time');
|
|
21
|
+
|
|
22
|
+
try {
|
|
23
|
+
// Navigate to your development server
|
|
24
|
+
console.log(`Navigating to ${config.url} ...`);
|
|
25
|
+
await page.goto(config.url);
|
|
26
|
+
|
|
27
|
+
// Wait for the selector to be available
|
|
28
|
+
await page.waitForSelector("[data-testid=\"twd-sidebar\"]", { timeout: config.timeout });
|
|
29
|
+
console.log('Page loaded. Starting tests...');
|
|
30
|
+
|
|
31
|
+
// Execute all tests
|
|
32
|
+
const { handlers, testStatus } = await page.evaluate(async () => {
|
|
33
|
+
return await executeTests();
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
console.log(`Tests to report: ${testStatus.length}`);
|
|
37
|
+
|
|
38
|
+
// Display results in console
|
|
39
|
+
reportResults(handlers, testStatus);
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
// Exit with appropriate code
|
|
43
|
+
const hasFailures = testStatus.some(test => test.status === 'fail');
|
|
44
|
+
console.timeEnd('Total Test Time');
|
|
45
|
+
// Handle code coverage if enabled
|
|
46
|
+
if (config.coverage && !hasFailures) {
|
|
47
|
+
const coverage = await page.evaluate(() => window.__coverage__);
|
|
48
|
+
if (coverage) {
|
|
49
|
+
console.log('Collecting code coverage data...');
|
|
50
|
+
const coverageDir = path.resolve(workingDir, config.coverageDir);
|
|
51
|
+
const nycDir = path.resolve(workingDir, config.nycOutputDir);
|
|
52
|
+
|
|
53
|
+
if (!fs.existsSync(nycDir)) {
|
|
54
|
+
fs.mkdirSync(nycDir, { recursive: true });
|
|
55
|
+
}
|
|
56
|
+
if (!fs.existsSync(coverageDir)) {
|
|
57
|
+
fs.mkdirSync(coverageDir, { recursive: true });
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const coveragePath = path.join(nycDir, 'out.json');
|
|
61
|
+
fs.writeFileSync(coveragePath, JSON.stringify(coverage));
|
|
62
|
+
console.log(`Code coverage data written to ${coveragePath}`);
|
|
63
|
+
} else {
|
|
64
|
+
console.log('No code coverage data found.');
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
await browser.close();
|
|
69
|
+
console.log('Browser closed.');
|
|
70
|
+
|
|
71
|
+
process.exit(hasFailures ? 1 : 0);
|
|
72
|
+
|
|
73
|
+
} catch (error) {
|
|
74
|
+
console.error('Error running tests:', error);
|
|
75
|
+
await browser.close();
|
|
76
|
+
process.exit(1);
|
|
77
|
+
}
|
|
78
|
+
}
|