From aa3884e3fae9ac5ed995c8bd674afc2c9056f514 Mon Sep 17 00:00:00 2001 From: Kay Robbins <1189050+VisLab@users.noreply.github.com> Date: Sun, 27 Oct 2024 16:15:24 -0500 Subject: [PATCH] Updated tests for curly brace recursion --- parser/columnSplicer.js | 35 +- tests/bidsTests.data.js | 280 --------- tests/bidsTests.spec.js | 16 +- tests/eventTests.spec.js | 2 +- tests/runLog.txt | 22 +- tests/tagConverterTests.spec.js | 2 +- tests/testData/bidsTests.data.js | 574 ++++++++++++++++++ tests/{ => testData}/eventTests.data.js | 4 +- .../{ => testData}/tagConverterTests.data.js | 8 +- tests/{ => testData}/tokenizerErrorData.js | 0 tests/{ => testData}/tokenizerPassingData.js | 2 +- tests/tokenizerErrorTests.spec.js | 2 +- tests/tokenizerPassingTests.spec.js | 2 +- 13 files changed, 632 insertions(+), 317 deletions(-) delete mode 100644 tests/bidsTests.data.js create mode 100644 tests/testData/bidsTests.data.js rename tests/{ => testData}/eventTests.data.js (92%) rename tests/{ => testData}/tagConverterTests.data.js (69%) rename tests/{ => testData}/tokenizerErrorData.js (100%) rename tests/{ => testData}/tokenizerPassingData.js (99%) diff --git a/parser/columnSplicer.js b/parser/columnSplicer.js index df23f7b8..fd365b04 100644 --- a/parser/columnSplicer.js +++ b/parser/columnSplicer.js @@ -111,25 +111,36 @@ export class ColumnSplicer { */ _spliceTemplate(columnTemplate) { const columnName = columnTemplate.originalTag - const replacementString = this.columnReplacements.get(columnName) - if (replacementString === undefined) { - this.issues.push(generateIssue('undefinedCurlyBraces', { column: columnName })) - return [] + + // HED column handled specially + if (columnName === 'HED') { + return this._spliceHedColumnTemplate() } + + // Not the HED column so treat as usual + const replacementString = this.columnReplacements.get(columnName) + + // Handle null or undefined replacement strings if (replacementString === null) { return null } - if (columnName === 'HED') { - return this._spliceHedColumnTemplate() + if (replacementString === undefined) { + this.issues.push(generateIssue('undefinedCurlyBraces', { column: columnName })) + return [] } + + // Handle recursive curly braces if (replacementString.columnSplices.length > 0) { this.issues.push(generateIssue('recursiveCurlyBraces', { column: columnName })) return [] } - const tagsHavePlaceholder = replacementString.tags.some((tag) => tag.originalTagName === '#') - if (tagsHavePlaceholder) { + + // Handle value templates with placeholder + if (replacementString.tags.some((tag) => tag.originalTagName === '#')) { return this._spliceValueTemplate(columnTemplate) } + + // Default case return replacementString.parseTree } @@ -142,6 +153,14 @@ export class ColumnSplicer { _spliceHedColumnTemplate() { const columnName = 'HED' const replacementString = this.columnValues.get(columnName) + if (replacementString === null || replacementString === 'n/a' || replacementString === '') { + return null + } + + if (replacementString === undefined) { + this.issues.push(generateIssue('undefinedCurlyBraces', { column: columnName })) + return [] + } return this._reparseAndSpliceString(replacementString) } diff --git a/tests/bidsTests.data.js b/tests/bidsTests.data.js deleted file mode 100644 index eaf3e55d..00000000 --- a/tests/bidsTests.data.js +++ /dev/null @@ -1,280 +0,0 @@ -import { BidsHedIssue } from '../bids' -import { generateIssue } from '../common/issues/issues' - -export const bidsTestData = [ - { - name: 'valid-bids-datasets-with-limited-hed', - description: 'HED or data is missing in various places', - tests: [ - { - testname: 'no-hed-at-all-but-both-tsv-json-non-empty', - explanation: 'Neither the sidecar or tsv has HED but neither non-empty', - schemaVersion: '8.3.0', - sidecar: { - duration: { - description: 'Duration of the event in seconds.', - }, - }, - eventsString: 'onset\tduration\n' + '7\t4', - sidecarOnlyErrors: [], - eventsOnlyErrors: [], - comboErrors: [], - }, - { - testname: 'only-header-in-tsv-with-return', - explanation: 'TSV only has header and trailing return and white space', - schemaVersion: '8.3.0', - sidecar: { - duration: { - description: 'Duration of the event in seconds.', - }, - }, - eventsString: 'onset\tduration\n ', - sidecarOnlyErrors: [], - eventsOnlyErrors: [], - comboErrors: [], - }, - { - testname: 'empty-json-empty-tsv', - explanation: 'Both sidecar and tsv are empty except for white space', - schemaVersion: '8.3.0', - sidecar: {}, - eventsString: '\n \n', - sidecarOnlyErrors: [], - eventsOnlyErrors: [], - comboErrors: [], - }, - ], - }, - { - name: 'valid-json-invalid-tsv', - description: 'JSON is valid but tsv is invalid', - tests: [ - { - testname: 'valid-sidecar-bad-tag-tsv', - explanation: 'Unrelated sidecar is valid but HED column tag is invalid', - schemaVersion: '8.3.0', - sidecar: { - event_code: { - HED: { - face: '(Red, Blue), (Green, (Yellow))', - }, - }, - }, - eventsString: 'onset\tduration\tHED\n' + '7\t4\tBaloney', - sidecarOnlyErrors: [], - eventsOnlyErrors: [ - BidsHedIssue.fromHedIssue( - generateIssue('invalidTag', { tag: 'Baloney' }), - { relativePath: 'valid-sidecar-bad-tag-tsv.tsv' }, - { tsvLine: 2 }, - ), - ], - comboErrors: [ - BidsHedIssue.fromHedIssue( - generateIssue('invalidTag', { tag: 'Baloney' }), - { path: 'valid-sidecar-bad-tag-tsv.tsv', relativePath: 'valid-sidecar-bad-tag-tsv.tsv' }, - { tsvLine: 2 }, - ), - ], - }, - { - testname: 'valid-sidecar-tsv-curly-brace', - explanation: 'The sidecar is valid, but tsv HED column has braces}', - schemaVersion: '8.3.0', - sidecar: { - event_code: { - HED: { - face: '(Red, Blue), (Green, (Yellow))', - }, - }, - }, - eventsString: 'onset\tduration\tevent_code\tHED\n' + '7\t4\tface\tRed,{blue}', - sidecarOnlyErrors: [], - eventsOnlyErrors: [ - BidsHedIssue.fromHedIssue( - generateIssue('curlyBracesInHedColumn', { column: '{blue}' }), - { relativePath: 'valid-sidecar-tsv-curly-brace.tsv' }, - { tsvLine: 2 }, - ), - ], - comboErrors: [ - BidsHedIssue.fromHedIssue( - generateIssue('curlyBracesInHedColumn', { column: '{blue}' }), - { path: 'valid-sidecar-tsv-curly-brace.tsv', relativePath: 'valid-sidecar-tsv-curly-brace.tsv' }, - { tsvLine: 2 }, - ), - ], - }, - ], - }, - { - name: 'duplicate-tag-test', - description: 'Duplicate tags can appear in isolation or in combiantion', - tests: [ - { - testname: 'first-level-duplicate-json-tsv', - explanation: 'Each is okay but when combined, duplicate tag', - schemaVersion: '8.3.0', - sidecar: { - vehicle: { - HED: { - car: 'Car', - train: 'Train', - boat: 'Boat', - }, - }, - speed: { - HED: 'Speed/# mph', - }, - transport: { - HED: { - car: 'Car', - train: 'Train', - boat: 'Boat', - maglev: 'Vehicle', - }, - }, - }, - eventsString: 'onset\tduration\tvehicle\ttransport\tspeed\n' + '19\t6\tboat\tboat\t5\n', - sidecarOnlyErrors: [], - eventsOnlyErrors: [], - comboErrors: [ - BidsHedIssue.fromHedIssue( - generateIssue('duplicateTag', { tag: 'Boat' }), - { path: 'first-level-duplicate-json-tsv.tsv', relativePath: 'first-level-duplicate-json-tsv.tsv' }, - { tsvLine: 2 }, - ), - BidsHedIssue.fromHedIssue( - generateIssue('duplicateTag', { tag: 'Boat' }), - { path: 'first-level-duplicate-json-tsv.tsv', relativePath: 'first-level-duplicate-json-tsv.tsv' }, - { tsvLine: 2 }, - ), - ], - }, - ], - }, - - { - name: 'curly-brace-tests', - description: 'Curly braces tested in various places', - tests: [ - { - testname: 'valid-curly-brace-in-sidecar-with-simple-splice', - explanation: 'Valid curly brace in sidecar and valid value is spliced in', - schemaVersion: '8.3.0', - sidecar: { - event_code: { - HED: { - face: '(Red, Blue), (Green, (Yellow))', - ball: '{ball_type}, Black', - }, - }, - ball_type: { - Description: 'Has description with HED', - HED: 'Label/#', - }, - }, - eventsString: 'onset\tduration\tevent_code\tball_type\n' + '19\t6\tball\tbig-one\n', - sidecarOnlyErrors: [], - eventsOnlyErrors: [], - comboErrors: [], - }, - { - testname: 'valid-curly-brace-in-sidecar-with-n/a-splice', - explanation: 'Valid curly brace in sidecar and but tsv splice entry is n/a', - schemaVersion: '8.3.0', - sidecar: { - event_code: { - HED: { - face: '(Red, Blue), (Green, (Yellow))', - ball: '{ball_type}, Black', - }, - }, - ball_type: { - Description: 'Has description with HED', - HED: 'Label/#', - }, - }, - eventsString: 'onset\tduration\tevent_code\tball_type\n' + '19\t6\tball\tn/a\n', - sidecarOnlyErrors: [], - eventsOnlyErrors: [], - comboErrors: [], - }, - { - testname: 'valid-curly-brace-in-sidecar-with-HED-column-splice', - explanation: 'Valid curly brace in sidecar with HED column splice', - schemaVersion: '8.3.0', - sidecar: { - event_code: { - HED: { - face: '(Red, Blue), (Green, (Yellow))', - ball: '{ball_type}, Black, ({HED})', - }, - }, - ball_type: { - Description: 'Has description with HED', - HED: 'Label/#', - }, - }, - eventsString: 'onset\tduration\tevent_code\tball_type\tHED\n' + '19\t6\tball\tn/a\tPurple\n', - sidecarOnlyErrors: [], - eventsOnlyErrors: [], - comboErrors: [], - }, - { - testname: 'invalid-curly-brace-column-slice-has-no hed', - explanation: 'A column name is used in a splice but does not have HED', - schemaVersion: '8.3.0', - sidecar: { - event_code: { - HED: { - face: '(Red, Blue), (Green, (Yellow))', - ball: '{ball_type}, Black', - }, - }, - }, - eventsString: 'onset\tduration\tevent_code\tball_type\n' + '19\t6\tball\tn/a\tPurple\n', - sidecarOnlyErrors: [ - BidsHedIssue.fromHedIssue(generateIssue('undefinedCurlyBraces', { column: 'ball_type' }), { - path: 'invalid-curly-brace-column-slice-has-no hed.json', - relativePath: 'invalid-curly-brace-column-slice-has-no hed.json', - }), - ], - eventsOnlyErrors: [], - comboErrors: [ - BidsHedIssue.fromHedIssue(generateIssue('undefinedCurlyBraces', { column: 'ball_type' }), { - path: 'invalid-curly-brace-column-slice-has-no hed.tsv', - relativePath: 'invalid-curly-brace-column-slice-has-no hed.tsv', - }), - ], - }, - { - testname: 'invalid-HED-curly-brace-but-tsv-has-no-HED-column', - explanation: 'A {HED} column splice is used in a sidecar but the tsv has no HED column', - schemaVersion: '8.3.0', - sidecar: { - event_code: { - HED: { - face: '(Red, Blue), (Green, (Yellow))', - ball: '{HED}, Black', - }, - }, - }, - eventsString: 'onset\tduration\tevent_code\n' + '19\t6\tball\n', - sidecarOnlyErrors: [], - eventsOnlyErrors: [], - comboErrors: [ - BidsHedIssue.fromHedIssue( - generateIssue('undefinedCurlyBraces', { column: 'HED' }), - { - path: 'invalid-HED-curly-brace-but-tsv-has-no-HED-column.tsv', - relativePath: 'invalid-HED-curly-brace-but-tsv-has-no-HED-column.tsv', - }, - { tsvLine: 2 }, - ), - ], - }, - ], - }, -] diff --git a/tests/bidsTests.spec.js b/tests/bidsTests.spec.js index 51a8346d..a253ff83 100644 --- a/tests/bidsTests.spec.js +++ b/tests/bidsTests.spec.js @@ -6,22 +6,20 @@ import path from 'path' import { BidsHedIssue } from '../bids/types/issues' import { buildSchemas } from '../validator/schema/init' import { SchemaSpec, SchemasSpec } from '../common/schema/types' -import { BidsDataset, BidsEventFile, BidsHedTsvValidator, BidsSidecar, BidsTsvFile } from '../bids' -import { generateIssue, IssueError } from '../common/issues/issues' +import { BidsHedTsvValidator, BidsSidecar, BidsTsvFile } from '../bids' -import { bidsTestData } from './bidsTests.data' +import { bidsTestData } from './testData/bidsTests.data' import parseTSV from '../bids/tsvParser' const fs = require('fs') //const displayLog = process.env.DISPLAY_LOG === 'true' const displayLog = true -const skippedTests = new Map() // Ability to select individual tests to run const runAll = false let onlyRun = new Map() if (!runAll) { - onlyRun = new Map([['curly-brace-tests', ['invalid-HED-curly-brace-but-tsv-has-no-HED-column']]]) + onlyRun = new Map([['duplicate-tag-tests', ['invalid-duplicate-groups-first-level-tsv']]]) } function shouldRun(name, testname) { @@ -31,11 +29,7 @@ function shouldRun(name, testname) { const cases = onlyRun.get(name) if (cases.length === 0) return true - if (cases.includes(testname)) { - return true - } else { - return false - } + return !!cases.includes(testname) } // Return an array of hedCode values extracted from an issues list. @@ -84,7 +78,7 @@ describe('BIDS validation', () => { } }) - describe.each(bidsTestData)('$name : $description', ({ name, description, tests }) => { + describe.each(bidsTestData)('$name : $description', ({ name, tests }) => { let itemLog const assertErrors = function (test, type, expectedErrors, issues, iLog) { diff --git a/tests/eventTests.spec.js b/tests/eventTests.spec.js index 898b698d..bc38e644 100644 --- a/tests/eventTests.spec.js +++ b/tests/eventTests.spec.js @@ -14,7 +14,7 @@ import { BidsHedTsvParser } from '../bids/validator/bidsHedTsvValidator' import { buildSchemas } from '../validator/schema/init' import { BidsEventFile, BidsHedTsvValidator, BidsSidecar, BidsTsvFile } from '../bids' -import { eventTestData } from './eventTests.data' +import { eventTestData } from './testData/eventTests.data' import parseTSV from '../bids/tsvParser' const fs = require('fs') diff --git a/tests/runLog.txt b/tests/runLog.txt index bf3b903a..ec166b5a 100644 --- a/tests/runLog.txt +++ b/tests/runLog.txt @@ -4,12 +4,20 @@ Total tests:3 Wrong errors:0 MissingErrors:0 ----Skipping valid-bids-datasets-with-limited-hed: empty-json-empty-tsv ----Skipping valid-json-invalid-tsv: valid-sidecar-bad-tag-tsv ----Skipping valid-json-invalid-tsv: valid-sidecar-tsv-curly-brace -----Skipping duplicate-tag-test: first-level-duplicate-json-tsv -----Skipping curly-brace-tests: valid-curly-brace-in-sidecar-with-simple-splice +----Skipping duplicate-tag-tests: invalid-first-level-duplicate-json-tsv +[invalid-duplicate-groups-first-level-tsv (Expect pass)] +[duplicate-tag-tests:invalid-duplicate-groups-first-level-tsv][Sidecar only](Expect pass) +[duplicate-tag-tests:invalid-duplicate-groups-first-level-tsv][Events only](Expect fail) +[duplicate-tag-tests:invalid-duplicate-groups-first-level-tsv][Events+side](Expect fail) +----Skipping curly-brace-tests: valid-curly-brace-in-sidecar-with-value-splice +----Skipping curly-brace-tests: valid-curly-brace-in-sidecar-with-category-splice ----Skipping curly-brace-tests: valid-curly-brace-in-sidecar-with-n/a-splice -----Skipping curly-brace-tests: valid-curly-brace-in-sidecar-with-HED-column-splice +----Skipping curly-brace-tests: valid-HED-column-splice +----Skipping curly-brace-tests: valid-HED-column-splice-with-n/a ----Skipping curly-brace-tests: invalid-curly-brace-column-slice-has-no hed -[invalid-HED-curly-brace-but-tsv-has-no-HED-column (Expect pass)] -[curly-brace-tests:invalid-HED-curly-brace-but-tsv-has-no-HED-column][Sidecar only](Expect pass) -[curly-brace-tests:invalid-HED-curly-brace-but-tsv-has-no-HED-column][Events only](Expect pass) -[curly-brace-tests:invalid-HED-curly-brace-but-tsv-has-no-HED-column][Events+side](Expect fail) \ No newline at end of file +----Skipping curly-brace-tests: invalid-HED-curly-brace-but-tsv-has-no-HED-column +----Skipping curly-brace-tests: invalid-curly-brace-in-HED-tsv-column +----Skipping curly-brace-tests: invalid-curly-brace-in-HED-tsv-column +----Skipping curly-brace-tests: invalid-recursive-curly-braces +----Skipping curly-brace-tests: invalid-self-recursive-curly-braces +----Skipping curly-brace-tests: invalid-recursive-curly-brace-chain \ No newline at end of file diff --git a/tests/tagConverterTests.spec.js b/tests/tagConverterTests.spec.js index 2803c286..0a867c94 100644 --- a/tests/tagConverterTests.spec.js +++ b/tests/tagConverterTests.spec.js @@ -11,7 +11,7 @@ import { SchemaSpec, SchemasSpec } from '../common/schema/types' import { ParsedHed3Tag } from '../parser/parsedHedTag' import { TagConverter } from '../parser/tagConverter' -import { tagConverterTestData } from './tagConverterTests.data' +import { tagConverterTestData } from './testData/tagConverterTests.data' import parseTSV from '../bids/tsvParser' const fs = require('fs') diff --git a/tests/testData/bidsTests.data.js b/tests/testData/bidsTests.data.js new file mode 100644 index 00000000..9de91972 --- /dev/null +++ b/tests/testData/bidsTests.data.js @@ -0,0 +1,574 @@ +import { BidsHedIssue } from '../../bids' +import { generateIssue } from '../../common/issues/issues' + +export const bidsTestData = [ + { + name: 'valid-bids-datasets-with-limited-hed', + description: 'HED or data is missing in various places', + tests: [ + { + testname: 'no-hed-at-all-but-both-tsv-json-non-empty', + explanation: 'Neither the sidecar or tsv has HED but neither non-empty', + schemaVersion: '8.3.0', + sidecar: { + duration: { + description: 'Duration of the event in seconds.', + }, + }, + eventsString: 'onset\tduration\n' + '7\t4', + sidecarOnlyErrors: [], + eventsOnlyErrors: [], + comboErrors: [], + }, + { + testname: 'only-header-in-tsv-with-return', + explanation: 'TSV only has header and trailing return and white space', + schemaVersion: '8.3.0', + sidecar: { + duration: { + description: 'Duration of the event in seconds.', + }, + }, + eventsString: 'onset\tduration\n ', + sidecarOnlyErrors: [], + eventsOnlyErrors: [], + comboErrors: [], + }, + { + testname: 'empty-json-empty-tsv', + explanation: 'Both sidecar and tsv are empty except for white space', + schemaVersion: '8.3.0', + sidecar: {}, + eventsString: '\n \n', + sidecarOnlyErrors: [], + eventsOnlyErrors: [], + comboErrors: [], + }, + ], + }, + { + name: 'valid-json-invalid-tsv', + description: 'JSON is valid but tsv is invalid', + tests: [ + { + testname: 'valid-sidecar-bad-tag-tsv', + explanation: 'Unrelated sidecar is valid but HED column tag is invalid', + schemaVersion: '8.3.0', + sidecar: { + event_code: { + HED: { + face: '(Red, Blue), (Green, (Yellow))', + }, + }, + }, + eventsString: 'onset\tduration\tHED\n' + '7\t4\tBaloney', + sidecarOnlyErrors: [], + eventsOnlyErrors: [ + BidsHedIssue.fromHedIssue( + generateIssue('invalidTag', { tag: 'Baloney' }), + { relativePath: 'valid-sidecar-bad-tag-tsv.tsv' }, + { tsvLine: 2 }, + ), + ], + comboErrors: [ + BidsHedIssue.fromHedIssue( + generateIssue('invalidTag', { tag: 'Baloney' }), + { path: 'valid-sidecar-bad-tag-tsv.tsv', relativePath: 'valid-sidecar-bad-tag-tsv.tsv' }, + { tsvLine: 2 }, + ), + ], + }, + { + testname: 'valid-sidecar-tsv-curly-brace', + explanation: 'The sidecar is valid, but tsv HED column has braces}', + schemaVersion: '8.3.0', + sidecar: { + event_code: { + HED: { + face: '(Red, Blue), (Green, (Yellow))', + }, + }, + }, + eventsString: 'onset\tduration\tevent_code\tHED\n' + '7\t4\tface\tRed,{blue}', + sidecarOnlyErrors: [], + eventsOnlyErrors: [ + BidsHedIssue.fromHedIssue( + generateIssue('curlyBracesInHedColumn', { column: '{blue}' }), + { relativePath: 'valid-sidecar-tsv-curly-brace.tsv' }, + { tsvLine: 2 }, + ), + ], + comboErrors: [ + BidsHedIssue.fromHedIssue( + generateIssue('curlyBracesInHedColumn', { column: '{blue}' }), + { path: 'valid-sidecar-tsv-curly-brace.tsv', relativePath: 'valid-sidecar-tsv-curly-brace.tsv' }, + { tsvLine: 2 }, + ), + ], + }, + ], + }, + { + name: 'duplicate-tag-tests', + description: 'Duplicate tags can appear in isolation or in combination', + tests: [ + { + testname: 'invalid-first-level-duplicate-json-tsv', + explanation: 'Each is okay but when combined, duplicate tag', + schemaVersion: '8.3.0', + sidecar: { + vehicle: { + HED: { + car: 'Car', + train: 'Train', + boat: 'Boat', + }, + }, + speed: { + HED: 'Speed/# mph', + }, + transport: { + HED: { + car: 'Car', + train: 'Train', + boat: 'Boat', + maglev: 'Vehicle', + }, + }, + }, + eventsString: 'onset\tduration\tvehicle\ttransport\tspeed\n' + '19\t6\tboat\tboat\t5\n', + sidecarOnlyErrors: [], + eventsOnlyErrors: [], + comboErrors: [ + BidsHedIssue.fromHedIssue( + generateIssue('duplicateTag', { tag: 'Boat' }), + { + path: 'invalid-first-level-duplicate-json-tsv.tsv', + relativePath: 'invalid-first-level-duplicate-json-tsv.tsv', + }, + { tsvLine: 2 }, + ), + BidsHedIssue.fromHedIssue( + generateIssue('duplicateTag', { tag: 'Boat' }), + { + path: 'invalid-first-level-duplicate-json-tsv.tsv', + relativePath: 'invalid-first-level-duplicate-json-tsv.tsv', + }, + { tsvLine: 2 }, + ), + ], + }, + { + testname: 'invalid-duplicate-groups-first-level-tsv', + explanation: 'The HED string has first level duplicate groups', + schemaVersion: '8.3.0', + sidecar: { + vehicle: { + HED: { + car: 'Car', + train: 'Train', + boat: 'Boat', + }, + }, + speed: { + HED: 'Speed/# mph', + }, + transport: { + HED: { + car: 'Car', + train: 'Train', + boat: 'Boat', + maglev: 'Vehicle', + }, + }, + }, + eventsString: 'onset\tduration\tvehicle\tHED\n' + '19\t6\tboat\t(Green, Blue),(Green, Blue)\n', + sidecarOnlyErrors: [], + eventsOnlyErrors: [ + BidsHedIssue.fromHedIssue( + generateIssue('duplicateTag', { tag: '(Green, Blue)' }), + { relativePath: 'invalid-duplicate-groups-first-level-tsv.tsv' }, + { tsvLine: 2 }, + ), + BidsHedIssue.fromHedIssue( + generateIssue('duplicateTag', { tag: '(Green, Blue)' }), + { relativePath: 'invalid-duplicate-groups-first-level-tsv.tsv' }, + { tsvLine: 2 }, + ), + ], + comboErrors: [ + BidsHedIssue.fromHedIssue( + generateIssue('duplicateTag', { tag: '(Green, Blue)' }), + { + path: 'invalid-duplicate-groups-first-level-tsv.tsv', + relativePath: 'invalid-duplicate-groups-first-level-tsv.tsv', + }, + { tsvLine: 2 }, + ), + BidsHedIssue.fromHedIssue( + generateIssue('duplicateTag', { tag: '(Green, Blue)' }), + { + path: 'invalid-duplicate-groups-first-level-tsv.tsv', + relativePath: 'invalid-duplicate-groups-first-level-tsv.tsv', + }, + { tsvLine: 2 }, + ), + ], + }, + ], + }, + { + name: 'curly-brace-tests', + description: 'Curly braces tested in various places', + tests: [ + { + testname: 'valid-curly-brace-in-sidecar-with-value-splice', + explanation: 'Valid curly brace in sidecar and valid value is spliced in', + schemaVersion: '8.3.0', + sidecar: { + event_code: { + HED: { + face: '(Red, Blue), (Green, (Yellow))', + ball: '{ball_type}, Black', + }, + }, + ball_type: { + Description: 'Has description with HED', + HED: 'Label/#', + }, + }, + eventsString: 'onset\tduration\tevent_code\tball_type\n' + '19\t6\tball\tbig-one\n', + sidecarOnlyErrors: [], + eventsOnlyErrors: [], + comboErrors: [], + }, + { + testname: 'valid-curly-brace-in-sidecar-with-category-splice', + explanation: 'Valid curly brace in sidecar and valid value is spliced in', + schemaVersion: '8.3.0', + sidecar: { + event_code: { + HED: { + face: '(Red, Blue), (Green, (Yellow))', + ball: '{ball_type}, Black', + }, + }, + ball_type: { + HED: { + beginner: 'Small', + advanced: 'Large', + }, + }, + }, + eventsString: 'onset\tduration\tevent_code\tball_type\n' + '19\t6\tball\tadvanced\n', + sidecarOnlyErrors: [], + eventsOnlyErrors: [], + comboErrors: [], + }, + { + testname: 'valid-curly-brace-in-sidecar-with-n/a-splice', + explanation: 'Valid curly brace in sidecar and but tsv splice entry is n/a', + schemaVersion: '8.3.0', + sidecar: { + event_code: { + HED: { + face: '(Red, Blue), (Green, (Yellow))', + ball: '{ball_type}, Black', + }, + }, + ball_type: { + Description: 'Has description with HED', + HED: 'Label/#', + }, + }, + eventsString: 'onset\tduration\tevent_code\tball_type\n' + '19\t6\tball\tn/a\n', + sidecarOnlyErrors: [], + eventsOnlyErrors: [], + comboErrors: [], + }, + { + testname: 'valid-HED-column-splice', + explanation: 'Valid curly brace in sidecar with valid HED column splice', + schemaVersion: '8.3.0', + sidecar: { + event_code: { + HED: { + face: '(Red, Blue), (Green, (Yellow))', + ball: 'Black, {HED}', + }, + }, + ball_type: { + Description: 'Has description with HED', + HED: 'Label/#', + }, + }, + eventsString: 'onset\tduration\tevent_code\tball_type\tHED\n' + '19\t6\tball\tn/a\tPurple\n', + sidecarOnlyErrors: [], + eventsOnlyErrors: [], + comboErrors: [], + }, + { + testname: 'valid-HED-column-splice-with-n/a', + explanation: 'Valid curly brace in sidecar with HED column entry n/a', + schemaVersion: '8.3.0', + sidecar: { + event_code: { + HED: { + ball: '{HED}', + }, + }, + }, + eventsString: 'onset\tduration\tevent_code\tball_type\tHED\n' + '19\t6\tball\tn/a\tn/a\n', + sidecarOnlyErrors: [], + eventsOnlyErrors: [], + comboErrors: [], + }, + { + testname: 'invalid-curly-brace-column-slice-has-no hed', + explanation: 'A column name is used in a splice but does not have HED', + schemaVersion: '8.3.0', + sidecar: { + event_code: { + HED: { + face: '(Red, Blue), (Green, (Yellow))', + ball: '{ball_type}, Black', + }, + }, + }, + eventsString: 'onset\tduration\tevent_code\tball_type\n' + '19\t6\tball\tn/a\tPurple\n', + sidecarOnlyErrors: [ + BidsHedIssue.fromHedIssue(generateIssue('undefinedCurlyBraces', { column: 'ball_type' }), { + path: 'invalid-curly-brace-column-slice-has-no hed.json', + relativePath: 'invalid-curly-brace-column-slice-has-no hed.json', + }), + ], + eventsOnlyErrors: [], + comboErrors: [ + BidsHedIssue.fromHedIssue(generateIssue('undefinedCurlyBraces', { column: 'ball_type' }), { + path: 'invalid-curly-brace-column-slice-has-no hed.tsv', + relativePath: 'invalid-curly-brace-column-slice-has-no hed.tsv', + }), + ], + }, + { + testname: 'invalid-HED-curly-brace-but-tsv-has-no-HED-column', + explanation: 'A {HED} column splice is used in a sidecar but the tsv has no HED column', + schemaVersion: '8.3.0', + sidecar: { + event_code: { + HED: { + face: '(Red, Blue), (Green, (Yellow))', + ball: '{HED}, Black', + }, + }, + }, + eventsString: 'onset\tduration\tevent_code\n' + '19\t6\tball\n', + sidecarOnlyErrors: [], + eventsOnlyErrors: [], + comboErrors: [ + BidsHedIssue.fromHedIssue( + generateIssue('undefinedCurlyBraces', { column: 'HED' }), + { + path: 'invalid-HED-curly-brace-but-tsv-has-no-HED-column.tsv', + relativePath: 'invalid-HED-curly-brace-but-tsv-has-no-HED-column.tsv', + }, + { tsvLine: 2 }, + ), + ], + }, + { + testname: 'invalid-curly-brace-in-HED-tsv-column', + explanation: 'Curly braces are used in the HED column of a tsv.', + schemaVersion: '8.3.0', + sidecar: { + event_code: { + HED: { + face: '(Red, Blue), (Green, (Yellow))', + ball: 'Black', + }, + }, + }, + eventsString: 'onset\tduration\tHED\n' + '19\t6\t{event_code}\n', + sidecarOnlyErrors: [], + eventsOnlyErrors: [ + BidsHedIssue.fromHedIssue( + generateIssue('curlyBracesInHedColumn', { column: '{event_code}' }), + { + relativePath: 'invalid-curly-brace-in-HED-tsv-column.tsv', + }, + { tsvLine: 2 }, + ), + ], + comboErrors: [ + BidsHedIssue.fromHedIssue( + generateIssue('curlyBracesInHedColumn', { column: '{event_code}' }), + { + path: 'invalid-curly-brace-in-HED-tsv-column.tsv', + relativePath: 'invalid-curly-brace-in-HED-tsv-column.tsv', + }, + { tsvLine: 2 }, + ), + ], + }, + { + testname: 'invalid-curly-brace-in-HED-tsv-column', + explanation: 'Curly braces are used in the HED column of a tsv.', + schemaVersion: '8.3.0', + sidecar: { + event_code: { + HED: { + face: '(Red, Blue), (Green, (Yellow))', + ball: 'Black', + }, + }, + }, + eventsString: 'onset\tduration\tHED\n' + '19\t6\t{event_code}\n', + sidecarOnlyErrors: [], + eventsOnlyErrors: [ + BidsHedIssue.fromHedIssue( + generateIssue('curlyBracesInHedColumn', { column: '{event_code}' }), + { + relativePath: 'invalid-curly-brace-in-HED-tsv-column.tsv', + }, + { tsvLine: 2 }, + ), + ], + comboErrors: [ + BidsHedIssue.fromHedIssue( + generateIssue('curlyBracesInHedColumn', { column: '{event_code}' }), + { + path: 'invalid-curly-brace-in-HED-tsv-column.tsv', + relativePath: 'invalid-curly-brace-in-HED-tsv-column.tsv', + }, + { tsvLine: 2 }, + ), + ], + }, + { + testname: 'invalid-recursive-curly-braces', + explanation: 'Mutually recursive curly braces in sidecar.', + schemaVersion: '8.3.0', + sidecar: { + event_code: { + HED: { + face: '(Red, Blue), (Green, (Yellow))', + ball: 'Black, {type}', + }, + }, + type: { + HED: { + familiar: '{event_code}', + }, + }, + }, + eventsString: 'onset\tduration\tevent_code\n' + '19\t6\tball\n', + sidecarOnlyErrors: [ + BidsHedIssue.fromHedIssue( + generateIssue('recursiveCurlyBracesWithKey', { column: 'type', referrer: 'event_code' }), + { + path: 'invalid-recursive-curly-braces.json', + relativePath: 'invalid-recursive-curly-braces.json', + }, + ), + BidsHedIssue.fromHedIssue( + generateIssue('recursiveCurlyBracesWithKey', { column: 'event_code', referrer: 'type' }), + { + path: 'invalid-recursive-curly-braces.json', + relativePath: 'invalid-recursive-curly-braces.json', + }, + ), + ], + eventsOnlyErrors: [], + comboErrors: [ + BidsHedIssue.fromHedIssue( + generateIssue('recursiveCurlyBracesWithKey', { column: 'type', referrer: 'event_code' }), + { + path: 'invalid-recursive-curly-braces.tsv', + relativePath: 'invalid-recursive-curly-braces.tsv', + }, + ), + BidsHedIssue.fromHedIssue( + generateIssue('recursiveCurlyBracesWithKey', { column: 'event_code', referrer: 'type' }), + { + path: 'invalid-recursive-curly-braces.tsv', + relativePath: 'invalid-recursive-curly-braces.tsv', + }, + ), + ], + }, + { + testname: 'invalid-self-recursive-curly-braces', + explanation: 'Mutually recursive curly braces in sidecar.', + schemaVersion: '8.3.0', + sidecar: { + event_code: { + HED: { + face: '(Red, Blue), (Green, (Yellow))', + ball: 'Black, {event_code}', + }, + }, + }, + eventsString: 'onset\tduration\tevent_code\n' + '19\t6\tball\n', + sidecarOnlyErrors: [ + BidsHedIssue.fromHedIssue( + generateIssue('recursiveCurlyBracesWithKey', { column: 'event_code', referrer: 'event_code' }), + { + path: 'invalid-self-recursive-curly-braces.json', + relativePath: 'invalid-self-recursive-curly-braces.json', + }, + ), + ], + eventsOnlyErrors: [], + comboErrors: [ + BidsHedIssue.fromHedIssue( + generateIssue('recursiveCurlyBracesWithKey', { column: 'event_code', referrer: 'event_code' }), + { + path: 'invalid-self-recursive-curly-braces.tsv', + relativePath: 'invalid-self-recursive-curly-braces.tsv', + }, + ), + ], + }, + { + testname: 'invalid-recursive-curly-brace-chain', + explanation: 'Curly braces column A -> column B -> Column C.', + schemaVersion: '8.3.0', + sidecar: { + event_code: { + HED: { + ball: 'Black, {ball_type}', + }, + }, + ball_type: { + HED: { + advanced: 'Large, {ball_size}', + }, + }, + ball_size: { + HED: 'Radius/# cm', + }, + }, + eventsString: 'onset\tduration\tevent_code\tball_type\tball_size\n' + '19\t6\tball\tadvanced\t10\n', + sidecarOnlyErrors: [ + BidsHedIssue.fromHedIssue( + generateIssue('recursiveCurlyBracesWithKey', { column: 'ball_type', referrer: 'event_code' }), + { + path: 'invalid-recursive-curly-brace-chain.json', + relativePath: 'invalid-recursive-curly-brace-chain.json', + }, + ), + ], + eventsOnlyErrors: [], + comboErrors: [ + BidsHedIssue.fromHedIssue( + generateIssue('recursiveCurlyBracesWithKey', { column: 'ball_type', referrer: 'event_code' }), + { + path: 'invalid-recursive-curly-brace-chain.tsv', + relativePath: 'invalid-recursive-curly-brace-chain.tsv', + }, + ), + ], + }, + ], + }, +] diff --git a/tests/eventTests.data.js b/tests/testData/eventTests.data.js similarity index 92% rename from tests/eventTests.data.js rename to tests/testData/eventTests.data.js index dac3352f..747596a5 100644 --- a/tests/eventTests.data.js +++ b/tests/testData/eventTests.data.js @@ -1,5 +1,5 @@ -import { BidsHedIssue } from '../bids' -import { generateIssue } from '../common/issues/issues' +import { BidsHedIssue } from '../../bids' +import { generateIssue } from '../../common/issues/issues' export const eventTestData = [ { diff --git a/tests/tagConverterTests.data.js b/tests/testData/tagConverterTests.data.js similarity index 69% rename from tests/tagConverterTests.data.js rename to tests/testData/tagConverterTests.data.js index f6a1e861..d90742a9 100644 --- a/tests/tagConverterTests.data.js +++ b/tests/testData/tagConverterTests.data.js @@ -1,7 +1,7 @@ -import { BidsHedIssue } from '../bids' -import { generateIssue } from '../common/issues/issues' -import { ColumnSpliceSpec, TagSpec } from '../parser/tokenizer' -import { SchemaTag } from '../validator/schema/types.js' +import { BidsHedIssue } from '../../bids' +import { generateIssue } from '../../common/issues/issues' +import { ColumnSpliceSpec, TagSpec } from '../../parser/tokenizer' +import { SchemaTag } from '../../validator/schema/types.js' export const tagConverterTestData = [ // Tests conversion of TagSpec to schema tag diff --git a/tests/tokenizerErrorData.js b/tests/testData/tokenizerErrorData.js similarity index 100% rename from tests/tokenizerErrorData.js rename to tests/testData/tokenizerErrorData.js diff --git a/tests/tokenizerPassingData.js b/tests/testData/tokenizerPassingData.js similarity index 99% rename from tests/tokenizerPassingData.js rename to tests/testData/tokenizerPassingData.js index 6577791b..df730da8 100644 --- a/tests/tokenizerPassingData.js +++ b/tests/testData/tokenizerPassingData.js @@ -1,5 +1,5 @@ //import { TagSpec, GroupSpec, ColumnSpliceSpec } from '../parser/tokenizerNew' -import { TagSpec, GroupSpec, ColumnSpliceSpec } from '../parser/tokenizer' +import { TagSpec, GroupSpec, ColumnSpliceSpec } from '../../parser/tokenizer' export const passingTests = [ { diff --git a/tests/tokenizerErrorTests.spec.js b/tests/tokenizerErrorTests.spec.js index ef70d635..6036a4d7 100644 --- a/tests/tokenizerErrorTests.spec.js +++ b/tests/tokenizerErrorTests.spec.js @@ -3,7 +3,7 @@ const assert = chai.assert import { beforeAll, describe, afterAll } from '@jest/globals' import path from 'path' import { HedStringTokenizer } from '../parser/tokenizer' -import { errorTests } from './tokenizerErrorData' +import { errorTests } from './testData/tokenizerErrorData' const displayLog = process.env.DISPLAY_LOG === 'true' const fs = require('fs') diff --git a/tests/tokenizerPassingTests.spec.js b/tests/tokenizerPassingTests.spec.js index 20de31e3..3e188135 100644 --- a/tests/tokenizerPassingTests.spec.js +++ b/tests/tokenizerPassingTests.spec.js @@ -3,7 +3,7 @@ const assert = chai.assert import { beforeAll, describe, afterAll } from '@jest/globals' import path from 'path' import { HedStringTokenizer } from '../parser/tokenizer' -import { passingTests } from './tokenizerPassingData' +import { passingTests } from './testData/tokenizerPassingData' const fs = require('fs') const displayLog = process.env.DISPLAY_LOG === 'true'