mirror of
https://github.com/dorny/test-reporter.git
synced 2025-12-17 14:57:09 +01:00
feat: add reporter for salesforce apex
This commit is contained in:
parent
95058abb17
commit
c4f7701aa1
9 changed files with 11991 additions and 5 deletions
11
README.md
11
README.md
|
|
@ -19,6 +19,7 @@ This [Github Action](https://github.com/features/actions) displays test results
|
|||
- Java / [JUnit](https://junit.org/)
|
||||
- JavaScript / [JEST](https://jestjs.io/) / [Mocha](https://mochajs.org/)
|
||||
- Swift / xUnit
|
||||
- Apex / [JSON](https://developer.salesforce.com/docs/atlas.en-us.sfdx_dev.meta/sfdx_dev/sfdx_dev_testing.htm)
|
||||
|
||||
For more information see [Supported formats](#supported-formats) section.
|
||||
|
||||
|
|
@ -341,6 +342,16 @@ Please update Mocha to version [v9.1.0](https://github.com/mochajs/mocha/release
|
|||
Support for Swift test results in xUnit format is experimental - should work but it was not extensively tested.
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>apex-json (Experimental)</summary>
|
||||
|
||||
Support for [Salesforce Apex](https://developer.salesforce.com/docs/atlas.en-us.sfdx_dev.meta/sfdx_dev/sfdx_dev_testing.htm)
|
||||
|
||||
```bash
|
||||
sf apex test run --result-format json --wait 30 > test-results.json
|
||||
```
|
||||
</details>
|
||||
|
||||
## GitHub limitations
|
||||
|
||||
Unfortunately, there are some known issues and limitations caused by GitHub API:
|
||||
|
|
|
|||
45
__tests__/apex-json.test.ts
Normal file
45
__tests__/apex-json.test.ts
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
import path from 'node:path';
|
||||
import fs from 'node:fs';
|
||||
|
||||
import { ParseOptions } from '../src/test-parser';
|
||||
import { normalizeFilePath } from '../src/utils/path-utils';
|
||||
import { ApexJsonParser } from '../src/parsers/apex-json/apex-json-parsers';
|
||||
import { getReport } from '../src/report/get-report';
|
||||
|
||||
describe('apex-json tests', () => {
|
||||
it('produces empty test run result when there are no test cases', async () => {
|
||||
const fixturePath = path.join(__dirname, 'fixtures', 'empty', 'apex-json.json')
|
||||
const filePath = normalizeFilePath(path.relative(__dirname, fixturePath))
|
||||
const fileContent = fs.readFileSync(fixturePath, {encoding: 'utf8'})
|
||||
|
||||
const opts: ParseOptions = {
|
||||
parseErrors: true,
|
||||
trackedFiles: []
|
||||
}
|
||||
|
||||
const parser = new ApexJsonParser(opts)
|
||||
const result = await parser.parse(filePath, fileContent)
|
||||
expect(result.tests).toBe(0)
|
||||
expect(result.result).toBe('success')
|
||||
});
|
||||
|
||||
it('matches report snapshot', async () => {
|
||||
const opts: ParseOptions = {
|
||||
parseErrors: true,
|
||||
trackedFiles: []
|
||||
}
|
||||
|
||||
const fixturePath = path.join(__dirname, 'fixtures', 'apex-json.json')
|
||||
const outputPath = path.join(__dirname, '__outputs__', 'apex-json.md')
|
||||
const filePath = normalizeFilePath(path.relative(__dirname, fixturePath))
|
||||
const fileContent = fs.readFileSync(fixturePath, {encoding: 'utf8'})
|
||||
|
||||
const parser = new ApexJsonParser(opts)
|
||||
const result = await parser.parse(filePath, fileContent)
|
||||
expect(result).toMatchSnapshot()
|
||||
|
||||
const report = getReport([result])
|
||||
fs.mkdirSync(path.dirname(outputPath), {recursive: true})
|
||||
fs.writeFileSync(outputPath, report)
|
||||
})
|
||||
});
|
||||
11800
__tests__/fixtures/apex-json.json
Normal file
11800
__tests__/fixtures/apex-json.json
Normal file
File diff suppressed because it is too large
Load diff
25
__tests__/fixtures/empty/apex-json.json
Normal file
25
__tests__/fixtures/empty/apex-json.json
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
"result": {
|
||||
"summary": {
|
||||
"failRate": "0%",
|
||||
"failing": 0,
|
||||
"hostname": "https://scratch.my.salesforce.com",
|
||||
"orgId": "0000000000000",
|
||||
"outcome": "Passed",
|
||||
"passRate": "0%",
|
||||
"passing": 0,
|
||||
"skipped": 0,
|
||||
"testRunId": "000000000000",
|
||||
"testStartTime": "2024-07-11T15:21:00.000Z",
|
||||
"testsRan": 0,
|
||||
"userId": "000000000000000",
|
||||
"username": "test@example.com",
|
||||
"commandTime": "357 ms",
|
||||
"testExecutionTime": "1000 ms",
|
||||
"testTotalTime": "1000 ms",
|
||||
"orgWideCoverage": "0%",
|
||||
"testRunCoverage": "0%"
|
||||
},
|
||||
"tests": []
|
||||
}
|
||||
}
|
||||
8
package-lock.json
generated
8
package-lock.json
generated
|
|
@ -23,7 +23,7 @@
|
|||
"@types/adm-zip": "^0.5.5",
|
||||
"@types/github-slugger": "^1.3.0",
|
||||
"@types/jest": "^29.5.12",
|
||||
"@types/node": "^20.14.8",
|
||||
"@types/node": "^20.14.10",
|
||||
"@types/picomatch": "^2.3.3",
|
||||
"@types/xml2js": "^0.4.14",
|
||||
"@typescript-eslint/eslint-plugin": "^7.14.1",
|
||||
|
|
@ -1654,9 +1654,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "20.14.8",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.8.tgz",
|
||||
"integrity": "sha512-DO+2/jZinXfROG7j7WKFn/3C6nFwxy2lLpgLjEXJz+0XKphZlTLJ14mo8Vfg8X5BWN6XjyESXq+LcYdT7tR3bA==",
|
||||
"version": "20.14.10",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.10.tgz",
|
||||
"integrity": "sha512-MdiXf+nDuMvY0gJKxyfZ7/6UFsETO7mGKF54MVD/ekJS6HdFtpZFBgrh6Pseu64XTb2MLyFPlbW6hj8HYRQNOQ==",
|
||||
"dependencies": {
|
||||
"undici-types": "~5.26.4"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@
|
|||
"@types/adm-zip": "^0.5.5",
|
||||
"@types/github-slugger": "^1.3.0",
|
||||
"@types/jest": "^29.5.12",
|
||||
"@types/node": "^20.14.8",
|
||||
"@types/node": "^20.14.10",
|
||||
"@types/picomatch": "^2.3.3",
|
||||
"@types/xml2js": "^0.4.14",
|
||||
"@typescript-eslint/eslint-plugin": "^7.14.1",
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import {SwiftXunitParser} from './parsers/swift-xunit/swift-xunit-parser'
|
|||
|
||||
import {normalizeDirPath, normalizeFilePath} from './utils/path-utils'
|
||||
import {getCheckRunContext} from './utils/github-utils'
|
||||
import {ApexJsonParser} from './parsers/apex-json/apex-json-parsers'
|
||||
|
||||
async function main(): Promise<void> {
|
||||
try {
|
||||
|
|
@ -243,6 +244,8 @@ class TestReporter {
|
|||
return new RspecJsonParser(options)
|
||||
case 'swift-xunit':
|
||||
return new SwiftXunitParser(options)
|
||||
case 'apex-json':
|
||||
return new ApexJsonParser(options)
|
||||
default:
|
||||
throw new Error(`Input variable 'reporter' is set to invalid value '${reporter}'`)
|
||||
}
|
||||
|
|
|
|||
10
src/parsers/apex-json/apex-json-parsers.ts
Normal file
10
src/parsers/apex-json/apex-json-parsers.ts
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
import {ParseOptions, TestParser} from '../../test-parser'
|
||||
import {TestRunResult} from '../../test-results'
|
||||
|
||||
export class ApexJsonParser implements TestParser {
|
||||
constructor(readonly options: ParseOptions) {}
|
||||
|
||||
async parse(path: string, content: string): Promise<TestRunResult> {
|
||||
throw new Error('Method not implemented.')
|
||||
}
|
||||
}
|
||||
92
src/parsers/apex-json/apex-json-types.ts
Normal file
92
src/parsers/apex-json/apex-json-types.ts
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
export interface RootObject {
|
||||
result: Result
|
||||
}
|
||||
|
||||
export interface Result {
|
||||
summary: SuiteSummary
|
||||
tests: Test[]
|
||||
coverage: SuiteCoverage
|
||||
}
|
||||
|
||||
export interface SuiteCoverage {
|
||||
coverage?: Coverage[]
|
||||
records: ApexRecord[]
|
||||
summary: SuiteCoverageSummary
|
||||
}
|
||||
|
||||
export interface SuiteCoverageSummary {
|
||||
totalLines: number
|
||||
coveredLines: number
|
||||
orgWideCoverage: string
|
||||
testRunCoverage: string
|
||||
}
|
||||
|
||||
export interface ApexRecord {
|
||||
ApexTestClass: ApexTestClass
|
||||
Coverage: RecordCoverage
|
||||
TestMethodName: string
|
||||
NumLinesCovered: number
|
||||
ApexClassOrTrigger: ApexTestClass
|
||||
NumLinesUncovered: number
|
||||
}
|
||||
|
||||
export interface RecordCoverage {
|
||||
coveredLines: number[]
|
||||
uncoveredLines: number[]
|
||||
}
|
||||
|
||||
export interface ApexTestClass {
|
||||
Id: string
|
||||
Name: string
|
||||
}
|
||||
|
||||
export interface Coverage {
|
||||
id: string
|
||||
name: string
|
||||
totalLines: number
|
||||
lines: Lines
|
||||
totalCovered: number
|
||||
coveredPercent: number
|
||||
}
|
||||
|
||||
export type Lines = Record<number, number>
|
||||
|
||||
export interface Test {
|
||||
Id: string
|
||||
QueueItemId: string
|
||||
StackTrace: null
|
||||
Message: null
|
||||
AsyncApexJobId: string
|
||||
MethodName: string
|
||||
Outcome: string
|
||||
ApexClass: ApexClass
|
||||
RunTime: number
|
||||
FullName: string
|
||||
}
|
||||
|
||||
export interface ApexClass {
|
||||
Id: string
|
||||
Name: string
|
||||
NamespacePrefix: string
|
||||
}
|
||||
|
||||
export interface SuiteSummary {
|
||||
failRate: string
|
||||
failing: number
|
||||
hostname: string
|
||||
orgId: string
|
||||
outcome: string
|
||||
passRate: string
|
||||
passing: number
|
||||
skipped: number
|
||||
testRunId: string
|
||||
testStartTime: string
|
||||
testsRan: number
|
||||
userId: string
|
||||
username: string
|
||||
commandTime: string
|
||||
testExecutionTime: string
|
||||
testTotalTime: string
|
||||
orgWideCoverage: string
|
||||
testRunCoverage: string
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue