From 8a32a8b52295620fac8f94fca4ecd44b2b54ea1d Mon Sep 17 00:00:00 2001 From: Eike Lurz Date: Wed, 7 Feb 2024 21:36:58 +0100 Subject: [PATCH] Ignore test marked with todo (#257) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 🔧 Add eslint prettier integration Also add editor config * ♻️ Ignore tests marked with todo * 💄 Run eslint fix * 🔧 Use mts for vitest config --- .editorconfig | 10 +++ .eslintrc.json | 32 +++++---- .prettierrc | 5 +- package.json | 2 + pnpm-lock.yaml | 70 +++++++++++++++++++ src/app/escape.ts | 28 ++++---- src/app/messages/message.ts | 10 ++- src/app/messages/test-message.ts | 4 +- src/app/printer.ts | 52 ++++++-------- src/app/reporter.ts | 2 +- src/test/index.spec.ts | 3 +- .../miss-test-result-with-problem.expect.ts | 2 +- src/test/sequence-check/async-2.expect.ts | 2 +- src/test/sequence-check/async.expect.ts | 2 +- src/test/sequence-check/sync.expect.ts | 2 +- src/test/simple/work-check.expect.ts | 1 + src/test/simple/work-check.spec.ts | 14 ++++ vitest.config.ts => vitest.config.mts | 0 18 files changed, 168 insertions(+), 73 deletions(-) create mode 100644 .editorconfig rename vitest.config.ts => vitest.config.mts (100%) diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..819e523 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,10 @@ +root = true + +[*] +[*] +charset = utf-8 +insert_final_newline = true +end_of_line = lf +indent_style = space +indent_size = 2 +max_line_length = 140 diff --git a/.eslintrc.json b/.eslintrc.json index 4d2bafa..702c857 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,16 +1,20 @@ { - "env": { - "node": true, - "es2021": true - }, - "extends": "standard-with-typescript", - "parserOptions": { - "project": "./tsconfig.json", - "ecmaVersion": "latest", - "sourceType": "module" - }, - "rules": { - "@typescript-eslint/space-before-function-paren": ["error", "never"], - "@typescript-eslint/prefer-nullish-coalescing": "off" - } + "env": { + "node": true, + "es2021": true + }, + "extends": "standard-with-typescript", + "parserOptions": { + "project": "./tsconfig.json", + "ecmaVersion": "latest", + "sourceType": "module" + }, + "rules": { + "@typescript-eslint/space-before-function-paren": [ + "error", + "never" + ], + "@typescript-eslint/prefer-nullish-coalescing": "off", + "@typescript-eslint/comma-dangle": "off" + } } diff --git a/.prettierrc b/.prettierrc index 462846d..fd496a8 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,5 +1,4 @@ { - "printWidth": 140, - "tabWidth": 2, - "singleQuote": true + "singleQuote": true, + "semi": false } diff --git a/package.json b/package.json index 37da979..7eb05af 100644 --- a/package.json +++ b/package.json @@ -27,9 +27,11 @@ "@typescript-eslint/eslint-plugin": "^6.2.1", "@vitest/coverage-v8": "^1.0.1", "eslint": "^8.46.0", + "eslint-config-prettier": "^9.1.0", "eslint-config-standard-with-typescript": "^43.0.0", "eslint-plugin-import": "^2.28.0", "eslint-plugin-n": "^16.0.1", + "eslint-plugin-prettier": "^5.1.3", "eslint-plugin-promise": "^6.1.1", "rimraf": "^5.0.1", "typescript": "^5.1.6", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9d3b636..3800be8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -17,6 +17,9 @@ devDependencies: eslint: specifier: ^8.46.0 version: 8.56.0 + eslint-config-prettier: + specifier: ^9.1.0 + version: 9.1.0(eslint@8.56.0) eslint-config-standard-with-typescript: specifier: ^43.0.0 version: 43.0.1(@typescript-eslint/eslint-plugin@6.21.0)(eslint-plugin-import@2.29.1)(eslint-plugin-n@16.6.2)(eslint-plugin-promise@6.1.1)(eslint@8.56.0)(typescript@5.3.3) @@ -26,6 +29,9 @@ devDependencies: eslint-plugin-n: specifier: ^16.0.1 version: 16.6.2(eslint@8.56.0) + eslint-plugin-prettier: + specifier: ^5.1.3 + version: 5.1.3(eslint-config-prettier@9.1.0)(eslint@8.56.0)(prettier@3.2.5) eslint-plugin-promise: specifier: ^6.1.1 version: 6.1.1(eslint@8.56.0) @@ -426,6 +432,11 @@ packages: dev: true optional: true + /@pkgr/core@0.1.1: + resolution: {integrity: sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==} + engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} + dev: true + /@rollup/rollup-android-arm-eabi@4.6.1: resolution: {integrity: sha512-0WQ0ouLejaUCRsL93GD4uft3rOmB8qoQMU05Kb8CmMtMBe7XUDLAltxVZI1q6byNqEtU7N1ZX1Vw5lIpgulLQA==} cpu: [arm] @@ -1226,6 +1237,15 @@ packages: eslint: 8.56.0 dev: true + /eslint-config-prettier@9.1.0(eslint@8.56.0): + resolution: {integrity: sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==} + hasBin: true + peerDependencies: + eslint: '>=7.0.0' + dependencies: + eslint: 8.56.0 + dev: true + /eslint-config-standard-with-typescript@43.0.1(@typescript-eslint/eslint-plugin@6.21.0)(eslint-plugin-import@2.29.1)(eslint-plugin-n@16.6.2)(eslint-plugin-promise@6.1.1)(eslint@8.56.0)(typescript@5.3.3): resolution: {integrity: sha512-WfZ986+qzIzX6dcr4yGUyVb/l9N3Z8wPXCc5z/70fljs3UbWhhV+WxrfgsqMToRzuuyX9MqZ974pq2UPhDTOcA==} peerDependencies: @@ -1369,6 +1389,27 @@ packages: semver: 7.5.4 dev: true + /eslint-plugin-prettier@5.1.3(eslint-config-prettier@9.1.0)(eslint@8.56.0)(prettier@3.2.5): + resolution: {integrity: sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + '@types/eslint': '>=8.0.0' + eslint: '>=8.0.0' + eslint-config-prettier: '*' + prettier: '>=3.0.0' + peerDependenciesMeta: + '@types/eslint': + optional: true + eslint-config-prettier: + optional: true + dependencies: + eslint: 8.56.0 + eslint-config-prettier: 9.1.0(eslint@8.56.0) + prettier: 3.2.5 + prettier-linter-helpers: 1.0.0 + synckit: 0.8.8 + dev: true + /eslint-plugin-promise@6.1.1(eslint@8.56.0): resolution: {integrity: sha512-tjqWDwVZQo7UIPMeDReOpUgHCmCiH+ePnVT+5zVapL0uuHnegBUs2smM13CzOs2Xb5+MHMRFTs9v24yjba4Oig==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -1496,6 +1537,10 @@ packages: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} dev: true + /fast-diff@1.3.0: + resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==} + dev: true + /fast-glob@3.3.1: resolution: {integrity: sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==} engines: {node: '>=8.6.0'} @@ -2328,6 +2373,19 @@ packages: engines: {node: '>= 0.8.0'} dev: true + /prettier-linter-helpers@1.0.0: + resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==} + engines: {node: '>=6.0.0'} + dependencies: + fast-diff: 1.3.0 + dev: true + + /prettier@3.2.5: + resolution: {integrity: sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==} + engines: {node: '>=14'} + hasBin: true + dev: true + /pretty-format@29.7.0: resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -2596,6 +2654,14 @@ packages: engines: {node: '>= 0.4'} dev: true + /synckit@0.8.8: + resolution: {integrity: sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==} + engines: {node: ^14.18.0 || >=16.0.0} + dependencies: + '@pkgr/core': 0.1.1 + tslib: 2.6.2 + dev: true + /test-exclude@6.0.0: resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} engines: {node: '>=8'} @@ -2653,6 +2719,10 @@ packages: strip-bom: 3.0.0 dev: true + /tslib@2.6.2: + resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} + dev: true + /type-check@0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} diff --git a/src/app/escape.ts b/src/app/escape.ts index c1f81fd..2e34c09 100644 --- a/src/app/escape.ts +++ b/src/app/escape.ts @@ -1,15 +1,17 @@ export const escape = (str: string | number = ''): string => { - return str - .toString() - // eslint-disable-next-line no-control-regex - .replace(/\x1B.*?m/g, '') - .replace(/\|/g, '||') - .replace(/\n/g, '|n') - .replace(/\r/g, '|r') - .replace(/\[/g, '|[') - .replace(/]/g, '|]') - .replace(/\u0085/g, '|x') - .replace(/\u2028/g, '|l') - .replace(/\u2029/g, '|p') - .replace(/'/g, "|'") + return ( + str + .toString() + // eslint-disable-next-line no-control-regex + .replace(/\x1B.*?m/g, '') + .replace(/\|/g, '||') + .replace(/\n/g, '|n') + .replace(/\r/g, '|r') + .replace(/\[/g, '|[') + .replace(/]/g, '|]') + .replace(/\u0085/g, '|x') + .replace(/\u2028/g, '|l') + .replace(/\u2029/g, '|p') + .replace(/'/g, "|'") + ) } diff --git a/src/app/messages/message.ts b/src/app/messages/message.ts index 06087cb..12a5ec9 100644 --- a/src/app/messages/message.ts +++ b/src/app/messages/message.ts @@ -4,16 +4,14 @@ export type Parameters = { [key in string]: string | number } // https://www.jetbrains.com/help/teamcity/service-messages.html#Supported+Test+ServiceMessages export abstract class Message { - public constructor( - protected id: string, - protected name: string - ) { - } + public constructor(protected id: string, protected name: string) {} protected abstract generate(type: string, parameters: Parameters): string protected generateParameters(parameters: Parameters): string { - return Object.entries(parameters).map(([key, value]) => `${key}='${escape(value ?? '')}'`).join(' ') + return Object.entries(parameters) + .map(([key, value]) => `${key}='${escape(value ?? '')}'`) + .join(' ') } protected generateTeamcityMessage(type: string, flowId: string, parameters: Parameters): string { diff --git a/src/app/messages/test-message.ts b/src/app/messages/test-message.ts index ba3d876..f724cdc 100644 --- a/src/app/messages/test-message.ts +++ b/src/app/messages/test-message.ts @@ -16,8 +16,8 @@ export class TestMessage extends Message { return this.generate('testFailed', { message: escape(error?.message ?? ''), details: escape(error?.stackStr ?? ''), - actual: escape(error?.actual ?? ''), - expected: escape(error?.expected ?? '') + actual: escape(error?.actual as string ?? ''), + expected: escape(error?.expected as string ?? ''), }) } diff --git a/src/app/printer.ts b/src/app/printer.ts index 66aea85..51c525d 100644 --- a/src/app/printer.ts +++ b/src/app/printer.ts @@ -1,4 +1,13 @@ -import { type File, type Suite, type Task, type TaskResultPack, type Test, type UserConsoleLog, type Vitest, type ErrorWithDiff } from 'vitest' +import { + type File, + type Suite, + type Task, + type TaskResultPack, + type Test, + type UserConsoleLog, + type Vitest, + type ErrorWithDiff, +} from 'vitest' import { SuitMessage } from './messages/suite-message' import { escape } from './escape' import { TestMessage } from './messages/test-message' @@ -11,16 +20,11 @@ export class Printer { private readonly fileMessageMap = new Map() private readonly testConsoleMap = new Map() - constructor(private readonly logger: Vitest['logger']) { - } + constructor(private readonly logger: Vitest['logger']) {} public addFile = (file: File): void => { const suitMessage = new SuitMessage(file.id, escape(file.name)) - const messages = [ - suitMessage.started(), - ...file.tasks.flatMap(this.handleTask), - suitMessage.finished() - ] + const messages = [suitMessage.started(), ...file.tasks.flatMap(this.handleTask), suitMessage.finished()] this.fileMessageMap.set(file.id, messages) } @@ -35,10 +39,12 @@ export class Printer { public handeUpdate = ([id, result]: TaskResultPack): void => { const messages = this.fileMessageMap.get(id) - if ((messages != null) && (result != null) && result.state !== 'run') { + if (messages != null && result != null && result.state !== 'run') { messages - .flatMap((message: PotentialMessage) => typeof message === 'string' ? message : message()) - .forEach(message => { this.logger.console.info(message) }) + .flatMap((message: PotentialMessage) => (typeof message === 'string' ? message : message())) + .forEach((message) => { + this.logger.console.info(message) + }) this.fileMessageMap.delete(id) } } @@ -56,37 +62,25 @@ export class Printer { private readonly handleSuite = (suite: Suite): PotentialMessage[] => { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const suitMessage = new SuitMessage(suite.file!.id, escape(suite.name)) - return [ - suitMessage.started(), - ...suite.tasks.flatMap(this.handleTask), - suitMessage.finished() - ] + return [suitMessage.started(), ...suite.tasks.flatMap(this.handleTask), suitMessage.finished()] } private readonly handleTest = (test: Test): PotentialMessage => { const testMessage = new TestMessage(test) - if (test.mode === 'skip') { + if (test.mode === 'skip' || test.mode === 'todo') { return testMessage.ignored() } return () => { - const fail = (test.result == null) || test.result.state === 'fail' + const fail = test.result == null || test.result.state === 'fail' const logs = this.testConsoleMap.get(test.id) ?? [] - const logsMessages = logs.map(log => testMessage.log(log.type, log.content)) + const logsMessages = logs.map((log) => testMessage.log(log.type, log.content)) const filedMessages = fail ? this.getTestErrors(test).map(testMessage.fail) : [] - return [ - testMessage.started(), - ...logsMessages, - ...filedMessages, - testMessage.finished(test.result?.duration ?? 0) - ].filter(Boolean) + return [testMessage.started(), ...logsMessages, ...filedMessages, testMessage.finished(test.result?.duration ?? 0)].filter(Boolean) } } private readonly getTestErrors = (test: Test): ErrorWithDiff[] => - test.result?.errors ?? - test.suite.result?.errors ?? - test.file?.result?.errors ?? - [new MissingResultError(test)] + test.result?.errors ?? test.suite.result?.errors ?? test.file?.result?.errors ?? [new MissingResultError(test)] } diff --git a/src/app/reporter.ts b/src/app/reporter.ts index 8dcc418..0987c8e 100644 --- a/src/app/reporter.ts +++ b/src/app/reporter.ts @@ -16,7 +16,7 @@ class TeamCityReporter implements Reporter { } onTaskUpdate(packs: TaskResultPack[]): Awaitable { - return new Promise(resolve => { + return new Promise((resolve) => { setTimeout(() => { packs.reverse().forEach(this.printer.handeUpdate) resolve() diff --git a/src/test/index.spec.ts b/src/test/index.spec.ts index 01b777c..219d554 100644 --- a/src/test/index.spec.ts +++ b/src/test/index.spec.ts @@ -9,6 +9,7 @@ import missTestWithoutProblemExpect from './miss-test-result/miss-test-result-wi import missTestWithProblemExpect from './miss-test-result/miss-test-result-with-problem.expect' import sequenceSyncExpect from './sequence-check/sync.expect' import { compareResultWithExpect, generateExpectTest } from './utils' + describe('main tests', () => { let consoleStub: any @@ -36,7 +37,7 @@ describe('main tests', () => { expect(consoleStub.info).toHaveBeenCalled() expect(consoleStub.log).not.toHaveBeenCalled() - expect(info.length).toEqual(12) + expect(info.length).toEqual(13) compareResultWithExpect(workCheckExpect, info) }) diff --git a/src/test/miss-test-result/miss-test-result-with-problem.expect.ts b/src/test/miss-test-result/miss-test-result-with-problem.expect.ts index 8d4cfb7..af10215 100644 --- a/src/test/miss-test-result/miss-test-result-with-problem.expect.ts +++ b/src/test/miss-test-result/miss-test-result-with-problem.expect.ts @@ -8,5 +8,5 @@ export default [ ['testFailed', 'second test delays the execution result'], ['testFinished', 'second test delays the execution result'], ['testSuiteFinished', 'With delayed hook'], - ['testSuiteFinished', 'src/test/miss-test-result/miss-test-result-with-problem.spec.ts'] + ['testSuiteFinished', 'src/test/miss-test-result/miss-test-result-with-problem.spec.ts'], ] diff --git a/src/test/sequence-check/async-2.expect.ts b/src/test/sequence-check/async-2.expect.ts index b9ca822..c4a4b22 100644 --- a/src/test/sequence-check/async-2.expect.ts +++ b/src/test/sequence-check/async-2.expect.ts @@ -11,5 +11,5 @@ export default [ ['testFinished', 'should log after 1000 ms'], ['testSuiteFinished', 'Test log with async'], ['testSuiteFinished', 'Example sequence-check async file 2'], - ['testSuiteFinished', 'src/test/sequence-check/async-2.spec.ts'] + ['testSuiteFinished', 'src/test/sequence-check/async-2.spec.ts'], ] diff --git a/src/test/sequence-check/async.expect.ts b/src/test/sequence-check/async.expect.ts index e098f32..525d996 100644 --- a/src/test/sequence-check/async.expect.ts +++ b/src/test/sequence-check/async.expect.ts @@ -9,5 +9,5 @@ export default [ ['testFinished', 'should be done after 1500ms'], ['testSuiteFinished', 'Test async done'], ['testSuiteFinished', 'Example sequence-check async file 1'], - ['testSuiteFinished', 'src/test/sequence-check/async.spec.ts'] + ['testSuiteFinished', 'src/test/sequence-check/async.spec.ts'], ] diff --git a/src/test/sequence-check/sync.expect.ts b/src/test/sequence-check/sync.expect.ts index 6a7ad71..8f99c06 100644 --- a/src/test/sequence-check/sync.expect.ts +++ b/src/test/sequence-check/sync.expect.ts @@ -9,5 +9,5 @@ export default [ ['testFinished', 'should return false'], ['testSuiteFinished', 'Performance nested suit'], ['testSuiteFinished', 'Example sequence-check sync file'], - ['testSuiteFinished', 'src/test/sequence-check/sync.spec.ts'] + ['testSuiteFinished', 'src/test/sequence-check/sync.spec.ts'], ] diff --git a/src/test/simple/work-check.expect.ts b/src/test/simple/work-check.expect.ts index b1e3df3..7490698 100644 --- a/src/test/simple/work-check.expect.ts +++ b/src/test/simple/work-check.expect.ts @@ -8,6 +8,7 @@ export default [ ['testStdOut', 'should fired event test start, user std out and finished'], ['testFinished', 'should fired event test start, user std out and finished'], ['testIgnored', 'should fired event test ignored'], + ['testIgnored', 'should fired event test ignored by todo'], ['testSuiteFinished', 'should fired event suit start'], ['testSuiteFinished', 'Example test suite what generate 12 messages'], ['testSuiteFinished', 'src/test/simple/work-check.spec.ts'] diff --git a/src/test/simple/work-check.spec.ts b/src/test/simple/work-check.spec.ts index ef20799..b167775 100644 --- a/src/test/simple/work-check.spec.ts +++ b/src/test/simple/work-check.spec.ts @@ -16,6 +16,10 @@ describe('Example test suite what generate 12 messages', () => { it.skip('should fired event test ignored', () => { expect(1).toEqual(2) }) + + it.todo('should fired event test ignored by todo', () => { + expect(1).toEqual(2) + }) }) describe.skip('should not fired any event', () => { @@ -27,4 +31,14 @@ describe('Example test suite what generate 12 messages', () => { expect(1).toEqual(2) }) }) + + describe.todo('should not fired any event for todo', () => { + it('should not fired any event 2', () => { + expect(1).toEqual(2) + }) + + it('should not fired any event 2', () => { + expect(1).toEqual(2) + }) + }) }) diff --git a/vitest.config.ts b/vitest.config.mts similarity index 100% rename from vitest.config.ts rename to vitest.config.mts