From b195bd946756dc1e284e419804adf64434f1c84a Mon Sep 17 00:00:00 2001 From: recca0120 Date: Fri, 3 Jan 2025 12:45:53 +0800 Subject: [PATCH 1/3] refactor --- src/PHPUnit/TestParser/PHPUnitParser.test.ts | 829 ++++++++----------- src/PHPUnit/TestParser/PestParser.test.ts | 84 +- 2 files changed, 400 insertions(+), 513 deletions(-) diff --git a/src/PHPUnit/TestParser/PHPUnitParser.test.ts b/src/PHPUnit/TestParser/PHPUnitParser.test.ts index 6eab0672..ed1dc574 100644 --- a/src/PHPUnit/TestParser/PHPUnitParser.test.ts +++ b/src/PHPUnit/TestParser/PHPUnitParser.test.ts @@ -15,489 +15,386 @@ export const parse = (buffer: Buffer | string, file: string) => { }; describe('PHPUnitParser Test', () => { - describe('PHPUnit', () => { - const findTest = (tests: TestDefinition[], methodName: string) => { - const lookup = { - [TestType.method]: (test: TestDefinition) => test.methodName === methodName, - [TestType.class]: (test: TestDefinition) => test.className === methodName && !test.methodName, - [TestType.namespace]: (test: TestDefinition) => test.classFQN === methodName && !test.className && !test.methodName, - } as { [key: string]: Function }; - - for (const [, fn] of Object.entries(lookup)) { - const test = tests.find((test: TestDefinition) => fn(test)); - - if (test) { - return test; - } + const findTest = (tests: TestDefinition[], id: string) => { + const lookup = { + [TestType.method]: (test: TestDefinition) => test.methodName === id, + [TestType.class]: (test: TestDefinition) => test.className === id && !test.methodName, + [TestType.namespace]: (test: TestDefinition) => test.classFQN === id && !test.className && !test.methodName, + } as { [key: string]: Function }; + + for (const [, fn] of Object.entries(lookup)) { + const test = tests.find((test: TestDefinition) => fn(test)); + + if (test) { + return test; } + } + + return undefined; + }; + + const givenTest = (file: string, content: string, id: string) => { + return findTest(parse(content, file), id); + }; + + describe('AssertionsTest', () => { + const file = phpUnitProject('tests/AssertionsTest.php'); + let content: string; + beforeAll(async () => content = (await readFile(file)).toString()); + + it('parse namespace', () => { + expect(givenTest(file, content, 'Recca0120\\VSCode\\Tests')).toEqual(expect.objectContaining({ + type: TestType.namespace, + // file, + id: 'namespace:Tests (Recca0120\\VSCode\\Tests)', + classFQN: 'Recca0120\\VSCode\\Tests', + namespace: 'Recca0120\\VSCode\\Tests', + depth: 1, + })); + }); + + it('parse class', () => { + expect(givenTest(file, content, 'AssertionsTest')).toEqual(expect.objectContaining({ + type: TestType.class, + file, + id: 'Assertions (Recca0120\\VSCode\\Tests\\Assertions)', + classFQN: 'Recca0120\\VSCode\\Tests\\AssertionsTest', + namespace: 'Recca0120\\VSCode\\Tests', + className: 'AssertionsTest', + start: { line: 8, character: 0 }, + end: { line: 83, character: 1 }, + depth: 2, + })); + }); + + it('it should parse test_passed', () => { + expect(givenTest(file, content, 'test_passed')).toEqual(expect.objectContaining({ + type: TestType.method, + file, + id: 'Assertions (Recca0120\\VSCode\\Tests\\Assertions)::Passed', + classFQN: 'Recca0120\\VSCode\\Tests\\AssertionsTest', + namespace: 'Recca0120\\VSCode\\Tests', + className: 'AssertionsTest', + methodName: 'test_passed', + start: { line: 12, character: 4 }, + end: { line: 15, character: 5 }, + depth: 3, + })); + }); + + it('it should parse test_failed', () => { + expect(givenTest(file, content, 'test_failed')).toEqual(expect.objectContaining({ + type: TestType.method, + file, + id: 'Assertions (Recca0120\\VSCode\\Tests\\Assertions)::Failed', + classFQN: 'Recca0120\\VSCode\\Tests\\AssertionsTest', + namespace: 'Recca0120\\VSCode\\Tests', + className: 'AssertionsTest', + methodName: 'test_failed', + annotations: { depends: ['test_passed'] }, + start: { line: 20, character: 4 }, + end: { line: 23, character: 5 }, + depth: 3, + })); + }); + + it('it should parse test_is_not_same', () => { + expect(givenTest(file, content, 'test_is_not_same')).toEqual(expect.objectContaining({ + type: TestType.method, + file, + id: 'Assertions (Recca0120\\VSCode\\Tests\\Assertions)::Is not same', + classFQN: 'Recca0120\\VSCode\\Tests\\AssertionsTest', + namespace: 'Recca0120\\VSCode\\Tests', + className: 'AssertionsTest', + methodName: 'test_is_not_same', + start: { line: 25, character: 4 }, + end: { line: 28, character: 5 }, + depth: 3, + })); + }); + + it('it should parse test_risky', () => { + expect(givenTest(file, content, 'test_risky')).toEqual(expect.objectContaining({ + type: TestType.method, + file, + id: 'Assertions (Recca0120\\VSCode\\Tests\\Assertions)::Risky', + classFQN: 'Recca0120\\VSCode\\Tests\\AssertionsTest', + namespace: 'Recca0120\\VSCode\\Tests', + className: 'AssertionsTest', + methodName: 'test_risky', + start: { line: 30, character: 4 }, + end: { line: 33, character: 5 }, + depth: 3, + })); + }); + + it('it should parse annotation_test', () => { + expect(givenTest(file, content, 'annotation_test')).toEqual(expect.objectContaining({ + type: TestType.method, + file, + id: 'Assertions (Recca0120\\VSCode\\Tests\\Assertions)::Annotation test', + classFQN: 'Recca0120\\VSCode\\Tests\\AssertionsTest', + namespace: 'Recca0120\\VSCode\\Tests', + className: 'AssertionsTest', + methodName: 'annotation_test', + start: { line: 38, character: 4 }, + end: { line: 41, character: 5 }, + depth: 3, + })); + }); + + it('it should parse test_skipped', () => { + expect(givenTest(file, content, 'test_skipped')).toEqual(expect.objectContaining({ + type: TestType.method, + file, + id: 'Assertions (Recca0120\\VSCode\\Tests\\Assertions)::Skipped', + classFQN: 'Recca0120\\VSCode\\Tests\\AssertionsTest', + namespace: 'Recca0120\\VSCode\\Tests', + className: 'AssertionsTest', + methodName: 'test_skipped', + start: { line: 43, character: 4 }, + end: { line: 46, character: 5 }, + depth: 3, + })); + }); + + it('it should parse test_incomplete', () => { + expect(givenTest(file, content, 'test_incomplete')).toEqual(expect.objectContaining({ + type: TestType.method, + file, + id: 'Assertions (Recca0120\\VSCode\\Tests\\Assertions)::Incomplete', + classFQN: 'Recca0120\\VSCode\\Tests\\AssertionsTest', + namespace: 'Recca0120\\VSCode\\Tests', + className: 'AssertionsTest', + methodName: 'test_incomplete', + start: { line: 48, character: 4 }, + end: { line: 51, character: 5 }, + depth: 3, + })); + }); + + it('it should parse addition_provider', () => { + expect(givenTest(file, content, 'addition_provider')).toEqual(expect.objectContaining({ + type: TestType.method, + file, + id: 'Assertions (Recca0120\\VSCode\\Tests\\Assertions)::Addition provider', + classFQN: 'Recca0120\\VSCode\\Tests\\AssertionsTest', + namespace: 'Recca0120\\VSCode\\Tests', + className: 'AssertionsTest', + methodName: 'addition_provider', + annotations: { dataProvider: ['additionProvider'], depends: ['test_passed'] }, + start: { line: 60, character: 4 }, + end: { line: 63, character: 5 }, + depth: 3, + })); + }); - return undefined; - }; - - const givenTests = async (file: string) => { - const buffer = await readFile(file); - - return parse(buffer.toString(), file); - }; - - const givenTest = async (file: string, methodName: string) => { - return findTest(await givenTests(file), methodName); - }; - - describe('parse AssertionsTest', () => { - const file = phpUnitProject('tests/AssertionsTest.php'); - const namespace = 'Recca0120\\VSCode\\Tests'; - const type = TestType.method; - const className = 'AssertionsTest'; - const classFQN = `${namespace}\\${className}`; - - it('namespace', async () => { - const methodName = 'Recca0120\\VSCode\\Tests'; - const id = 'namespace:Tests (Recca0120\\VSCode\\Tests)'; - - expect(await givenTest(file, methodName)).toEqual(expect.objectContaining({ - type: TestType.namespace, - id, - classFQN: methodName, - namespace: methodName, - depth: 1, - })); - }); - - it('class', async () => { - const methodName = 'AssertionsTest'; - const id = 'Assertions (Recca0120\\VSCode\\Tests\\Assertions)'; - - expect(await givenTest(file, methodName)).toEqual(expect.objectContaining({ - type: TestType.class, - file, - id, - classFQN, - namespace, - className, - start: { line: 8, character: 0 }, - end: { line: 83, character: 1 }, - depth: 2, - })); - }); - - it('it should parse test_passed', async () => { - const methodName = 'test_passed'; - const id = 'Assertions (Recca0120\\VSCode\\Tests\\Assertions)::Passed'; - - expect(await givenTest(file, methodName)).toEqual( - expect.objectContaining({ - type, - file, - id, - classFQN, - namespace, - className, - methodName, - start: { line: 12, character: 4 }, - end: { line: 15, character: 5 }, - depth: 3, - }), - ); - }); - - it('it should parse test_failed', async () => { - const methodName = 'test_failed'; - const id = 'Assertions (Recca0120\\VSCode\\Tests\\Assertions)::Failed'; - - expect(await givenTest(file, methodName)).toEqual( - expect.objectContaining({ - file, - id, - classFQN, - namespace, - className, - methodName, - annotations: { depends: ['test_passed'] }, - start: { line: 20, character: 4 }, - end: { line: 23, character: 5 }, - depth: 3, - }), - ); - }); - - it('it should parse test_is_not_same', async () => { - const methodName = 'test_is_not_same'; - const id = 'Assertions (Recca0120\\VSCode\\Tests\\Assertions)::Is not same'; - - expect(await givenTest(file, methodName)).toEqual( - expect.objectContaining({ - file, - id, - classFQN, - namespace, - className, - methodName, - start: { line: 25, character: 4 }, - end: { line: 28, character: 5 }, - depth: 3, - }), - ); - }); - - it('it should parse test_risky', async () => { - const methodName = 'test_risky'; - const id = 'Assertions (Recca0120\\VSCode\\Tests\\Assertions)::Risky'; - - expect(await givenTest(file, methodName)).toEqual( - expect.objectContaining({ - file, - id, - classFQN, - namespace, - className, - methodName, - start: { line: 30, character: 4 }, - end: { line: 33, character: 5 }, - depth: 3, - }), - ); - }); - - it('it should parse annotation_test', async () => { - const methodName = 'annotation_test'; - const id = 'Assertions (Recca0120\\VSCode\\Tests\\Assertions)::Annotation test'; - - expect(await givenTest(file, methodName)).toEqual( - expect.objectContaining({ - file, - id, - classFQN, - namespace, - className, - methodName, - start: { line: 38, character: 4 }, - end: { line: 41, character: 5 }, - depth: 3, - }), - ); - }); - - it('it should parse test_skipped', async () => { - const methodName = 'test_skipped'; - const id = 'Assertions (Recca0120\\VSCode\\Tests\\Assertions)::Skipped'; - - expect(await givenTest(file, methodName)).toEqual( - expect.objectContaining({ - file, - id, - classFQN, - namespace, - className, - methodName, - start: { line: 43, character: 4 }, - end: { line: 46, character: 5 }, - depth: 3, - }), - ); - }); - - it('it should parse test_incomplete', async () => { - const methodName = 'test_incomplete'; - const id = 'Assertions (Recca0120\\VSCode\\Tests\\Assertions)::Incomplete'; - - expect(await givenTest(file, methodName)).toEqual( - expect.objectContaining({ - file, - id, - classFQN, - namespace, - className, - methodName, - start: { line: 48, character: 4 }, - end: { line: 51, character: 5 }, - depth: 3, - }), - ); - }); - - it('it should parse addition_provider', async () => { - const methodName = 'addition_provider'; - const id = 'Assertions (Recca0120\\VSCode\\Tests\\Assertions)::Addition provider'; - - expect(await givenTest(file, methodName)).toEqual( - expect.objectContaining({ - file, - id, - classFQN, - namespace, - className, - methodName, - annotations: { - dataProvider: ['additionProvider'], - depends: ['test_passed'], - }, - start: { line: 60, character: 4 }, - end: { line: 63, character: 5 }, - depth: 3, - }), - ); - }); - - it('it should parse testdox annotation', async () => { - const methodName = 'balanceIsInitiallyZero'; - const id = 'Assertions (Recca0120\\VSCode\\Tests\\Assertions)::Balance is initially zero'; - - expect(await givenTest(file, methodName)).toEqual( - expect.objectContaining({ - file, - id, - classFQN, - namespace, - className, - methodName, - annotations: { testdox: ['has an initial balance of zero'] }, - start: { line: 79, character: 4 }, - end: { line: 82, character: 5 }, - depth: 3, - }), - ); - }); + it('it should parse testdox annotation', () => { + expect(givenTest(file, content, 'balanceIsInitiallyZero')).toEqual(expect.objectContaining({ + type: TestType.method, + file, + id: 'Assertions (Recca0120\\VSCode\\Tests\\Assertions)::Balance is initially zero', + classFQN: 'Recca0120\\VSCode\\Tests\\AssertionsTest', + namespace: 'Recca0120\\VSCode\\Tests', + className: 'AssertionsTest', + methodName: 'balanceIsInitiallyZero', + annotations: { testdox: ['has an initial balance of zero'] }, + start: { line: 79, character: 4 }, + end: { line: 82, character: 5 }, + depth: 3, + })); }); + }); + + describe('parse AbstractTest', () => { + const file = phpUnitProject('tests/AbstractTest.php'); + let content: string; + beforeAll(async () => content = (await readFile(file)).toString()); + + it('it should not parse abstract class', () => { + expect(parse(content, file)).toHaveLength(0); + }); + }); - describe('parse AbstractTest', () => { - const file = phpUnitProject('tests/AbstractTest.php'); + describe('parse StaticMethodTest', () => { + const file = phpUnitProject('tests/StaticMethodTest.php'); + let content: string; + beforeAll(async () => content = (await readFile(file)).toString()); - it('it should not parse abstract class', async () => { - expect(await givenTests(file)).toHaveLength(0); - }); + it('StaticMethodTest should has 3 tests', () => { + expect(parse(content, file)).toHaveLength(3); }); - describe('parse StaticMethodTest', () => { - const file = phpUnitProject('tests/StaticMethodTest.php'); - const namespace = 'Recca0120\\VSCode\\Tests'; - const type = TestType.method; - const className = 'StaticMethodTest'; - const classFQN = `${namespace}\\${className}`; - - it('it should parse test_static_public_fail', async () => { - const methodName = 'test_static_public_fail'; - const id = 'Static Method (Recca0120\\VSCode\\Tests\\StaticMethod)::Static public fail'; - - expect(await givenTest(file, methodName)).toEqual( - expect.objectContaining({ - type, - file, - id, - classFQN, - namespace, - className, - methodName, - start: { line: 9, character: 4 }, - end: { line: 11, character: 5 }, - depth: 3, - }), - ); - - expect(await givenTests(file)).toHaveLength(3); - }); + it('it should parse test_static_public_fail', () => { + expect(givenTest(file, content, 'test_static_public_fail')).toEqual(expect.objectContaining({ + type: TestType.method, + file, + id: 'Static Method (Recca0120\\VSCode\\Tests\\StaticMethod)::Static public fail', + classFQN: 'Recca0120\\VSCode\\Tests\\StaticMethodTest', + namespace: 'Recca0120\\VSCode\\Tests', + className: 'StaticMethodTest', + methodName: 'test_static_public_fail', + start: { line: 9, character: 4 }, + end: { line: 11, character: 5 }, + depth: 3, + })); }); + }); + + describe('parse HasPropertyTest', () => { + const file = phpUnitProject('tests/SubFolder/HasPropertyTest.php'); + let content: string; + beforeAll(async () => content = (await readFile(file)).toString()); - describe('parse HasPropertyTest', () => { - const file = phpUnitProject('tests/SubFolder/HasPropertyTest.php'); - const namespace = 'Recca0120\\VSCode\\Tests\\SubFolder'; - const type = TestType.method; - const className = 'HasPropertyTest'; - const classFQN = `${namespace}\\${className}`; - - it('it should parse property', async () => { - const methodName = 'property'; - const id = 'Has Property (Recca0120\\VSCode\\Tests\\SubFolder\\HasProperty)::Property'; - - expect(await givenTest(file, methodName)).toEqual( - expect.objectContaining({ - type, - file, - id, - classFQN, - namespace, - className, - methodName, - start: { line: 17, character: 4 }, - end: { line: 20, character: 5 }, - depth: 3, - }), - ); - - expect(await givenTests(file)).toHaveLength(3); - }); + it('HasPropertyTest should has 3 tests', () => { + expect(parse(content, file)).toHaveLength(3); }); - describe('parse LeadingCommentsTest', () => { - const file = phpUnitProject('tests/SubFolder/LeadingCommentsTest.php'); - const namespace = 'Recca0120\\VSCode\\Tests\\SubFolder'; - const type = TestType.method; - const className = 'LeadingCommentsTest'; - const classFQN = `${namespace}\\${className}`; - - it('it should parse firstLeadingComments', async () => { - const methodName = 'firstLeadingComments'; - const id = 'Leading Comments (Recca0120\\VSCode\\Tests\\SubFolder\\LeadingComments)::First leading comments'; - - expect(await givenTest(file, methodName)).toEqual( - expect.objectContaining({ - type, - file, - id, - classFQN, - namespace, - className, - methodName, - start: { line: 10, character: 4 }, - end: { line: 13, character: 5 }, - depth: 3, - }), - ); - }); + it('it should parse property', () => { + expect(givenTest(file, content, 'property')).toEqual(expect.objectContaining({ + type: TestType.method, + file, + id: 'Has Property (Recca0120\\VSCode\\Tests\\SubFolder\\HasProperty)::Property', + classFQN: 'Recca0120\\VSCode\\Tests\\SubFolder\\HasPropertyTest', + namespace: 'Recca0120\\VSCode\\Tests\\SubFolder', + className: 'HasPropertyTest', + methodName: 'property', + start: { line: 17, character: 4 }, + end: { line: 20, character: 5 }, + depth: 3, + })); }); + }); - describe('parse UseTraitTest', () => { - const file = phpUnitProject('tests/SubFolder/UseTraitTest.php'); - const namespace = 'Recca0120\\VSCode\\Tests\\SubFolder'; - const type = TestType.method; - const className = 'UseTraitTest'; - const classFQN = `${namespace}\\${className}`; - - it('it should parse use_trait', async () => { - const methodName = 'use_trait'; - const id = 'Use Trait (Recca0120\\VSCode\\Tests\\SubFolder\\UseTrait)::Use trait'; - - expect(await givenTest(file, methodName)).toEqual( - expect.objectContaining({ - type, - file, - id, - classFQN, - namespace, - className, - methodName, - start: { line: 12, character: 4 }, - end: { line: 15, character: 5 }, - depth: 3, - }), - ); - }); + describe('parse LeadingCommentsTest', () => { + const file = phpUnitProject('tests/SubFolder/LeadingCommentsTest.php'); + let content: string; + beforeAll(async () => content = (await readFile(file)).toString()); + + it('it should parse firstLeadingComments', () => { + expect(givenTest(file, content, 'firstLeadingComments')).toEqual(expect.objectContaining({ + type: TestType.method, + file, + id: 'Leading Comments (Recca0120\\VSCode\\Tests\\SubFolder\\LeadingComments)::First leading comments', + classFQN: 'Recca0120\\VSCode\\Tests\\SubFolder\\LeadingCommentsTest', + namespace: 'Recca0120\\VSCode\\Tests\\SubFolder', + className: 'LeadingCommentsTest', + methodName: 'firstLeadingComments', + start: { line: 10, character: 4 }, + end: { line: 13, character: 5 }, + depth: 3, + })); }); + }); - describe('parse AttributeTest', () => { - const file = phpUnitProject('tests/AttributeTest.php'); - const namespace = 'Recca0120\\VSCode\\Tests'; - const type = TestType.method; - const className = 'AttributeTest'; - const classFQN = `${namespace}\\${className}`; - - it('parse Test Attribute', async () => { - const methodName = 'hi'; - const id = 'Attribute (Recca0120\\VSCode\\Tests\\Attribute)::Hi'; - - expect(await givenTest(file, methodName)).toEqual( - expect.objectContaining({ - type, - file, - id, - classFQN, - namespace, - className, - methodName, - start: { line: 14, character: 4 }, - end: { line: 17, character: 5 }, - depth: 3, - }), - ); - }); - - it('parse DataProvider Attribute', async () => { - const methodName = 'testAdd'; - const id = 'Attribute (Recca0120\\VSCode\\Tests\\Attribute)::Add'; - - expect(await givenTest(file, methodName)).toEqual( - expect.objectContaining({ - file, - id, - classFQN, - namespace, - className, - methodName, - annotations: { dataProvider: ['additionProvider'] }, - start: { line: 20, character: 4 }, - end: { line: 23, character: 5 }, - depth: 3, - }), - ); - }); - - it('parse Depends Attribute', async () => { - const methodName = 'testPush'; - const id = 'Attribute (Recca0120\\VSCode\\Tests\\Attribute)::Push'; - - expect(await givenTest(file, methodName)).toEqual( - expect.objectContaining({ - file, - id, - classFQN, - namespace, - className, - methodName, - annotations: { depends: ['testEmpty'] }, - start: { line: 44, character: 4 }, - end: { line: 51, character: 5 }, - depth: 3, - }), - ); - }); - - it('parse TestDox Attribute', async () => { - const methodName = 'balanceIsInitiallyZero'; - const id = 'Attribute (Recca0120\\VSCode\\Tests\\Attribute)::Balance is initially zero'; - - expect(await givenTest(file, methodName)).toEqual( - expect.objectContaining({ - file, - id, - classFQN, - namespace, - className, - methodName, - annotations: { testdox: ['has an initial balance of zero'] }, - start: { line: 55, character: 4 }, - end: { line: 58, character: 5 }, - depth: 3, - }), - ); - }); + describe('parse UseTraitTest', () => { + const file = phpUnitProject('tests/SubFolder/UseTraitTest.php'); + let content: string; + beforeAll(async () => content = (await readFile(file)).toString()); + + it('it should parse use_trait', () => { + expect(givenTest(file, content, 'use_trait')).toEqual(expect.objectContaining({ + type: TestType.method, + file, + id: 'Use Trait (Recca0120\\VSCode\\Tests\\SubFolder\\UseTrait)::Use trait', + classFQN: 'Recca0120\\VSCode\\Tests\\SubFolder\\UseTraitTest', + namespace: 'Recca0120\\VSCode\\Tests\\SubFolder', + className: 'UseTraitTest', + methodName: 'use_trait', + start: { line: 12, character: 4 }, + end: { line: 15, character: 5 }, + depth: 3, + })); }); + }); + + describe('parse AttributeTest', () => { + const file = phpUnitProject('tests/AttributeTest.php'); + let content: string; + beforeAll(async () => content = (await readFile(file)).toString()); + + it('parse Test Attribute', () => { + expect(givenTest(file, content, 'hi')).toEqual(expect.objectContaining({ + type: TestType.method, + file, + id: 'Attribute (Recca0120\\VSCode\\Tests\\Attribute)::Hi', + classFQN: 'Recca0120\\VSCode\\Tests\\AttributeTest', + namespace: 'Recca0120\\VSCode\\Tests', + className: 'AttributeTest', + methodName: 'hi', + start: { line: 14, character: 4 }, + end: { line: 17, character: 5 }, + depth: 3, + })); + }); + + it('parse DataProvider Attribute', () => { + expect(givenTest(file, content, 'testAdd')).toEqual(expect.objectContaining({ + type: TestType.method, + file, + id: 'Attribute (Recca0120\\VSCode\\Tests\\Attribute)::Add', + classFQN: 'Recca0120\\VSCode\\Tests\\AttributeTest', + namespace: 'Recca0120\\VSCode\\Tests', + className: 'AttributeTest', + methodName: 'testAdd', + annotations: { dataProvider: ['additionProvider'] }, + start: { line: 20, character: 4 }, + end: { line: 23, character: 5 }, + depth: 3, + })); + }); + + it('parse Depends Attribute', () => { + expect(givenTest(file, content, 'testPush')).toEqual(expect.objectContaining({ + type: TestType.method, + file, + id: 'Attribute (Recca0120\\VSCode\\Tests\\Attribute)::Push', + classFQN: 'Recca0120\\VSCode\\Tests\\AttributeTest', + namespace: 'Recca0120\\VSCode\\Tests', + className: 'AttributeTest', + methodName: 'testPush', + annotations: { depends: ['testEmpty'] }, + start: { line: 44, character: 4 }, + end: { line: 51, character: 5 }, + depth: 3, + })); + }); + + it('parse TestDox Attribute', () => { + expect(givenTest(file, content, 'balanceIsInitiallyZero')).toEqual(expect.objectContaining({ + type: TestType.method, + file, + id: 'Attribute (Recca0120\\VSCode\\Tests\\Attribute)::Balance is initially zero', + classFQN: 'Recca0120\\VSCode\\Tests\\AttributeTest', + namespace: 'Recca0120\\VSCode\\Tests', + className: 'AttributeTest', + methodName: 'balanceIsInitiallyZero', + annotations: { testdox: ['has an initial balance of zero'] }, + start: { line: 55, character: 4 }, + end: { line: 58, character: 5 }, + depth: 3, + })); + }); + }); - describe('parse NoNamespaceTest', () => { - const file = phpUnitProject('tests/NoNamespaceTest.php'); - const type = TestType.method; - const className = 'NoNamespaceTest'; - const classFQN = className; - - it('parse NoNamespaceTest', async () => { - const methodName = 'test_no_namespace'; - await givenTests(phpUnitProject('tests/AttributeTest.php')); - const id = 'No Namespace::No namespace'; - - expect(await givenTest(file, methodName)).toEqual( - expect.objectContaining({ - type, - file, - id, - classFQN, - namespace: undefined, - className, - methodName, - start: { line: 7, character: 4 }, - end: { line: 10, character: 5 }, - depth: 3, - }), - ); - }); + describe('parse NoNamespaceTest', () => { + const file = phpUnitProject('tests/NoNamespaceTest.php'); + let content: string; + beforeAll(async () => content = (await readFile(file)).toString()); + + it('parse NoNamespaceTest', () => { + expect(givenTest(file, content, 'test_no_namespace')).toEqual(expect.objectContaining({ + type: TestType.method, + file, + id: 'No Namespace::No namespace', + classFQN: 'NoNamespaceTest', + namespace: undefined, + className: 'NoNamespaceTest', + methodName: 'test_no_namespace', + start: { line: 7, character: 4 }, + end: { line: 10, character: 5 }, + depth: 3, + })); }); }); }); diff --git a/src/PHPUnit/TestParser/PestParser.test.ts b/src/PHPUnit/TestParser/PestParser.test.ts index 496a1daa..d32466db 100644 --- a/src/PHPUnit/TestParser/PestParser.test.ts +++ b/src/PHPUnit/TestParser/PestParser.test.ts @@ -18,13 +18,11 @@ export const parse = (buffer: Buffer | string, file: string) => { }; describe('PestParser', () => { - const file = pestProject('tests/Fixtures/ExampleTest.php'); - - const findTest = (tests: TestDefinition[], methodName: string) => { + const findTest = (tests: TestDefinition[], id: string) => { const lookup = { - [TestType.method]: (test: TestDefinition) => test.methodName === methodName, - [TestType.class]: (test: TestDefinition) => test.className === methodName && !test.methodName, - [TestType.namespace]: (test: TestDefinition) => test.classFQN === methodName && !test.className && !test.methodName, + [TestType.method]: (test: TestDefinition) => test.methodName === id, + [TestType.class]: (test: TestDefinition) => test.className === id && !test.methodName, + [TestType.namespace]: (test: TestDefinition) => test.classFQN === id && !test.className && !test.methodName, } as { [key: string]: Function }; for (const [, fn] of Object.entries(lookup)) { @@ -38,20 +36,21 @@ describe('PestParser', () => { return undefined; }; - const givenTest = (methodName: string, content: string, _file?: string) => { - return findTest(parse(content, _file ?? file), methodName); + const givenTest = (file: string, content: string, id: string) => { + return findTest(parse(content, file), id); }; + const file = pestProject('tests/Fixtures/ExampleTest.php'); + it('namespace:Tests\\Fixtures', async () => { - const actual = givenTest('P\\Tests\\Fixtures', ` -toBeTrue(); }); - `); + `; - expect(actual).toEqual(expect.objectContaining({ + expect(givenTest(file, content, 'P\\Tests\\Fixtures')).toEqual(expect.objectContaining({ type: TestType.namespace, id: 'namespace:Tests\\Fixtures', classFQN: 'P\\Tests\\Fixtures', @@ -62,16 +61,13 @@ test('example', function () { }); it('ExampleTest', async () => { - const actual = givenTest('ExampleTest', ` -toBeTrue(); }) - -`); - - expect(actual).toEqual(expect.objectContaining({ +`; + expect(givenTest(file, content, 'ExampleTest')).toEqual(expect.objectContaining({ type: TestType.class, id: 'Tests\\Fixtures\\ExampleTest', classFQN: 'P\\Tests\\Fixtures\\ExampleTest', @@ -86,15 +82,14 @@ test('example', function () { }); it('example', async () => { - const actual = givenTest('example', ` -toBeTrue(); }); - `); + `; - expect(actual).toEqual({ + expect(givenTest(file, content, 'example')).toEqual({ type: TestType.method, id: 'tests/Fixtures/ExampleTest.php::example', classFQN: 'P\\Tests\\Fixtures\\ExampleTest', @@ -110,15 +105,14 @@ test('example', function () { }); it('it test example', async () => { - const actual = givenTest('it test example', ` -toBeTrue(); }); - `); + `; - expect(actual).toEqual({ + expect(givenTest(file, content, 'it test example')).toEqual({ type: TestType.method, id: 'tests/Fixtures/ExampleTest.php::it test example', classFQN: 'P\\Tests\\Fixtures\\ExampleTest', @@ -134,17 +128,15 @@ it('test example', function () { }); it('`something` → example', async () => { - const actual = givenTest('`something` → example', ` -toBeTrue(); }); }); - `); - - expect(actual).toEqual({ + `; + expect(givenTest(file, content, '`something` → example')).toEqual({ type: TestType.method, id: 'tests/Fixtures/ExampleTest.php::`something` → example', classFQN: 'P\\Tests\\Fixtures\\ExampleTest', @@ -160,12 +152,13 @@ describe('something', function () { }); it('arrow function `something` → it example', async () => { - const actual = givenTest('`something` → it example', ` - it('example', expect(true)->toBeTrue())); - `); - expect(actual).toEqual({ + `; + + expect(givenTest(file, content, '`something` → it example')).toEqual({ type: TestType.method, id: 'tests/Fixtures/ExampleTest.php::`something` → it example', classFQN: 'P\\Tests\\Fixtures\\ExampleTest', @@ -181,8 +174,7 @@ describe('something', fn () => it('example', expect(true)->toBeTrue())); }); it('`something` → `something else` → it test example', async () => { - const actual = givenTest('`something` → `something else` → it test example', ` - { - const actual = givenTest('it example 2', ` -assertTrue(true); - `); + `; - expect(actual).toEqual({ + expect(givenTest(file, content, 'it example 2')).toEqual({ type: TestType.method, id: 'tests/Fixtures/ExampleTest.php::it example 2', classFQN: 'P\\Tests\\Fixtures\\ExampleTest', @@ -231,16 +222,15 @@ it('example 2')->assertTrue(true); }); it('not test or test', async () => { - const actual = givenTest('hello', ` -toBeTrue(); }); - `); + `; - expect(actual).toBeUndefined(); + expect(givenTest(file, content, 'hello')).toBeUndefined(); }); }); \ No newline at end of file From e7d1a85b7653b16722d7359cd7511e2025d78b45 Mon Sep 17 00:00:00 2001 From: recca0120 Date: Fri, 3 Jan 2025 13:59:52 +0800 Subject: [PATCH 2/3] fix #251 --- src/PHPUnit/TestParser/PHPUnitParser.test.ts | 25 ++++++++++++++++++++ src/PHPUnit/TestParser/Parser.ts | 2 +- src/PHPUnit/TestParser/PestParser.ts | 2 +- 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/src/PHPUnit/TestParser/PHPUnitParser.test.ts b/src/PHPUnit/TestParser/PHPUnitParser.test.ts index ed1dc574..e5e518b9 100644 --- a/src/PHPUnit/TestParser/PHPUnitParser.test.ts +++ b/src/PHPUnit/TestParser/PHPUnitParser.test.ts @@ -397,4 +397,29 @@ describe('PHPUnitParser Test', () => { })); }); }); + + it('has require', () => { + const file = phpUnitProject('tests/PDF_testerTest.php'); + const content = ` Date: Fri, 3 Jan 2025 14:01:58 +0800 Subject: [PATCH 3/3] bump --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1f764e34..cbb402e1 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "displayName": "PHPUnit Test Explorer", "icon": "img/icon.png", "publisher": "recca0120", - "version": "3.5.7", + "version": "3.5.8", "private": true, "license": "MIT", "repository": {