Skip to content

Commit 7cc42ba

Browse files
feat: - Methods saveHistory is removed and no more needed.
- config.json file obligatory fields are updated. Now only the base path to reports files should be provided in the config.json file - see the below example. - History of the coverage changes is now reflected in HTML report and stored individually per service for all supported clients - History is tracked for test runs with as minimum of 10 minutes intervals (this limitation is made to unify the behaviour between clients because the Playwright spawns new workers if API test fails and this is causing the reset of the stats) - Support for Postman collections coverage calculation agains openAPI specification with cli command or inlline script - To maintain the history of the test coverage - do not delete appropriate service json files from the output directory
1 parent 1531c3c commit 7cc42ba

21 files changed

+4502
-1259
lines changed

config.json

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,18 @@
3232
"repository": "",
3333
"swaggerUrl": "https://raw.githubusercontent.com/ServeRest/ServeRest/trunk/docs/swagger.json",
3434
"swaggerFile": ""
35+
},
36+
{
37+
"key": "Parabank-api-service",
38+
"name": "Parabank API",
39+
"tags": [
40+
"API",
41+
"COVERAGE"
42+
],
43+
"repository": "",
44+
"swaggerUrl": "https://parabank.parasoft.com/parabank/services/bank/openapi.yaml",
45+
"swaggerFile": ""
3546
}
3647
],
37-
"json-report-path": "./reports/report.json",
38-
"json-report-history-path": "./reports/history.json",
39-
"html-report-path": "./reports/index.html",
40-
"stats-path": "./reports/stats.json"
48+
"report-path": "./reports"
4149
}

