mirror of
https://github.com/dorny/test-reporter.git
synced 2026-03-21 23:52:12 +01:00
Modernize ESLint configuration
This commit is contained in:
parent
393efa337c
commit
eed2d2d031
8 changed files with 86 additions and 121 deletions
|
|
@ -1,68 +0,0 @@
|
||||||
{
|
|
||||||
"plugins": ["import", "jest", "@typescript-eslint"],
|
|
||||||
"extends": ["plugin:github/recommended"],
|
|
||||||
"parser": "@typescript-eslint/parser",
|
|
||||||
"parserOptions": {
|
|
||||||
"ecmaVersion": 9,
|
|
||||||
"sourceType": "module",
|
|
||||||
"project": "./tsconfig.json"
|
|
||||||
},
|
|
||||||
"rules": {
|
|
||||||
"i18n-text/no-en": "off",
|
|
||||||
"eslint-comments/no-use": "off",
|
|
||||||
"import/no-namespace": "off",
|
|
||||||
"import/no-named-as-default": "off",
|
|
||||||
"no-shadow": "off",
|
|
||||||
"no-unused-vars": "off",
|
|
||||||
"prefer-template": "off",
|
|
||||||
"@typescript-eslint/no-unused-vars": ["error", {"varsIgnorePattern": "^_"}],
|
|
||||||
"@typescript-eslint/explicit-member-accessibility": ["error", {"accessibility": "no-public"}],
|
|
||||||
"@typescript-eslint/no-require-imports": "error",
|
|
||||||
"@typescript-eslint/array-type": "error",
|
|
||||||
"@typescript-eslint/await-thenable": "error",
|
|
||||||
"@typescript-eslint/ban-ts-comment": "error",
|
|
||||||
"camelcase": "off",
|
|
||||||
"@typescript-eslint/consistent-type-assertions": "error",
|
|
||||||
"@typescript-eslint/explicit-function-return-type": ["error", {"allowExpressions": true}],
|
|
||||||
"@typescript-eslint/func-call-spacing": ["error", "never"],
|
|
||||||
"@typescript-eslint/no-array-constructor": "error",
|
|
||||||
"@typescript-eslint/no-empty-interface": "error",
|
|
||||||
"@typescript-eslint/no-explicit-any": "error",
|
|
||||||
"@typescript-eslint/no-extraneous-class": "error",
|
|
||||||
"@typescript-eslint/no-for-in-array": "error",
|
|
||||||
"@typescript-eslint/no-inferrable-types": "error",
|
|
||||||
"@typescript-eslint/no-misused-new": "error",
|
|
||||||
"@typescript-eslint/no-namespace": "error",
|
|
||||||
"@typescript-eslint/no-non-null-assertion": "warn",
|
|
||||||
"@typescript-eslint/no-unnecessary-qualifier": "error",
|
|
||||||
"@typescript-eslint/no-unnecessary-type-assertion": "error",
|
|
||||||
"@typescript-eslint/no-useless-constructor": "error",
|
|
||||||
"@typescript-eslint/no-var-requires": "error",
|
|
||||||
"@typescript-eslint/prefer-for-of": "warn",
|
|
||||||
"@typescript-eslint/prefer-function-type": "warn",
|
|
||||||
"@typescript-eslint/prefer-includes": "error",
|
|
||||||
"@typescript-eslint/prefer-string-starts-ends-with": "error",
|
|
||||||
"@typescript-eslint/promise-function-async": "error",
|
|
||||||
"@typescript-eslint/require-array-sort-compare": "error",
|
|
||||||
"@typescript-eslint/restrict-plus-operands": "error",
|
|
||||||
"semi": "off",
|
|
||||||
"@typescript-eslint/semi": ["error", "never"],
|
|
||||||
"@typescript-eslint/type-annotation-spacing": "error",
|
|
||||||
"@typescript-eslint/unbound-method": "error"
|
|
||||||
},
|
|
||||||
"env": {
|
|
||||||
"node": true,
|
|
||||||
"es6": true,
|
|
||||||
"jest/globals": true
|
|
||||||
},
|
|
||||||
"settings": {
|
|
||||||
"import/parsers": {
|
|
||||||
"@typescript-eslint/parser": [".ts", ".tsx"]
|
|
||||||
},
|
|
||||||
"import/resolver": {
|
|
||||||
"typescript": {
|
|
||||||
"alwaysTryTypes": true // always try to resolve types under `<root>@types` directory even it doesn't contain any source code, like `@types/unist`
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -8,7 +8,9 @@ describe('getBadge', () => {
|
||||||
badgeTitle: 'tests'
|
badgeTitle: 'tests'
|
||||||
}
|
}
|
||||||
const badge = getBadge(5, 0, 1, options)
|
const badge = getBadge(5, 0, 1, options)
|
||||||
expect(badge).toBe('')
|
expect(badge).toBe(
|
||||||
|
''
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('handles badge title with single hyphen', () => {
|
it('handles badge title with single hyphen', () => {
|
||||||
|
|
@ -28,7 +30,9 @@ describe('getBadge', () => {
|
||||||
}
|
}
|
||||||
const badge = getBadge(10, 0, 0, options)
|
const badge = getBadge(10, 0, 0, options)
|
||||||
// All hyphens in the title should be encoded as --
|
// All hyphens in the title should be encoded as --
|
||||||
expect(badge).toBe('')
|
expect(badge).toBe(
|
||||||
|
''
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('handles badge title with multiple underscores', () => {
|
it('handles badge title with multiple underscores', () => {
|
||||||
|
|
@ -38,7 +42,9 @@ describe('getBadge', () => {
|
||||||
}
|
}
|
||||||
const badge = getBadge(10, 0, 0, options)
|
const badge = getBadge(10, 0, 0, options)
|
||||||
// All underscores in the title should be encoded as __
|
// All underscores in the title should be encoded as __
|
||||||
expect(badge).toBe('')
|
expect(badge).toBe(
|
||||||
|
''
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('handles badge title with version format containing hyphen', () => {
|
it('handles badge title with version format containing hyphen', () => {
|
||||||
|
|
@ -48,7 +54,9 @@ describe('getBadge', () => {
|
||||||
}
|
}
|
||||||
const badge = getBadge(1, 0, 0, options)
|
const badge = getBadge(1, 0, 0, options)
|
||||||
// The hyphen in "12.0-ubi" should be encoded as --
|
// The hyphen in "12.0-ubi" should be encoded as --
|
||||||
expect(badge).toBe('')
|
expect(badge).toBe(
|
||||||
|
''
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('handles badge title with dots and hyphens', () => {
|
it('handles badge title with dots and hyphens', () => {
|
||||||
|
|
@ -57,7 +65,9 @@ describe('getBadge', () => {
|
||||||
badgeTitle: 'v1.2.3-beta-test'
|
badgeTitle: 'v1.2.3-beta-test'
|
||||||
}
|
}
|
||||||
const badge = getBadge(4, 1, 0, options)
|
const badge = getBadge(4, 1, 0, options)
|
||||||
expect(badge).toBe('')
|
expect(badge).toBe(
|
||||||
|
''
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('preserves structural hyphens between label and message', () => {
|
it('preserves structural hyphens between label and message', () => {
|
||||||
|
|
@ -67,7 +77,9 @@ describe('getBadge', () => {
|
||||||
}
|
}
|
||||||
const badge = getBadge(2, 3, 1, options)
|
const badge = getBadge(2, 3, 1, options)
|
||||||
// The URI should have literal hyphens separating title-message-color
|
// The URI should have literal hyphens separating title-message-color
|
||||||
expect(badge).toBe('')
|
expect(badge).toBe(
|
||||||
|
''
|
||||||
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -107,7 +119,9 @@ describe('getBadge', () => {
|
||||||
it('includes passed, failed and skipped counts', () => {
|
it('includes passed, failed and skipped counts', () => {
|
||||||
const options: ReportOptions = {...DEFAULT_OPTIONS}
|
const options: ReportOptions = {...DEFAULT_OPTIONS}
|
||||||
const badge = getBadge(5, 2, 1, options)
|
const badge = getBadge(5, 2, 1, options)
|
||||||
expect(badge).toBe('')
|
expect(badge).toBe(
|
||||||
|
''
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('uses "none" message when no tests', () => {
|
it('uses "none" message when no tests', () => {
|
||||||
|
|
@ -117,4 +131,3 @@ describe('getBadge', () => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,32 +4,58 @@ import jest from 'eslint-plugin-jest'
|
||||||
export default [
|
export default [
|
||||||
github.getFlatConfigs().recommended,
|
github.getFlatConfigs().recommended,
|
||||||
...github.getFlatConfigs().typescript,
|
...github.getFlatConfigs().typescript,
|
||||||
|
{
|
||||||
|
settings: {
|
||||||
|
'import/parsers': {
|
||||||
|
'@typescript-eslint/parser': ['.ts', '.tsx']
|
||||||
|
},
|
||||||
|
'import/resolver': {
|
||||||
|
typescript: {
|
||||||
|
project: './tsconfig.json',
|
||||||
|
alwaysTryTypes: true
|
||||||
|
},
|
||||||
|
node: {
|
||||||
|
extensions: ['.js', '.mjs', '.ts', '.tsx']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
files: ['src/**/*.ts'],
|
files: ['src/**/*.ts'],
|
||||||
rules: {
|
rules: {
|
||||||
'no-shadow': 'off',
|
|
||||||
'import/no-namespace': 'off',
|
|
||||||
'i18n-text/no-en': 'off',
|
'i18n-text/no-en': 'off',
|
||||||
|
'eslint-comments/no-use': 'off',
|
||||||
|
'import/no-namespace': 'off',
|
||||||
|
'import/no-named-as-default': 'off',
|
||||||
|
'no-shadow': 'off',
|
||||||
|
'no-unused-vars': 'off',
|
||||||
'prefer-template': 'off',
|
'prefer-template': 'off',
|
||||||
"@typescript-eslint/array-type": ['error', {default: 'array'}],
|
camelcase: 'off',
|
||||||
|
semi: 'off',
|
||||||
|
'@typescript-eslint/array-type': ['error', {default: 'array'}],
|
||||||
'@typescript-eslint/no-unused-vars': ['error', {varsIgnorePattern: '^_'}],
|
'@typescript-eslint/no-unused-vars': ['error', {varsIgnorePattern: '^_'}],
|
||||||
'@typescript-eslint/no-shadow': ['error'],
|
'@typescript-eslint/no-shadow': ['error'],
|
||||||
},
|
// Modern replacements for deprecated rules from the legacy config.
|
||||||
|
'@typescript-eslint/no-empty-object-type': 'error',
|
||||||
|
'@typescript-eslint/no-require-imports': 'error'
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
files: ['__tests__/**/*.test.ts'],
|
files: ['__tests__/**/*.test.ts'],
|
||||||
...jest.configs['flat/recommended'],
|
...jest.configs['flat/recommended'],
|
||||||
plugins: {
|
plugins: {
|
||||||
jest,
|
jest
|
||||||
},
|
},
|
||||||
languageOptions: {
|
languageOptions: {
|
||||||
globals: jest.environments.globals.globals,
|
globals: jest.environments.globals.globals
|
||||||
},
|
},
|
||||||
rules: {
|
rules: {
|
||||||
'i18n-text/no-en': 'off',
|
'i18n-text/no-en': 'off',
|
||||||
'import/no-namespace': 'off',
|
'import/no-namespace': 'off',
|
||||||
"@typescript-eslint/array-type": ['error', {default: 'array'}],
|
'@typescript-eslint/array-type': ['error', {default: 'array'}],
|
||||||
},
|
'@typescript-eslint/no-explicit-any': 'off',
|
||||||
|
'@typescript-eslint/explicit-function-return-type': 'off'
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ignores: [
|
ignores: [
|
||||||
|
|
@ -41,7 +67,7 @@ export default [
|
||||||
'assets/**',
|
'assets/**',
|
||||||
'reports/**',
|
'reports/**',
|
||||||
'eslint.config.mjs',
|
'eslint.config.mjs',
|
||||||
'jest.config.cjs',
|
'jest.config.cjs'
|
||||||
],
|
]
|
||||||
},
|
}
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -62,8 +62,11 @@ export class DotnetTrxParser implements TestParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
private getTestClasses(trx: TrxReport): TestClass[] {
|
private getTestClasses(trx: TrxReport): TestClass[] {
|
||||||
if (trx.TestRun.TestDefinitions === undefined || trx.TestRun.Results === undefined ||
|
if (
|
||||||
!trx.TestRun.TestDefinitions.some(td => td.UnitTest && Array.isArray(td.UnitTest))) {
|
trx.TestRun.TestDefinitions === undefined ||
|
||||||
|
trx.TestRun.Results === undefined ||
|
||||||
|
!trx.TestRun.TestDefinitions.some(td => td.UnitTest && Array.isArray(td.UnitTest))
|
||||||
|
) {
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -81,7 +84,7 @@ export class DotnetTrxParser implements TestParser {
|
||||||
|
|
||||||
const testClasses: {[name: string]: TestClass} = {}
|
const testClasses: {[name: string]: TestClass} = {}
|
||||||
for (const r of unitTestsResults) {
|
for (const r of unitTestsResults) {
|
||||||
const className = r.test.TestMethod[0].$.className ?? "Unclassified"
|
const className = r.test.TestMethod[0].$.className ?? 'Unclassified'
|
||||||
let tc = testClasses[className]
|
let tc = testClasses[className]
|
||||||
if (tc === undefined) {
|
if (tc === undefined) {
|
||||||
tc = new TestClass(className)
|
tc = new TestClass(className)
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,6 @@
|
||||||
import {ParseOptions, TestParser} from '../../test-parser.js'
|
import {ParseOptions, TestParser} from '../../test-parser.js'
|
||||||
|
|
||||||
import {GoTestEvent} from './golang-json-types.js'
|
import {GoTestEvent} from './golang-json-types.js'
|
||||||
import { getExceptionSource } from '../../utils/node-utils.js'
|
|
||||||
import { getBasePath, normalizeFilePath } from '../../utils/path-utils.js'
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
TestExecutionResult,
|
TestExecutionResult,
|
||||||
|
|
@ -24,7 +22,10 @@ export class GolangJsonParser implements TestParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
private async getGolangTestEvents(path: string, content: string): Promise<GoTestEvent[]> {
|
private async getGolangTestEvents(path: string, content: string): Promise<GoTestEvent[]> {
|
||||||
return content.trim().split('\n').map((line, index) => {
|
return content
|
||||||
|
.trim()
|
||||||
|
.split('\n')
|
||||||
|
.map((line, index) => {
|
||||||
try {
|
try {
|
||||||
return JSON.parse(line) as GoTestEvent
|
return JSON.parse(line) as GoTestEvent
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
@ -63,9 +64,8 @@ export class GolangJsonParser implements TestParser {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
let groupName: string | null
|
const [first, ...rest] = event.Test.split('/')
|
||||||
let rest: string[]
|
let groupName: string | null = first
|
||||||
[groupName, ...rest] = event.Test.split('/')
|
|
||||||
let testName = rest.join('/')
|
let testName = rest.join('/')
|
||||||
if (!testName) {
|
if (!testName) {
|
||||||
testName = groupName
|
testName = groupName
|
||||||
|
|
@ -80,9 +80,8 @@ export class GolangJsonParser implements TestParser {
|
||||||
|
|
||||||
const lastEvent = eventGroup.at(-1)!
|
const lastEvent = eventGroup.at(-1)!
|
||||||
|
|
||||||
const result: TestExecutionResult = lastEvent.Action === 'pass' ? 'success'
|
const result: TestExecutionResult =
|
||||||
: lastEvent.Action === 'skip' ? 'skipped'
|
lastEvent.Action === 'pass' ? 'success' : lastEvent.Action === 'skip' ? 'skipped' : 'failed'
|
||||||
: 'failed'
|
|
||||||
if (lastEvent.Elapsed === undefined) {
|
if (lastEvent.Elapsed === undefined) {
|
||||||
throw new Error('missing elapsed on final test event')
|
throw new Error('missing elapsed on final test event')
|
||||||
}
|
}
|
||||||
|
|
@ -94,7 +93,7 @@ export class GolangJsonParser implements TestParser {
|
||||||
.filter(e => e.Action === 'output')
|
.filter(e => e.Action === 'output')
|
||||||
.map(e => e.Output ?? '')
|
.map(e => e.Output ?? '')
|
||||||
// Go output prepends indentation to help group tests - remove it
|
// Go output prepends indentation to help group tests - remove it
|
||||||
.map(o => o.replace(/^ /, ''))
|
.map(o => o.replace(/^ {4}/, ''))
|
||||||
|
|
||||||
// First and last lines will be generic "test started" and "test finished" lines - remove them
|
// First and last lines will be generic "test started" and "test finished" lines - remove them
|
||||||
outputEvents.splice(0, 1)
|
outputEvents.splice(0, 1)
|
||||||
|
|
@ -103,7 +102,7 @@ export class GolangJsonParser implements TestParser {
|
||||||
const details = outputEvents.join('')
|
const details = outputEvents.join('')
|
||||||
error = {
|
error = {
|
||||||
message: details,
|
message: details,
|
||||||
details: details
|
details
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,4 @@
|
||||||
export type GoTestAction = 'start'
|
export type GoTestAction = 'start' | 'run' | 'pause' | 'cont' | 'pass' | 'bench' | 'fail' | 'output' | 'skip'
|
||||||
| 'run'
|
|
||||||
| 'pause'
|
|
||||||
| 'cont'
|
|
||||||
| 'pass'
|
|
||||||
| 'bench'
|
|
||||||
| 'fail'
|
|
||||||
| 'output'
|
|
||||||
| 'skip'
|
|
||||||
|
|
||||||
export type GoTestEvent = {
|
export type GoTestEvent = {
|
||||||
Time: string
|
Time: string
|
||||||
|
|
|
||||||
|
|
@ -130,7 +130,7 @@ export class PhpunitJunitParser implements TestParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
const failure = failures[0]
|
const failure = failures[0]
|
||||||
const details = typeof failure === 'string' ? failure : failure._ ?? ''
|
const details = typeof failure === 'string' ? failure : (failure._ ?? '')
|
||||||
|
|
||||||
// PHPUnit provides file path directly in testcase attributes
|
// PHPUnit provides file path directly in testcase attributes
|
||||||
let filePath: string | undefined
|
let filePath: string | undefined
|
||||||
|
|
|
||||||
|
|
@ -199,7 +199,7 @@ export class NetteTesterJunitParser implements TestParser {
|
||||||
|
|
||||||
const failure = failures[0]
|
const failure = failures[0]
|
||||||
// For Nette Tester, details are in the message attribute, not as inner text
|
// For Nette Tester, details are in the message attribute, not as inner text
|
||||||
const details = typeof failure === 'string' ? failure : failure._ ?? failure.$?.message ?? ''
|
const details = typeof failure === 'string' ? failure : (failure._ ?? failure.$?.message ?? '')
|
||||||
|
|
||||||
// Try to extract file path and line from error details
|
// Try to extract file path and line from error details
|
||||||
let errorFilePath: string | undefined
|
let errorFilePath: string | undefined
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue