From 1ae3d9b1848ad862cc5337659a989ba3b573b72e Mon Sep 17 00:00:00 2001 From: ivojawer Date: Fri, 22 Mar 2024 21:04:14 -0300 Subject: [PATCH 1/5] match by exact test --- .../existing-folder/package.json | 2 +- .../test-examples/normal-case/test-one.wtest | 4 ++ src/commands/test.ts | 41 +++++++++++++++++-- test/test.test.ts | 32 +++++++++------ 4 files changed, 61 insertions(+), 18 deletions(-) diff --git a/examples/init-examples/existing-folder/package.json b/examples/init-examples/existing-folder/package.json index ef8cb6a..94b9f99 100644 --- a/examples/init-examples/existing-folder/package.json +++ b/examples/init-examples/existing-folder/package.json @@ -2,6 +2,6 @@ "name": "existing-folder", "version": "1.0.0", "wollokVersion": "4.0.0", - "author": "palumbon", + "author": "ivanjawerbaum", "license": "ISC" } diff --git a/examples/test-examples/normal-case/test-one.wtest b/examples/test-examples/normal-case/test-one.wtest index fecd1a4..0a802ab 100644 --- a/examples/test-examples/normal-case/test-one.wtest +++ b/examples/test-examples/normal-case/test-one.wtest @@ -9,4 +9,8 @@ describe "this describe" { assert.equals(2, a) } + test "another test with longer name" { + assert.equals("aaa", "aaa") + } + } \ No newline at end of file diff --git a/src/commands/test.ts b/src/commands/test.ts index a0d8a28..8bd21a4 100644 --- a/src/commands/test.ts +++ b/src/commands/test.ts @@ -1,10 +1,11 @@ import { bold } from 'chalk' import { time, timeEnd } from 'console' import logger from 'loglevel' -import { Entity, Environment, Node, Test, is, match, when, WRENatives as natives, interpret } from 'wollok-ts' +import { Entity, Environment, Node, Test, is, match, when, WRENatives as natives, interpret, Describe } from 'wollok-ts' import { buildEnvironmentForProject, failureDescription, successDescription, valueDescription, validateEnvironment, handleError, ENTER, stackTrace, buildEnvironmentIcon, testIcon } from '../utils' import { logger as fileLogger } from '../logger' import { TimeMeasurer } from '../time-measurer' +import { Package } from 'wollok-ts' const { log } = console @@ -24,15 +25,47 @@ export function sanitize(value?: string): string | undefined { return value?.replaceAll('"', '') } -export function getTarget(environment: Environment, filter: string | undefined, { file, describe, test }: Options): Test[] { - const fqnByOptionalParameters = [file, describe, test].filter(Boolean).join('.') - const filterTest = sanitize(filter) ?? fqnByOptionalParameters ?? '' +export function getTarget(environment: Environment, filter: string | undefined, options: Options): Test[] { + if(filter){ + return getTargetByFilter(environment, filter) + } else { + return getTargetByOptions(environment, options) + } +} + +function getTargetByFilter(environment: Environment, filter: string | undefined): Test[] { + const filterTest = sanitize(filter) ?? '' const possibleTargets = environment.descendants.filter(is(Test)) const onlyTarget = possibleTargets.find((test: Test) => test.isOnly) const testMatches = (filter: string) => (test: Test) => !filter || sanitize(test.fullyQualifiedName)!.includes(filter) return onlyTarget ? [onlyTarget] : possibleTargets.filter(testMatches(filterTest)) } + +function getTargetByOptions(environment: Environment, { file, describe, test }: Options): Test[] { + let nodeToFilter: Environment | Package | Describe = environment + + if(file) { + nodeToFilter = environment.descendants.find(node => node.is(Package) && node.name === file) as Package | undefined ?? environment + } + + if(describe) { + nodeToFilter = nodeToFilter.descendants.find(node => node.is(Describe) && node.name === `"${describe}"`) as Describe | undefined ?? nodeToFilter + } + + const testFilter = test ? + (node: Node): node is Test => node.is(Test) && node.name === `"${test}"` : + is(Test) + + const matchedTests = nodeToFilter.descendants.filter(testFilter) + + if(matchedTests.some(test => test.isOnly)) { + return [matchedTests.find(test => test.isOnly)!] + } + + return matchedTests +} + export function tabulationForNode({ fullyQualifiedName }: { fullyQualifiedName: string }): string { return ' '.repeat(fullyQualifiedName.split('.').length - 1) } diff --git a/test/test.test.ts b/test/test.test.ts index 02fa1a2..d4d80d7 100644 --- a/test/test.test.ts +++ b/test/test.test.ts @@ -32,8 +32,9 @@ describe('Test', () => { it('should filter by test using filter option', () => { const tests = getTarget(environment, 'another test', emptyOptions) - expect(tests.length).to.equal(1) + expect(tests.length).to.equal(2) expect(tests[0].name).to.equal('"another test"') + expect(tests[1].name).to.equal('"another test with longer name"') }) it('should filter by test using filter option - case insensitive', () => { @@ -50,7 +51,7 @@ describe('Test', () => { expect(tests[0].name).to.equal('"another test"') }) - it('should filter by test using test option - case insensitive', () => { + it('should filter by test using test option - case sensitive', () => { const tests = getTarget(environment, undefined, { ...emptyOptions, test: 'aNother Test', @@ -92,9 +93,10 @@ describe('Test', () => { it('should filter by file using filter option', () => { const tests = getTarget(environment, 'test-one', emptyOptions) - expect(tests.length).to.equal(2) + expect(tests.length).to.equal(3) expect(tests[0].name).to.equal('"a test"') expect(tests[1].name).to.equal('"another test"') + expect(tests[2].name).to.equal('"another test with longer name"') }) it('should filter by file using file option', () => { @@ -102,9 +104,10 @@ describe('Test', () => { ...emptyOptions, file: 'test-one', }) - expect(tests.length).to.equal(2) + expect(tests.length).to.equal(3) expect(tests[0].name).to.equal('"a test"') expect(tests[1].name).to.equal('"another test"') + expect(tests[2].name).to.equal('"another test with longer name"') }) it('should filter by file & describe using file & describe option', () => { @@ -113,16 +116,18 @@ describe('Test', () => { file: 'test-one', describe: 'this describe', }) - expect(tests.length).to.equal(2) + expect(tests.length).to.equal(3) expect(tests[0].name).to.equal('"a test"') expect(tests[1].name).to.equal('"another test"') + expect(tests[2].name).to.equal('"another test with longer name"') }) it('should filter by file & describe using filter option', () => { const tests = getTarget(environment, 'test-one.this describe', emptyOptions) - expect(tests.length).to.equal(2) + expect(tests.length).to.equal(3) expect(tests[0].name).to.equal('"a test"') expect(tests[1].name).to.equal('"another test"') + expect(tests[2].name).to.equal('"another test with longer name"') }) it('should filter by file & describe & test using file & describe & test option', () => { @@ -138,8 +143,9 @@ describe('Test', () => { it('should filter by file using filter option', () => { const tests = getTarget(environment, 'test-one.this describe.another test', emptyOptions) - expect(tests.length).to.equal(1) + expect(tests.length).to.equal(2) expect(tests[0].name).to.equal('"another test"') + expect(tests[1].name).to.equal('"another test with longer name"') }) }) @@ -283,23 +289,23 @@ describe('Test', () => { }) expect(processExitSpy.callCount).to.equal(0) - expect(spyCalledWithSubstring(loggerInfoSpy, 'Running 2 tests')).to.be.true - expect(spyCalledWithSubstring(loggerInfoSpy, '2 passing')).to.be.true + expect(spyCalledWithSubstring(loggerInfoSpy, 'Running 3 tests')).to.be.true + expect(spyCalledWithSubstring(loggerInfoSpy, '3 passing')).to.be.true expect(spyCalledWithSubstring(loggerInfoSpy, '0 failing')).to.be.false // old version expect(fileLoggerInfoSpy.calledOnce).to.be.true - expect(fileLoggerInfoSpy.firstCall.firstArg.result).to.deep.equal({ ok: 2, failed: 0 }) + expect(fileLoggerInfoSpy.firstCall.firstArg.result).to.deep.equal({ ok: 3, failed: 0 }) }) it('returns exit code 2 if one or more tests fail', async () => { await test(undefined, emptyOptions) expect(processExitSpy.calledWith(2)).to.be.true - expect(spyCalledWithSubstring(loggerInfoSpy, 'Running 5 tests')).to.be.true - expect(spyCalledWithSubstring(loggerInfoSpy, '4 passing')).to.be.true + expect(spyCalledWithSubstring(loggerInfoSpy, 'Running 6 tests')).to.be.true + expect(spyCalledWithSubstring(loggerInfoSpy, '5 passing')).to.be.true expect(spyCalledWithSubstring(loggerInfoSpy, '1 failing')).to.be.true expect(fileLoggerInfoSpy.calledOnce).to.be.true const fileLoggerArg = fileLoggerInfoSpy.firstCall.firstArg - expect(fileLoggerArg.result).to.deep.equal({ ok: 4, failed: 1 }) + expect(fileLoggerArg.result).to.deep.equal({ ok: 5, failed: 1 }) expect(fileLoggerArg.failures.length).to.equal(1) }) From 2b2686bb6d1619cf0ae20c2d4c75cddc65ee1690 Mon Sep 17 00:00:00 2001 From: ivojawer Date: Fri, 22 Mar 2024 21:23:50 -0300 Subject: [PATCH 2/5] group tests by options used --- src/commands/test.ts | 11 +-- test/test.test.ts | 195 ++++++++++++++++++++++--------------------- 2 files changed, 104 insertions(+), 102 deletions(-) diff --git a/src/commands/test.ts b/src/commands/test.ts index 8bd21a4..bcfcc0f 100644 --- a/src/commands/test.ts +++ b/src/commands/test.ts @@ -29,7 +29,7 @@ export function getTarget(environment: Environment, filter: string | undefined, if(filter){ return getTargetByFilter(environment, filter) } else { - return getTargetByOptions(environment, options) + return getTargetByPreciseOptions(environment, options) } } @@ -42,13 +42,12 @@ function getTargetByFilter(environment: Environment, filter: string | undefined) } -function getTargetByOptions(environment: Environment, { file, describe, test }: Options): Test[] { +function getTargetByPreciseOptions(environment: Environment, { file, describe, test }: Options): Test[] { let nodeToFilter: Environment | Package | Describe = environment if(file) { nodeToFilter = environment.descendants.find(node => node.is(Package) && node.name === file) as Package | undefined ?? environment } - if(describe) { nodeToFilter = nodeToFilter.descendants.find(node => node.is(Describe) && node.name === `"${describe}"`) as Describe | undefined ?? nodeToFilter } @@ -59,11 +58,9 @@ function getTargetByOptions(environment: Environment, { file, describe, test }: const matchedTests = nodeToFilter.descendants.filter(testFilter) - if(matchedTests.some(test => test.isOnly)) { - return [matchedTests.find(test => test.isOnly)!] - } + const onlyTest = matchedTests.find(test => test.isOnly) - return matchedTests + return onlyTest ? [onlyTest] : matchedTests } export function tabulationForNode({ fullyQualifiedName }: { fullyQualifiedName: string }): string { diff --git a/test/test.test.ts b/test/test.test.ts index d4d80d7..bcc552a 100644 --- a/test/test.test.ts +++ b/test/test.test.ts @@ -30,122 +30,127 @@ describe('Test', () => { environment = await buildEnvironmentForProject(projectPath) }) - it('should filter by test using filter option', () => { - const tests = getTarget(environment, 'another test', emptyOptions) - expect(tests.length).to.equal(2) - expect(tests[0].name).to.equal('"another test"') - expect(tests[1].name).to.equal('"another test with longer name"') - }) + describe('using filter option', () => { + it('should filter by test using filter option', () => { + const tests = getTarget(environment, 'another test', emptyOptions) + expect(tests.length).to.equal(2) + expect(tests[0].name).to.equal('"another test"') + expect(tests[1].name).to.equal('"another test with longer name"') + }) - it('should filter by test using filter option - case insensitive', () => { - const tests = getTarget(environment, 'aNothEr Test', emptyOptions) - expect(tests.length).to.equal(0) - }) + it('should filter by test using filter option - case insensitive', () => { + const tests = getTarget(environment, 'aNothEr Test', emptyOptions) + expect(tests.length).to.equal(0) + }) - it('should filter by test using test option', () => { - const tests = getTarget(environment, undefined, { - ...emptyOptions, - test: 'another test', + it('should filter by describe using filter option', () => { + const tests = getTarget(environment, 'second describe', emptyOptions) + expect(tests.length).to.equal(2) + expect(tests[0].name).to.equal('"second test"') + expect(tests[1].name).to.equal('"another second test"') }) - expect(tests.length).to.equal(1) - expect(tests[0].name).to.equal('"another test"') - }) - it('should filter by test using test option - case sensitive', () => { - const tests = getTarget(environment, undefined, { - ...emptyOptions, - test: 'aNother Test', + it('should filter by describe using filter option - case insensitive', () => { + const tests = getTarget(environment, 'SeCOND describe', emptyOptions) + expect(tests.length).to.equal(0) }) - expect(tests.length).to.equal(0) - }) - it('should filter by describe using filter option', () => { - const tests = getTarget(environment, 'second describe', emptyOptions) - expect(tests.length).to.equal(2) - expect(tests[0].name).to.equal('"second test"') - expect(tests[1].name).to.equal('"another second test"') - }) + it('should filter by file using filter option', () => { + const tests = getTarget(environment, 'test-one', emptyOptions) + expect(tests.length).to.equal(3) + expect(tests[0].name).to.equal('"a test"') + expect(tests[1].name).to.equal('"another test"') + expect(tests[2].name).to.equal('"another test with longer name"') + }) - it('should filter by describe using filter option - case insensitive', () => { - const tests = getTarget(environment, 'SeCOND describe', emptyOptions) - expect(tests.length).to.equal(0) - }) + it('should filter by file & describe using filter option', () => { + const tests = getTarget(environment, 'test-one.this describe', emptyOptions) + expect(tests.length).to.equal(3) + expect(tests[0].name).to.equal('"a test"') + expect(tests[1].name).to.equal('"another test"') + expect(tests[2].name).to.equal('"another test with longer name"') + }) - it('should filter by describe using describe option', () => { - const tests = getTarget(environment, undefined, { - ...emptyOptions, - describe: 'second describe', + it('should filter by file using filter option', () => { + const tests = getTarget(environment, 'test-one.this describe.another test', emptyOptions) + expect(tests.length).to.equal(2) + expect(tests[0].name).to.equal('"another test"') + expect(tests[1].name).to.equal('"another test with longer name"') }) - expect(tests.length).to.equal(2) - expect(tests[0].name).to.equal('"second test"') - expect(tests[1].name).to.equal('"another second test"') + }) - it('should filter by describe & test using describe & test option', () => { - const tests = getTarget(environment, undefined, { - ...emptyOptions, - describe: 'second describe', - test: 'another second test', + describe('with file/describe/test options', () => { + it('should filter by test using test option', () => { + const tests = getTarget(environment, undefined, { + ...emptyOptions, + test: 'another test', + }) + expect(tests.length).to.equal(1) + expect(tests[0].name).to.equal('"another test"') }) - expect(tests.length).to.equal(1) - expect(tests[0].name).to.equal('"another second test"') - }) - it('should filter by file using filter option', () => { - const tests = getTarget(environment, 'test-one', emptyOptions) - expect(tests.length).to.equal(3) - expect(tests[0].name).to.equal('"a test"') - expect(tests[1].name).to.equal('"another test"') - expect(tests[2].name).to.equal('"another test with longer name"') - }) + it('should filter by test using test option - case sensitive', () => { + const tests = getTarget(environment, undefined, { + ...emptyOptions, + test: 'aNother Test', + }) + expect(tests.length).to.equal(0) + }) - it('should filter by file using file option', () => { - const tests = getTarget(environment, undefined, { - ...emptyOptions, - file: 'test-one', + it('should filter by describe using describe option', () => { + const tests = getTarget(environment, undefined, { + ...emptyOptions, + describe: 'second describe', + }) + expect(tests.length).to.equal(2) + expect(tests[0].name).to.equal('"second test"') + expect(tests[1].name).to.equal('"another second test"') }) - expect(tests.length).to.equal(3) - expect(tests[0].name).to.equal('"a test"') - expect(tests[1].name).to.equal('"another test"') - expect(tests[2].name).to.equal('"another test with longer name"') - }) - it('should filter by file & describe using file & describe option', () => { - const tests = getTarget(environment, undefined, { - ...emptyOptions, - file: 'test-one', - describe: 'this describe', + it('should filter by describe & test using describe & test option', () => { + const tests = getTarget(environment, undefined, { + ...emptyOptions, + describe: 'second describe', + test: 'another second test', + }) + expect(tests.length).to.equal(1) + expect(tests[0].name).to.equal('"another second test"') }) - expect(tests.length).to.equal(3) - expect(tests[0].name).to.equal('"a test"') - expect(tests[1].name).to.equal('"another test"') - expect(tests[2].name).to.equal('"another test with longer name"') - }) - it('should filter by file & describe using filter option', () => { - const tests = getTarget(environment, 'test-one.this describe', emptyOptions) - expect(tests.length).to.equal(3) - expect(tests[0].name).to.equal('"a test"') - expect(tests[1].name).to.equal('"another test"') - expect(tests[2].name).to.equal('"another test with longer name"') - }) + it('should filter by file using file option', () => { + const tests = getTarget(environment, undefined, { + ...emptyOptions, + file: 'test-one', + }) + expect(tests.length).to.equal(3) + expect(tests[0].name).to.equal('"a test"') + expect(tests[1].name).to.equal('"another test"') + expect(tests[2].name).to.equal('"another test with longer name"') + }) - it('should filter by file & describe & test using file & describe & test option', () => { - const tests = getTarget(environment, undefined, { - ...emptyOptions, - file: 'test-one', - describe: 'this describe', - test: 'another test', + it('should filter by file & describe using file & describe option', () => { + const tests = getTarget(environment, undefined, { + ...emptyOptions, + file: 'test-one', + describe: 'this describe', + }) + expect(tests.length).to.equal(3) + expect(tests[0].name).to.equal('"a test"') + expect(tests[1].name).to.equal('"another test"') + expect(tests[2].name).to.equal('"another test with longer name"') }) - expect(tests.length).to.equal(1) - expect(tests[0].name).to.equal('"another test"') - }) - it('should filter by file using filter option', () => { - const tests = getTarget(environment, 'test-one.this describe.another test', emptyOptions) - expect(tests.length).to.equal(2) - expect(tests[0].name).to.equal('"another test"') - expect(tests[1].name).to.equal('"another test with longer name"') + it('should filter by file & describe & test using file & describe & test option', () => { + const tests = getTarget(environment, undefined, { + ...emptyOptions, + file: 'test-one', + describe: 'this describe', + test: 'another test', + }) + expect(tests.length).to.equal(1) + expect(tests[0].name).to.equal('"another test"') + }) }) }) From 70d60fe904ce8e326133c1f34c51d3f52ea0fe79 Mon Sep 17 00:00:00 2001 From: ivojawer Date: Tue, 26 Mar 2024 01:29:37 -0300 Subject: [PATCH 3/5] Refac getTarget so it doesnt repeat logic Co-authored-by: Fernando Dodino --- src/commands/test.ts | 43 ++++++++++++++++++------------------------- 1 file changed, 18 insertions(+), 25 deletions(-) diff --git a/src/commands/test.ts b/src/commands/test.ts index bcfcc0f..ab2a046 100644 --- a/src/commands/test.ts +++ b/src/commands/test.ts @@ -25,44 +25,37 @@ export function sanitize(value?: string): string | undefined { return value?.replaceAll('"', '') } -export function getTarget(environment: Environment, filter: string | undefined, options: Options): Test[] { - if(filter){ - return getTargetByFilter(environment, filter) - } else { - return getTargetByPreciseOptions(environment, options) - } +export function sanitize(value?: string): string | undefined { + return value?.replaceAll('"', '') } -function getTargetByFilter(environment: Environment, filter: string | undefined): Test[] { - const filterTest = sanitize(filter) ?? '' - const possibleTargets = environment.descendants.filter(is(Test)) +export function getTarget(environment: Environment, filter: string | undefined, options: Options): Test[] { + const possibleTargets = getBaseNode(environment, filter, options).descendants.filter(getTestFilter(filter, options)) const onlyTarget = possibleTargets.find((test: Test) => test.isOnly) const testMatches = (filter: string) => (test: Test) => !filter || sanitize(test.fullyQualifiedName)!.includes(filter) + const filterTest = sanitize(filter) ?? '' return onlyTarget ? [onlyTarget] : possibleTargets.filter(testMatches(filterTest)) } +function getBaseNode(environment: Environment, filter: string | undefined, options: Options): Environment | Package | Describe { + if (filter) return environment -function getTargetByPreciseOptions(environment: Environment, { file, describe, test }: Options): Test[] { + const { file, describe } = options let nodeToFilter: Environment | Package | Describe = environment - - if(file) { - nodeToFilter = environment.descendants.find(node => node.is(Package) && node.name === file) as Package | undefined ?? environment + if (file) { + nodeToFilter = environment.descendants.find(node => node.is(Package) && node.name === file) as Package | undefined ?? nodeToFilter } - if(describe) { - nodeToFilter = nodeToFilter.descendants.find(node => node.is(Describe) && node.name === `"${describe}"`) as Describe | undefined ?? nodeToFilter + if (describe) { + nodeToFilter = environment.descendants.find(node => node.is(Describe) && node.name === `"${describe}"`) as Describe | undefined ?? nodeToFilter } - - const testFilter = test ? - (node: Node): node is Test => node.is(Test) && node.name === `"${test}"` : - is(Test) - - const matchedTests = nodeToFilter.descendants.filter(testFilter) - - const onlyTest = matchedTests.find(test => test.isOnly) - - return onlyTest ? [onlyTest] : matchedTests + return nodeToFilter } +function getTestFilter(filter: string | undefined, options: Options): (node: Node) => node is Test { + return filter || !options.test ? + is(Test) : + (node: Node): node is Test => node.is(Test) && node.name === `"${options.test}"` +} export function tabulationForNode({ fullyQualifiedName }: { fullyQualifiedName: string }): string { return ' '.repeat(fullyQualifiedName.split('.').length - 1) } From 9c68947a578544232f67023fc961c2bdd79ad0d2 Mon Sep 17 00:00:00 2001 From: ivojawer Date: Tue, 26 Mar 2024 15:40:17 -0300 Subject: [PATCH 4/5] rm duplicated fn --- src/commands/test.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/commands/test.ts b/src/commands/test.ts index ab2a046..707943e 100644 --- a/src/commands/test.ts +++ b/src/commands/test.ts @@ -25,10 +25,6 @@ export function sanitize(value?: string): string | undefined { return value?.replaceAll('"', '') } -export function sanitize(value?: string): string | undefined { - return value?.replaceAll('"', '') -} - export function getTarget(environment: Environment, filter: string | undefined, options: Options): Test[] { const possibleTargets = getBaseNode(environment, filter, options).descendants.filter(getTestFilter(filter, options)) const onlyTarget = possibleTargets.find((test: Test) => test.isOnly) From 68e8b75c9e7c380c51881b7426e2938206cc923e Mon Sep 17 00:00:00 2001 From: Nahuel Palumbo Date: Thu, 28 Mar 2024 22:10:35 +0100 Subject: [PATCH 5/5] Better tests selection --- src/commands/test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/commands/test.ts b/src/commands/test.ts index 707943e..2cc3d8c 100644 --- a/src/commands/test.ts +++ b/src/commands/test.ts @@ -39,10 +39,10 @@ function getBaseNode(environment: Environment, filter: string | undefined, optio const { file, describe } = options let nodeToFilter: Environment | Package | Describe = environment if (file) { - nodeToFilter = environment.descendants.find(node => node.is(Package) && node.name === file) as Package | undefined ?? nodeToFilter + nodeToFilter = nodeToFilter.descendants.find(node => node.is(Package) && node.name === file) as Package | undefined ?? nodeToFilter } if (describe) { - nodeToFilter = environment.descendants.find(node => node.is(Describe) && node.name === `"${describe}"`) as Describe | undefined ?? nodeToFilter + nodeToFilter = nodeToFilter.descendants.find(node => node.is(Describe) && node.name === `"${describe}"`) as Describe | undefined ?? nodeToFilter } return nodeToFilter }