Skip to content

Commit 280845e

Browse files
authored
Test coverage reporting (#15)
* test infra wip * gh workflow summary * reporting in ci * webdav coverage/test execution helpers * license * test coverage examples
1 parent 06a9aa8 commit 280845e

File tree

21 files changed

+1894
-7
lines changed

21 files changed

+1894
-7
lines changed

.github/workflows/ci.yml

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@ on:
88
branches:
99
- main
1010

11+
permissions:
12+
contents: read
13+
actions: read
14+
checks: write
15+
1116
jobs:
1217
test:
1318
runs-on: ubuntu-latest
@@ -49,5 +54,56 @@ jobs:
4954
- name: Build packages
5055
run: pnpm -r run build
5156

52-
- name: Run tests and lint
53-
run: pnpm -r run test
57+
- name: Run SDK tests
58+
id: sdk-test
59+
working-directory: packages/b2c-tooling-sdk
60+
run: pnpm run test:ci && pnpm run lint
61+
62+
- name: Run CLI tests
63+
id: cli-test
64+
if: always() && steps.sdk-test.conclusion != 'cancelled'
65+
working-directory: packages/b2c-cli
66+
run: pnpm run test:ci && pnpm run lint
67+
68+
- name: Test Report
69+
uses: dorny/test-reporter@fe45e9537387dac839af0d33ba56eed8e24189e8 # v2.3.0
70+
if: always() && steps.sdk-test.conclusion != 'cancelled'
71+
with:
72+
name: Test Results (Node ${{ matrix.node-version }})
73+
path: 'packages/*/test-results.json'
74+
reporter: mocha-json
75+
76+
- name: Generate coverage summary
77+
if: always() && steps.sdk-test.conclusion != 'cancelled'
78+
run: |
79+
echo "## Coverage (Node ${{ matrix.node-version }})" >> $GITHUB_STEP_SUMMARY
80+
echo "" >> $GITHUB_STEP_SUMMARY
81+
82+
# SDK Coverage
83+
if [ -f "packages/b2c-tooling-sdk/coverage/lcov.info" ]; then
84+
echo "### @salesforce/b2c-tooling-sdk" >> $GITHUB_STEP_SUMMARY
85+
echo '```' >> $GITHUB_STEP_SUMMARY
86+
cd packages/b2c-tooling-sdk && pnpm c8 report --reporter=text-summary 2>/dev/null | tail -n 6 >> $GITHUB_STEP_SUMMARY
87+
cd ../..
88+
echo '```' >> $GITHUB_STEP_SUMMARY
89+
echo "" >> $GITHUB_STEP_SUMMARY
90+
fi
91+
92+
# CLI Coverage
93+
if [ -f "packages/b2c-cli/coverage/lcov.info" ]; then
94+
echo "### @salesforce/b2c-cli" >> $GITHUB_STEP_SUMMARY
95+
echo '```' >> $GITHUB_STEP_SUMMARY
96+
cd packages/b2c-cli && pnpm c8 report --reporter=text-summary 2>/dev/null | tail -n 6 >> $GITHUB_STEP_SUMMARY
97+
cd ../..
98+
echo '```' >> $GITHUB_STEP_SUMMARY
99+
fi
100+
101+
- name: Upload coverage reports
102+
if: always() && steps.sdk-test.conclusion != 'cancelled'
103+
uses: actions/upload-artifact@v4
104+
with:
105+
name: coverage-reports-node-${{ matrix.node-version }}
106+
path: |
107+
packages/b2c-tooling-sdk/coverage/
108+
packages/b2c-cli/coverage/
109+
retention-days: 30

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
/dist
66
/tmp
77
/node_modules
8+
/coverage
89
oclif.manifest.json
910

1011

AGENTS.md

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,3 +79,75 @@ Features:
7979
- Dynamic column widths based on content
8080
- Supports `extended` flag on columns for optional fields
8181
- Use `TableRenderer` class directly for column validation helpers (e.g., `--columns` flag support)
82+
83+
## Testing
84+
85+
Tests use Mocha + Chai with c8 for coverage. HTTP mocking uses MSW (Mock Service Worker).
86+
87+
### Running Tests
88+
89+
```bash
90+
# Run all tests with coverage
91+
pnpm run test
92+
93+
# Run tests for specific package
94+
pnpm --filter @salesforce/b2c-tooling-sdk run test
95+
96+
# Run single test file (no coverage, faster)
97+
cd packages/b2c-tooling-sdk
98+
pnpm mocha "test/clients/webdav.test.ts"
99+
100+
# Run tests matching pattern
101+
pnpm mocha --grep "mkcol" "test/**/*.test.ts"
102+
103+
# Watch mode for TDD
104+
pnpm --filter @salesforce/b2c-tooling-sdk run test:watch
105+
```
106+
107+
### Writing Tests
108+
109+
- Place tests in `packages/<package>/test/` mirroring the src structure
110+
- Use `.test.ts` suffix for test files
111+
- Import from package names, not relative paths:
112+
```typescript
113+
// Good - uses package exports
114+
import { WebDavClient } from '@salesforce/b2c-tooling-sdk/clients';
115+
116+
// Avoid - relative paths
117+
import { WebDavClient } from '../../src/clients/webdav.js';
118+
```
119+
120+
### HTTP Mocking with MSW
121+
122+
For testing HTTP clients, use MSW to mock at the network level:
123+
124+
```typescript
125+
import { http, HttpResponse } from 'msw';
126+
import { setupServer } from 'msw/node';
127+
128+
const server = setupServer();
129+
130+
before(() => server.listen({ onUnhandledRequest: 'error' }));
131+
afterEach(() => server.resetHandlers());
132+
after(() => server.close());
133+
134+
it('makes HTTP request', async () => {
135+
server.use(
136+
http.get('https://example.com/api/*', () => {
137+
return HttpResponse.json({ data: 'test' });
138+
}),
139+
);
140+
141+
// Test code that makes HTTP requests...
142+
});
143+
```
144+
145+
### Test Helpers
146+
147+
- `test/helpers/mock-auth.ts` - Mock AuthStrategy for testing HTTP clients
148+
149+
### Coverage
150+
151+
- Coverage reports generated in `coverage/` directory
152+
- SDK package has 5% minimum threshold (will increase as tests are added)
153+
- CI publishes coverage summary to GitHub Actions job summary

README.md

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,42 @@ pnpm --filter @salesforce/b2c-cli run build
5959
pnpm --filter @salesforce/b2c-tooling-sdk run build
6060
```
6161

62-
### Testing and Linting
62+
### Testing
63+
64+
Tests use [Mocha](https://mochajs.org/) + [Chai](https://www.chaijs.com/) with [c8](https://github.com/bcoe/c8) for coverage. HTTP mocking uses [MSW](https://mswjs.io/).
6365

6466
```bash
65-
# Run all tests (also runs linter after tests)
67+
# Run all tests with coverage (also runs linter after tests)
6668
pnpm test
6769

70+
# Run tests for a specific package
71+
pnpm --filter @salesforce/b2c-tooling-sdk run test
72+
73+
# Run tests without coverage (faster)
74+
pnpm --filter @salesforce/b2c-tooling-sdk run test:unit
75+
76+
# Watch mode for TDD
77+
pnpm --filter @salesforce/b2c-tooling-sdk run test:watch
78+
79+
# Run a specific test file
80+
cd packages/b2c-tooling-sdk
81+
pnpm mocha "test/clients/webdav.test.ts"
82+
83+
# Run tests matching a pattern
84+
pnpm mocha --grep "uploads a file" "test/**/*.test.ts"
85+
```
86+
87+
#### Coverage
88+
89+
Coverage reports are generated in each package's `coverage/` directory:
90+
- `coverage/index.html` - HTML report
91+
- `coverage/lcov.info` - LCOV format for CI integration
92+
93+
The SDK package has a 5% coverage threshold that will fail the build if not met.
94+
95+
### Linting
96+
97+
```bash
6898
# Run linter only
6999
pnpm --filter @salesforce/b2c-cli run lint
70100
pnpm --filter @salesforce/b2c-tooling-sdk run lint

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
"scripts": {
77
"start": "pnpm --filter @salesforce/b2c-cli run dev",
88
"test": "pnpm -r test",
9+
"test:unit": "pnpm -r run test:unit",
10+
"coverage": "pnpm -r run coverage",
911
"format": "pnpm -r run format",
1012
"lint": "pnpm -r run lint",
1113
"build": "pnpm -r run build",
@@ -16,7 +18,7 @@
1618
},
1719
"keywords": [],
1820
"author": "",
19-
"license": "ISC",
21+
"license": "MIT",
2022
"packageManager": "pnpm@10.17.1",
2123
"devDependencies": {
2224
"typedoc": "^0.28.14",

packages/b2c-cli/.c8rc.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"all": true,
3+
"src": ["src"],
4+
"exclude": [
5+
"test/**",
6+
"**/*.d.ts"
7+
],
8+
"reporter": ["text", "text-summary", "html", "lcov"],
9+
"report-dir": "coverage"
10+
}

packages/b2c-cli/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
/build
77
/tmp
88
/node_modules
9+
/coverage
10+
test-results.json
911
oclif.manifest.json
1012

1113

packages/b2c-cli/package.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
"@types/chai": "^4",
2727
"@types/mocha": "^10",
2828
"@types/node": "^18",
29+
"c8": "^10.1.3",
2930
"chai": "^4",
3031
"eslint": "^9",
3132
"eslint-config-oclif": "^6",
@@ -116,7 +117,10 @@
116117
"posttest": "pnpm run lint",
117118
"prepack": "oclif manifest && oclif readme",
118119
"pretest": "tsc --noEmit -p test",
119-
"test": "OCLIF_TEST_ROOT=. mocha --forbid-only \"test/**/*.test.ts\"",
120+
"test": "c8 env OCLIF_TEST_ROOT=. mocha --forbid-only \"test/**/*.test.ts\"",
121+
"test:ci": "c8 env OCLIF_TEST_ROOT=. mocha --forbid-only --reporter json --reporter-option output=test-results.json \"test/**/*.test.ts\"",
122+
"test:unit": "env OCLIF_TEST_ROOT=. mocha --forbid-only \"test/**/*.test.ts\"",
123+
"coverage": "c8 report",
120124
"version": "oclif readme && git add README.md",
121125
"dev": "node ./bin/dev.js"
122126
},
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"all": true,
3+
"src": ["src"],
4+
"exclude": [
5+
"src/clients/*.generated.ts",
6+
"test/**",
7+
"**/*.d.ts"
8+
],
9+
"reporter": ["text", "text-summary", "html", "lcov"],
10+
"report-dir": "coverage",
11+
"check-coverage": true,
12+
"lines": 5,
13+
"functions": 5,
14+
"branches": 5,
15+
"statements": 5
16+
}

packages/b2c-tooling-sdk/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
/dist
66
/tmp
77
/node_modules
8+
/coverage
9+
test-results.json
810

911

1012
yarn.lock

0 commit comments

Comments
 (0)