Skip to content

Commit f64198f

Browse files
feat: added sharded example for vitest
1 parent a47f613 commit f64198f

File tree

12 files changed

+249
-60
lines changed

12 files changed

+249
-60
lines changed

.github/workflows/sharded-vitest.yml

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
name: Vitest Tests
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
workflow_dispatch:
9+
10+
jobs:
11+
test:
12+
runs-on: ubuntu-latest
13+
strategy:
14+
matrix:
15+
shard: [1, 2]
16+
total-shards: [2]
17+
18+
steps:
19+
- uses: actions/checkout@v4
20+
21+
- name: Setup Node.js
22+
uses: actions/setup-node@v4
23+
with:
24+
node-version: "18"
25+
cache: "npm"
26+
27+
- name: Install dependencies
28+
run: npm ci
29+
30+
- name: Run Vitest Tests (Shard ${{ matrix.shard }}/${{ matrix.total-shards }})
31+
run: npx vitest --run --shard=${{ matrix.shard }}/${{ matrix.total-shards }} vitest-sharded-example/tests/** --reporter=junit --outputFile=./vitest-sharded-example/results-${{ matrix.shard }}.xml
32+
33+
- name: Combine Vitest Sharded results
34+
run: node ./scripts/combine-results.js --reports-dir vitest-sharded-example --output-file vitest-sharded-example/combined-results.xml
35+
36+
- name: Report Vitest Sharded results
37+
env:
38+
CURRENTS_KEY: ${{ secrets.CURRENTS_KEY }}
39+
CURRENTS_PROJECT_ID: ${{ secrets.CURRENTS_PROJECT_ID }}
40+
CURRENTS_CI_BUILD_ID: ${{ github.run_id }}-${{ github.run_number }}
41+
run: node scripts/uploadResults.js --report-dir vitest-sharded-example

README.md

+53-12
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Currents.dev - Generic API example
1+
# Currents.dev - JUnit XML report example
22

33
This is an example repository that showcases using [Currents.dev](https://currents.dev) for sending test results via Currents Generic API.
44

@@ -12,18 +12,59 @@ This is an example repository that showcases using [Currents.dev](https://curren
1212

1313

1414
## Key points:
15-
- The report directory for this project is `postman-tests-example`
1615
- You have all scripts required to test the Generic API example in the `package.json` file
16+
- All the examples must have the `instances` folder within their respective example folders. Eg: `postman-tests-example/instances`
17+
- All the examples must have their respective `config.json` file with the following structure:
18+
```
19+
{
20+
"framework": "junit", // This is mandatory
21+
"frameworkVersion": "11.10.0", // Your framework's version
22+
"cliArgs": {
23+
"options": {
24+
"jUnitFile": "postman-tests-example/tests.xml" // This is mandatory and must point to the JUnit XML file with the tests results
25+
},
26+
"args": []
27+
},
28+
"frameworkConfig": {
29+
"originFramework": "postman", // This is your framework's name
30+
"originFrameworkVersion": "11.10.0" // This is your framework's version
31+
}
32+
}
33+
```
34+
- Recognized `originFramework` values in the dashboard are: `postman` for Postman, `vitest` for Vitest and `wdio` for WebDriver.io
35+
- You can run the `<framework>:full` command for each example to execute all the related commands to the specific example or execute each one of the commands in order to understand what is the purpose of each one.
1736

18-
## Scripts:
19-
- `parse-postman-test`: Transforms `postman-tests-example/tests.json` file into JUnit `postman-tests-example/tests.xml` file
20-
- `generate-instance-files`: Reads the JUnit XML file in `postman-tests-example/tests.xml` to generate instance JSON files in `postman-tests-example/instances` path.
21-
- `report-results`: Executes the `currents upload` command to report the test results in the report directory (`postman-tests-example`) to Currents platform.
2237

2338
## How to try it?
24-
1. Get your Record key and Project ID from Currents dashboard.
25-
2. Execute `node run parse-postman-test`
26-
3. Execute `node run generate-instance-files`
27-
4. Replace in the `package.json` file the script called `report-results` with your record key and project ID.
28-
5. Set a unique CI Build ID in the script from the previous step.
29-
6. Execute `node run report-results`
39+
1. Execute `npm run initial-setup` for setting up the needed folders for all the examples.
40+
2. Get your Record key and Project ID from Currents dashboard.
41+
3. Put the Record key, Project ID and a unique CI build ID in a `.env` file like this:
42+
```
43+
CURRENTS_KEY=your-record-key
44+
CURRENTS_PROJECT_ID=your-project-id
45+
CURRENTS_CI_BUILD_ID=unique-id
46+
```
47+
48+
### Postman
49+
Postman example is in `postman-tests-example` folder.
50+
The Postman example has the following commands:
51+
- `parse-postman-test`: Parses the JSON file exported from the Postman collection and turns it into a JUnit XML file. It uses `newman` to transform the file.
52+
- `gen-instance-postman`: Generates the instance files into `postman-tests-example/instances` folder from the JUnit XML file.
53+
- `report-results-postman`: Uploads the results to Currents platform.
54+
- `postman:full`: Executes all the postman example related commands consecutively in the right order.
55+
56+
### Vitest
57+
Vitest example is in `vitest-example` folder.
58+
The Vitest example has the following commands:
59+
- `test-vitest`: Executes the vitest tests and outputs the result into a JUnit XML file.
60+
- `gen-instance-vitest`: Generates the instance files into `vistes-example/instances` folder from the JUnit XML file.
61+
- `report-results-vitest`: Uploads the results to Currents platform.
62+
- `vitest:full`: Executes all the vitest example related commands consecutively in the right order.
63+
64+
### WebDriver.io
65+
WebDriver.io example is in `wdio-example` folder.
66+
The WebDriver.io example has the following commands:
67+
- `test-wdio`: Executes the WebDriver.io tests and outputs the result into a JUnit XML file.
68+
- `gen-instance-wdio`: Generates the instance files into `wdio-example/instances` folder from the JUnit XML file.
69+
- `report-results-wdio`: Uploads the results to Currents platform.
70+
- `wdio:full`: Executes all the WebDriver.io example related commands consecutively in the right order.

package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
"description": "",
55
"main": "index.js",
66
"scripts": {
7+
"initial-setup": "mkdir -p postman-tests-example/instances && mkdir -p vitest-example/instances && mkdir -p wdio-example/instances",
78
"parse-postman-test": "newman run postman-tests-example/tests.json -r junit --reporter-junit-export postman-tests-example/tests.xml",
89
"gen-instance-postman": "node scripts/junitXmlToInstanceJson.js --input postman-tests-example/tests.xml --output postman-tests-example/instances",
910
"report-results-postman": "node scripts/uploadResults.js --report-dir postman-tests-example",
@@ -12,7 +13,7 @@
1213
"gen-instance-vitest": "node scripts/junitXmlToInstanceJson.js --input vitest-example/junit.xml --output vitest-example/instances",
1314
"report-results-vitest": "node scripts/uploadResults.js --report-dir vitest-example",
1415
"vitest:full": "npm run test-vitest || true && npm run gen-instance-vitest && npm run report-results-vitest",
15-
"test-wdio": "npx wdio run wdio-example/wdio.conf.js || true && node ./scripts/combine-results.js",
16+
"test-wdio": "npx wdio run wdio-example/wdio.conf.js || true && node ./scripts/combine-results.js --reports-dir wdio-example --output-file wdio-example/combined-results.xml",
1617
"gen-instance-wdio": "node scripts/junitXmlToInstanceJson.js --input wdio-example/combined-results.xml --output wdio-example/instances",
1718
"report-results-wdio": "node scripts/uploadResults.js --report-dir wdio-example",
1819
"wdio:full": "npm run test-wdio || true && npm run gen-instance-wdio && npm run report-results-wdio"

scripts/combine-results.js

+12-2
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,18 @@ const fs = require("fs");
22
const xml2js = require("xml2js");
33
const path = require("path");
44

5-
const reportsDir = "wdio-example";
6-
const outputFile = "wdio-example/combined-results.xml";
5+
const args = process.argv.slice(2);
6+
const reportsDirIndex = args.indexOf('--reports-dir');
7+
const outputFileIndex = args.indexOf('--output-file');
8+
9+
// Set directories with defaults
10+
const reportsDir = reportsDirIndex !== -1 ? args[reportsDirIndex + 1] : "wdio-example";
11+
const outputFile = outputFileIndex !== -1 ? args[outputFileIndex + 1] : "wdio-example/combined-results.xml";
12+
13+
if (reportsDirIndex === -1 || outputFileIndex === -1) {
14+
console.log('Usage: node script.js --reports-dir <directory> --output-file <file>');
15+
console.log(`Using defaults: --reports-dir="${reportsDir}" --output-file="${outputFile}"`);
16+
}
717

818
async function combineResults() {
919
const files = fs

vitest-example/junit.xml

+8-22
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,15 @@
11
<?xml version="1.0" encoding="UTF-8" ?>
2-
<testsuites name="vitest tests" tests="12" failures="2" errors="0" time="0.306">
3-
<testsuite name="vitest-example/tests/numberUtils.spec.js" timestamp="2024-11-20T02:47:02.562Z" hostname="Miguels-Laptop.local" tests="6" failures="0" errors="0" skipped="0" time="0.003190458">
4-
<testcase classname="vitest-example/tests/numberUtils.spec.js" name="calculateAverage &gt; calculates average of positive numbers" time="0.001560375">
2+
<testsuites name="vitest tests" tests="6" failures="2" errors="0" time="0.386">
3+
<testsuite name="vitest-example/tests/stringUtils.spec.js" timestamp="2024-11-20T03:32:00.126Z" hostname="Miguels-Laptop.local" tests="6" failures="2" errors="0" skipped="0" time="0.0079045">
4+
<testcase classname="vitest-example/tests/stringUtils.spec.js" name="capitalizeWords &gt; capitalizes first letter of each word" time="0.0011366253">
55
</testcase>
6-
<testcase classname="vitest-example/tests/numberUtils.spec.js" name="calculateAverage &gt; handles array with single number" time="0.000205292">
6+
<testcase classname="vitest-example/tests/stringUtils.spec.js" name="capitalizeWords &gt; handles already capitalized words" time="0.0001980419">
77
</testcase>
8-
<testcase classname="vitest-example/tests/numberUtils.spec.js" name="calculateAverage &gt; handles empty array" time="0.000096167">
8+
<testcase classname="vitest-example/tests/stringUtils.spec.js" name="capitalizeWords &gt; handles empty string" time="0.0000864573">
99
</testcase>
10-
<testcase classname="vitest-example/tests/numberUtils.spec.js" name="calculateAverage &gt; handles negative numbers" time="0.000089292">
10+
<testcase classname="vitest-example/tests/stringUtils.spec.js" name="capitalizeWords &gt; handles single word" time="0.0000859175">
1111
</testcase>
12-
<testcase classname="vitest-example/tests/numberUtils.spec.js" name="calculateAverage &gt; handles decimal numbers" time="0.00022425">
13-
</testcase>
14-
<testcase classname="vitest-example/tests/numberUtils.spec.js" name="calculateAverage &gt; returns 0 for invalid input" time="0.000091958">
15-
</testcase>
16-
</testsuite>
17-
<testsuite name="vitest-example/tests/stringUtils.spec.js" timestamp="2024-11-20T02:47:02.564Z" hostname="Miguels-Laptop.local" tests="6" failures="2" errors="0" skipped="0" time="0.008223417">
18-
<testcase classname="vitest-example/tests/stringUtils.spec.js" name="capitalizeWords &gt; capitalizes first letter of each word" time="0.00153475">
19-
</testcase>
20-
<testcase classname="vitest-example/tests/stringUtils.spec.js" name="capitalizeWords &gt; handles already capitalized words" time="0.000207583">
21-
</testcase>
22-
<testcase classname="vitest-example/tests/stringUtils.spec.js" name="capitalizeWords &gt; handles empty string" time="0.000095292">
23-
</testcase>
24-
<testcase classname="vitest-example/tests/stringUtils.spec.js" name="capitalizeWords &gt; handles single word" time="0.000091708">
25-
</testcase>
26-
<testcase classname="vitest-example/tests/stringUtils.spec.js" name="capitalizeWords &gt; handles mixed case input" time="0.004720584">
12+
<testcase classname="vitest-example/tests/stringUtils.spec.js" name="capitalizeWords &gt; handles mixed case input" time="0.00472225">
2713
<failure message="expected &apos;Hello World&apos; to be &apos;Hello World!&apos; // Object.is equality" type="AssertionError">
2814
AssertionError: expected &apos;Hello World&apos; to be &apos;Hello World!&apos; // Object.is equality
2915

@@ -33,7 +19,7 @@ Received: &quot;Hello World&quot;
3319
❯ vitest-example/tests/stringUtils.spec.js:22:44
3420
</failure>
3521
</testcase>
36-
<testcase classname="vitest-example/tests/stringUtils.spec.js" name="capitalizeWords &gt; errors on number received" time="0.000677291">
22+
<testcase classname="vitest-example/tests/stringUtils.spec.js" name="capitalizeWords &gt; errors on number received" time="0.0006915846">
3723
<failure message="str.split is not a function" type="TypeError">
3824
TypeError: str.split is not a function
3925
❯ Module.capitalizeWords vitest-example/stringUtils.js:4:6

vitest-sharded-example/config.json

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"framework": "junit",
3+
"frameworkVersion": "2.1.5",
4+
"cliArgs": {
5+
"options": { "jUnitFile": "vitest-sharded-example/combined-results.xml" },
6+
"args": []
7+
},
8+
"frameworkConfig": {
9+
"originFramework": "vitest",
10+
"originFrameworkVersion": "2.1.5"
11+
}
12+
}

vitest-sharded-example/junit.xml

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?xml version="1.0" encoding="UTF-8" ?>
2+
<testsuites name="vitest tests" tests="6" failures="2" errors="0" time="0.386">
3+
<testsuite name="vitest-example/tests/stringUtils.spec.js" timestamp="2024-11-20T03:32:00.126Z" hostname="Miguels-Laptop.local" tests="6" failures="2" errors="0" skipped="0" time="0.0079045">
4+
<testcase classname="vitest-example/tests/stringUtils.spec.js" name="capitalizeWords &gt; capitalizes first letter of each word" time="0.0011366253">
5+
</testcase>
6+
<testcase classname="vitest-example/tests/stringUtils.spec.js" name="capitalizeWords &gt; handles already capitalized words" time="0.0001980419">
7+
</testcase>
8+
<testcase classname="vitest-example/tests/stringUtils.spec.js" name="capitalizeWords &gt; handles empty string" time="0.0000864573">
9+
</testcase>
10+
<testcase classname="vitest-example/tests/stringUtils.spec.js" name="capitalizeWords &gt; handles single word" time="0.0000859175">
11+
</testcase>
12+
<testcase classname="vitest-example/tests/stringUtils.spec.js" name="capitalizeWords &gt; handles mixed case input" time="0.00472225">
13+
<failure message="expected &apos;Hello World&apos; to be &apos;Hello World!&apos; // Object.is equality" type="AssertionError">
14+
AssertionError: expected &apos;Hello World&apos; to be &apos;Hello World!&apos; // Object.is equality
15+
16+
Expected: &quot;Hello World!&quot;
17+
Received: &quot;Hello World&quot;
18+
19+
❯ vitest-example/tests/stringUtils.spec.js:22:44
20+
</failure>
21+
</testcase>
22+
<testcase classname="vitest-example/tests/stringUtils.spec.js" name="capitalizeWords &gt; errors on number received" time="0.0006915846">
23+
<failure message="str.split is not a function" type="TypeError">
24+
TypeError: str.split is not a function
25+
❯ Module.capitalizeWords vitest-example/stringUtils.js:4:6
26+
❯ vitest-example/tests/stringUtils.spec.js:26:12
27+
</failure>
28+
</testcase>
29+
</testsuite>
30+
</testsuites>

vitest-sharded-example/numberUtils.js

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export function calculateAverage(numbers) {
2+
if (!Array.isArray(numbers) || numbers.length === 0) return 0;
3+
return numbers.reduce((sum, num) => sum + num, 0) / numbers.length;
4+
}

vitest-sharded-example/stringUtils.js

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export function capitalizeWords(str) {
2+
if (!str) return "";
3+
return str
4+
.split(" ")
5+
.map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
6+
.join(" ");
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { describe, it, expect } from "vitest";
2+
import { calculateAverage } from "../numberUtils";
3+
4+
describe("calculateAverage", () => {
5+
it("calculates average of positive numbers", () => {
6+
expect(calculateAverage([1, 2, 3, 4, 5])).toBe(3);
7+
});
8+
9+
it("handles array with single number", () => {
10+
expect(calculateAverage([5])).toBe(5);
11+
});
12+
13+
it("handles empty array", () => {
14+
expect(calculateAverage([])).toBe(0);
15+
});
16+
17+
it("handles negative numbers", () => {
18+
expect(calculateAverage([-1, -2, -3])).toBe(-2);
19+
});
20+
21+
it("handles decimal numbers", () => {
22+
expect(calculateAverage([1.5, 2.5])).toBe(2);
23+
});
24+
25+
it("returns 0 for invalid input", () => {
26+
expect(calculateAverage(null)).toBe(0);
27+
expect(calculateAverage(undefined)).toBe(0);
28+
});
29+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { describe, it, expect } from "vitest";
2+
import { capitalizeWords } from "../stringUtils";
3+
4+
describe("capitalizeWords", () => {
5+
it("capitalizes first letter of each word", () => {
6+
expect(capitalizeWords("hello world")).toBe("Hello World");
7+
});
8+
9+
it("handles already capitalized words", () => {
10+
expect(capitalizeWords("HELLO WORLD")).toBe("Hello World");
11+
});
12+
13+
it("handles empty string", () => {
14+
expect(capitalizeWords("")).toBe("");
15+
});
16+
17+
it("handles single word", () => {
18+
expect(capitalizeWords("javascript")).toBe("Javascript");
19+
});
20+
21+
it("handles mixed case input", () => {
22+
expect(capitalizeWords("hElLo wOrLd")).toBe("Hello World!");
23+
});
24+
25+
it("errors on number received", () => {
26+
expect(capitalizeWords(1)).toBe("Hello World!");
27+
});
28+
});

0 commit comments

Comments
 (0)