e2e/api-coverage-example.js

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,6 @@ async function exampleWithAxios() {
3838
// Make another request
3939
console.log('Making second request...')
4040
const petsResponse = await axiosInstance.get('/pet/findByStatus?status=available')
41-
const petsResponse2 = await axiosInstance.get('/pet/findByStatus?status=available')
42-
const petsResponse3 = await axiosInstance.get('/pet/findByStatus?status=available')
4341
console.log('Available pets count:', petsResponse.data.length)
4442

4543
// Get coverage statistics before stopping
@@ -52,9 +50,6 @@ async function exampleWithAxios() {
5250
// Stop tracking when done
5351
apiCoverage.stopTracking(axiosInstance)
5452
console.log('Axios tracking stopped')
55-
56-
// Save coverage history
57-
await apiCoverage.saveHistory()
5853
// Generate a report
5954
await apiCoverage.generateReport()
6055
} catch (error) {
@@ -89,8 +84,6 @@ async function exampleWithFetch() {
8984
// Get coverage statistics
9085
const stats = apiCoverage.getCoverageStats()
9186
console.log('Coverage stats:', stats)
92-
// Save coverage history
93-
await apiCoverage.saveHistory()
9487

9588
// Generate a report
9689
await apiCoverage.generateReport()
@@ -111,8 +104,6 @@ async function exampleManualRegistration() {
111104
// Get coverage statistics
112105
const stats = apiCoverage.getCoverageStats()
113106
console.log('Coverage stats:', stats)
114-
// Save coverage history
115-
await apiCoverage.saveHistory()
116107

117108
// Generate a report
118109
await apiCoverage.generateReport()

e2e/fakestore_coverage_api.spec.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,10 @@ await apiCoverage.loadSpec('https://fakestoreapi.com/fakestoreapi.json')
77
apiCoverage.setDebug(false)
88

99
test.beforeEach(async ({ request }) => {
10-
apiCoverage.startTracking(request, { clientType: 'playwright', coverage: 'detailed' })
10+
apiCoverage.startTracking(request, { clientType: 'playwright', coverage: 'basic' })
1111
})
1212

1313
test.afterEach(async ({ request }) => {
14-
await apiCoverage.saveHistory()
1514
apiCoverage.stopTracking(request)
1615
})
1716
test.afterAll(async () => {

e2e/petstore_coverage_api.spec.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
1-
import { expect, test } from '@fixtures/fixture.js'
1+
import { expect, test } from '@playwright/test'
22
import { ApiCoverage } from 'api-coverage-tracker'
33
import config from '../config.json' with { type: 'json' }
44

55
const apiCoverage = new ApiCoverage(config)
66
await apiCoverage.loadSpec('https://petstore.swagger.io/v2/swagger.json')
77
apiCoverage.setDebug(false)
88
test.beforeEach(async ({ request }) => {
9-
apiCoverage.startTracking(request, { clientType: 'playwright', coverage: 'basic' })
9+
apiCoverage.startTracking(request, { clientType: 'playwright', coverage: 'detailed' })
1010
})
1111

1212
test.afterEach(async ({ request }) => {
13-
await apiCoverage.saveHistory()
1413
apiCoverage.stopTracking(request) // always runs even on test failure
1514
})
1615
test.afterAll(async () => {

e2e/postman-example.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { ApiCoverage } from '../utils/api-coverage.js'
44
const apiCoverage = new ApiCoverage(config)
55
const openAPISpec = 'https://fakestoreapi.com/fakestoreapi.json'
66
const collectionPath = './e2e/data/FakeStoreAPI.postman_collection.json'
7+
apiCoverage.setDebug(false)
78
await apiCoverage.loadSpec(openAPISpec)
8-
apiCoverage.registerPostmanRequests({ collectionPath, coverage: 'basic' })
9-
await apiCoverage.saveHistory()
9+
await apiCoverage.registerPostmanRequests({ collectionPath, coverage: 'detailed' })
1010
await apiCoverage.generateReport()

e2e/servrest_api.spec.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ test.beforeEach(async ({ request }) => {
3131
})
3232

3333
test.afterEach(async ({ request }) => {
34-
await apiCoverage.saveHistory()
3534
apiCoverage.stopTracking(request)
3635
})
3736
test.afterAll(async () => {

fixtures/fixture.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,8 @@ apiCoverage.setDebug(false)
1010
const extension = {
1111
testHook: [
1212
async ({ request }, use) => {
13-
apiCoverage.startTracking(request, { clientType: 'playwright', coverage: 'detailed' })
13+
apiCoverage.startTracking(request, { clientType: 'playwright', coverage: 'basic' })
1414
await use()
15-
await apiCoverage.saveHistory()
1615
apiCoverage.stopTracking(request)
1716
await apiCoverage.generateReport()
1817
},

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "api-coverage-tracker",
3-
"version": "1.6.1",
3+
"version": "2.0.0",
44
"description": "A universal library for tracking API coverage against OpenAPI/Swagger specifications from URL or local file. Supports Axis, Fetch, Playwright and manual registry of the responses",
55
"main": "./utils/api-coverage.js",
66
"exports": {

readme.md

Lines changed: 69 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,16 @@ For Postman collections it also tracks the previous coverage statistics. Support
4444
- Axios
4545
- Fetch
4646
- Custom HTTP clients (via manual registration)
47-
- Postman collections coverage calculation agains openAPI specification
47+
- Postman collections coverage calculation agains openAPI specification (cli or inline script)
4848

49-
## Important changes between 1.0.4 and 1.1.0 versions:
49+
## Important changes between 2.0.0 and 1.6.1 versions:
5050

51-
- Methods `saveHistory` and `generateReport` do not need any parameters anymore.
52-
- Paths to reports files shold be provided in the config.json file - see the below example.
53-
- History of the coverage changes is now reflected in HTML report for Axios and Fetch clients
51+
- Methods `saveHistory` is removed and no more needed.
52+
- config.json file obligatory fields are updated. Now only the base path to reports files should be provided in the config.json file - see the below example.
53+
- History of the coverage changes is now reflected in HTML report and stored individually per service for all supported clients
54+
- History is tracked for test runs with as minimum of 10 minutes intervals (this limitation is made to unify the behaviour between clients because the Playwright spawns new workers if API test fails and this is causing the reset of the stats)
55+
- Support for Postman collections coverage calculation agains openAPI specification with cli command or inlline script
56+
- To maintain the history of the test coverage - do not delete appropriate service json files from the output directory
5457

5558
## Installation
5659

@@ -62,19 +65,16 @@ npm install -D api-coverage-tracker
6265
The library requires a configuration object with service information:
6366

6467

65-
- services: An array of service objects with the following properties:
66-
- key: A unique identifier for the service
68+
- services: An array of service objects (APIs) with the following properties:
69+
- key: A unique identifier for the service (obligatory)
6770
- name: The name of the service
6871
- tags: An array of tags associated with the service
6972
- repository: The repository URL for the service
70-
- swaggerUrl: The URL of the OpenAPI/Swagger specification
71-
- swaggerFile: The local path to the OpenAPI/Swagger specification file
72-
- json-report-path: The path to save the JSON report file
73-
- json-report-history-path: The path to save the JSON history file
74-
- html-report-path: The path to save the HTML report file
75-
- stats-path: The path to save the statistics file
73+
- swaggerUrl: The URL of the OpenAPI/Swagger specification (obligatory if no swaggerFile is provided)
74+
- swaggerFile: The local path to the OpenAPI/Swagger specification file (obligatory if no swaggerUrl is provided)
75+
- report-path: The path to save the statistics and reports file (obligatory)
7676

77-
```javascript
77+
```json
7878
// config.json example
7979
{
8080
"html-report-path": "./coverage/report.html",
@@ -88,10 +88,7 @@ The library requires a configuration object with service information:
8888
"swaggerFile": "./specs/petstore.json"
8989
}
9090
],
91-
"json-report-path": "./reports/report.json",
92-
"json-report-history-path": "./reports/history.json",
93-
"html-report-path": "./reports/index.html",
94-
"stats-path": "./reports/stats.json"
91+
"report-path": "./reports"
9592
}
9693
```
9794

@@ -122,6 +119,8 @@ console.log('Coverage stats:', stats);
122119

123120
### With Playwright
124121

122+
without fixture
123+
125124
```javascript
126125
import { test } from '@playwright/test';
127126
import { ApiCoverage } from 'api-coverage-tracker'
@@ -135,7 +134,6 @@ test.beforeEach(async ({ request }) => {
135134
})
136135

137136
test.afterEach(async ({ request }) => {
138-
apiCoverage.saveHistory()
139137
apiCoverage.stopTracking(request) // always runs even on test failure
140138
})
141139
test.afterAll(async () => {
@@ -146,10 +144,59 @@ test('API coverage test', async ({ request }) => {
146144
// Make API requests
147145
const response = await request.get('/api/pets');
148146
expect(petstporeResponse).toBeOK()
149-
expect(petstporeResponse.status()).toBe(200)
150147
});
151148
```
152149

150+
with fixture
151+
152+
```javascript
153+
// fixture.js
154+
155+
import * as base from '@playwright/test'
156+
import { ApiCoverage } from 'api-coverage-tracker'
157+
import config from '../config.json' with { type: 'json' }
158+
159+
export { expect } from '@playwright/test'
160+
const apiCoverage = new ApiCoverage(config)
161+
await apiCoverage.loadSpec('https://parabank.parasoft.com/parabank/services/bank/openapi.yaml')
162+
apiCoverage.setDebug(false)
163+
164+
const extension = {
165+
testHook: [
166+
async ({ request }, use) => {
167+
apiCoverage.startTracking(request, { clientType: 'playwright', coverage: 'basic' })
168+
await use()
169+
apiCoverage.stopTracking(request)
170+
await apiCoverage.generateReport()
171+
},
172+
{ auto: true, scope: 'test' }
173+
]
174+
}
175+
export const test = base.test.extend(extension)
176+
177+
// test file
178+
179+
import { expect, test } from '@fixtures/fixture.js'
180+
181+
test('POST Start JMS Listener /startupJmsListener', async ({ request }) => {
182+
const response = await request.post('startupJmsListener')
183+
expect.soft(response.status()).toBe(204)
184+
})
185+
test('POST Clean the Database /cleanDatabase', async ({ request }) => {
186+
const response = await request.post('cleanDB')
187+
expect.soft(response.status()).toBe(204)
188+
})
189+
test('POST Initialize the Database /initializeDatabase', async ({ request }) => {
190+
const response = await request.post('initializeDB')
191+
expect.soft(response.status()).toBe(204)
192+
})
193+
test('POST Set Parameters /setParameter/:name/:value', async ({ request }) => {
194+
const response = await request.post(`setParameter/product/account`)
195+
expect.soft(response.status()).toBe(204)
196+
})
197+
198+
```
199+
153200
### With Axios
154201

155202
```javascript
@@ -176,7 +223,6 @@ async function testApi() {
176223
apiCoverage.stopTracking(axiosInstance);
177224
const stats = apiCoverage.getCoverageStats();
178225
console.log('Coverage stats:', stats);
179-
apiCoverage.saveHistory()
180226

181227
apiCoverage.generateReport()
182228
}
@@ -203,7 +249,6 @@ async function testApi() {
203249

204250
const stats = apiCoverage.getCoverageStats();
205251
console.log('Coverage stats:', stats);
206-
apiCoverage.saveHistory()
207252

208253
apiCoverage.generateReport()
209254
}
@@ -228,7 +273,6 @@ async function testApi() {
228273

229274
const stats = apiCoverage.getCoverageStats();
230275
console.log('Coverage stats:', stats);
231-
apiCoverage.saveHistory()
232276

233277
apiCoverage.generateReport()
234278
}
@@ -246,11 +290,6 @@ setupNodeEvents(on, config) {
246290
apiCoverage.registerRequest(method, url, response)
247291
return null
248292
},
249-
250-
// Task to save API history
251-
saveApiHistory() {
252-
return apiCoverage.saveHistory().then(() => null)
253-
},
254293
// Task to generate the API coverage report
255294
generateApiReport() {
256295
return apiCoverage.generateReport().then(() => {
@@ -267,9 +306,6 @@ before(() => {
267306
Cypress.log({ name: 'API Coverage', message: 'Spec loaded successfully' })
268307
})
269308
})
270-
afterEach(() => {
271-
cy.task('saveApiHistory')
272-
})
273309
after(() => {
274310
cy.task('generateApiReport').then(() => {
275311
Cypress.log({ name: 'API Coverage', message: 'Report generated' })
@@ -305,17 +341,14 @@ const apiCoverage = new ApiCoverage(config)
305341
const openAPISpec = 'https://fakestoreapi.com/fakestoreapi.json'
306342
const collectionPath = './e2e/data/FakeStoreAPI.postman_collection.json'
307343
await apiCoverage.loadSpec(openAPISpec)
308-
apiCoverage.registerPostmanRequests({ collectionPath, coverage: 'basic' })
309-
await apiCoverage.saveHistory()
344+
await apiCoverage.registerPostmanRequests({ collectionPath, coverage: 'basic' })
310345
await apiCoverage.generateReport()
311346

312347
```
313348

314-
### Saving and Loading Coverage History
349+
### Saving and Loading Coverage History occurs automatically
315350

316351
```javascript
317-
// Save coverage history to a file
318-
apiCoverage.saveHistory();
319352

320353
// Generate a final html and json reports from history
321354
apiCoverage.generateReport();
@@ -407,10 +440,6 @@ Get coverage statistics.
407440

408441
- Returns: Object containing coverage statistics
409442

410-
### `saveHistory()`
411-
412-
Save current coverage state to a history file.
413-
414443
### `generateReport()`
415444

416445
Generate coverage report from history file.

reports/Fakestoreapiservice.json

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
[
2+
{
3+
"createdAt": "2025-06-08T23:11:22.515Z",
4+
"totalCoverage": 31.3
5+
},
6+
{
7+
"createdAt": "2025-06-08T23:33:14.782Z",
8+
"totalCoverage": 100
9+
},
10+
{
11+
"createdAt": "2025-06-09T07:14:45.682Z",
12+
"totalCoverage": 100
13+
},
14+
{
15+
"createdAt": "2025-06-09T10:14:04.571Z",
16+
"totalCoverage": 77.5
17+
},
18+
{
19+
"createdAt": "2025-06-09T12:53:58.974Z",
20+
"totalCoverage": 100
21+
}
22+
]

0 commit comments

Comments
 (0)