diff --git a/jest-setup.ts b/jest-setup.ts index b58164c..b9a2c19 100644 --- a/jest-setup.ts +++ b/jest-setup.ts @@ -1,2 +1,3 @@ import './test-utils/to-have-pattern'; import './test-utils/to-match-groups'; +import './test-utils/to-match-string'; diff --git a/src/__tests__/examples.ts b/src/__tests__/examples.ts index 02df4c0..fb48e11 100644 --- a/src/__tests__/examples.ts +++ b/src/__tests__/examples.ts @@ -36,14 +36,14 @@ test('example: IPv4 address validator', () => { expect(regex).toMatchGroups('255.255.255.255', ['255.255.255.255', '255', '255', '255', '255']); expect(regex).toMatchGroups('123.45.67.89', ['123.45.67.89', '123', '45', '67', '89']); - expect(regex.test('0.0.0.')).toBe(false); - expect(regex.test('0.0.0.0.')).toBe(false); - expect(regex.test('0.-1.0.0')).toBe(false); - expect(regex.test('0.1000.0.0')).toBe(false); - expect(regex.test('0.0.300.0')).toBe(false); - expect(regex.test('255.255.255.256')).toBe(false); + expect(regex).not.toMatchString('0.0.0.'); + expect(regex).not.toMatchString('0.0.0.0.'); + expect(regex).not.toMatchString('0.-1.0.0'); + expect(regex).not.toMatchString('0.1000.0.0'); + expect(regex).not.toMatchString('0.0.300.0'); + expect(regex).not.toMatchString('255.255.255.256'); - expect(regex.source).toEqual( - '^(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])$' + expect(regex).toHavePattern( + /^(\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])$/ ); }); diff --git a/src/components/__tests__/anchors.test.tsx b/src/components/__tests__/anchors.test.tsx index bfc7a8e..ca9db58 100644 --- a/src/components/__tests__/anchors.test.tsx +++ b/src/components/__tests__/anchors.test.tsx @@ -2,8 +2,8 @@ import { endOfString, startOfString } from '../anchors'; import { oneOrMore } from '../quantifiers'; test('`startOfString` basic cases', () => { - expect([startOfString]).toHavePattern('^'); - expect([startOfString, 'a', 'b']).toHavePattern('^ab'); + expect(startOfString).toHavePattern(/^/); + expect([startOfString, 'a', 'b']).toHavePattern(/^ab/); }); test('`startOfString` regex tests', () => { @@ -11,8 +11,8 @@ test('`startOfString` regex tests', () => { }); test('`endOfString` basic cases', () => { - expect([endOfString]).toHavePattern('$'); - expect(['a', 'b', endOfString]).toHavePattern('ab$'); + expect(endOfString).toHavePattern(/$/); + expect(['a', 'b', endOfString]).toHavePattern(/ab$/); }); test('`endOfString` regex tests', () => { diff --git a/src/components/__tests__/capture.test.tsx b/src/components/__tests__/capture.test.tsx index 2777819..ae4d200 100644 --- a/src/components/__tests__/capture.test.tsx +++ b/src/components/__tests__/capture.test.tsx @@ -2,10 +2,10 @@ import { capture } from '../capture'; import { oneOrMore } from '../quantifiers'; test('`capture` base cases', () => { - expect(capture('a')).toHavePattern('(a)'); - expect(capture('abc')).toHavePattern('(abc)'); - expect(capture(oneOrMore('abc'))).toHavePattern('((?:abc)+)'); - expect(oneOrMore(capture('abc'))).toHavePattern('(abc)+'); + expect(capture('a')).toHavePattern(/(a)/); + expect(capture('abc')).toHavePattern(/(abc)/); + expect(capture(oneOrMore('abc'))).toHavePattern(/((?:abc)+)/); + expect(oneOrMore(capture('abc'))).toHavePattern(/(abc)+/); }); test('`capture` captures group', () => { diff --git a/src/components/__tests__/character-class.test.ts b/src/components/__tests__/character-class.test.ts index c35f360..95a4f83 100644 --- a/src/components/__tests__/character-class.test.ts +++ b/src/components/__tests__/character-class.test.ts @@ -12,37 +12,37 @@ import { import { buildRegex } from '../../builders'; test('`any` character class', () => { - expect(any).toHavePattern('.'); - expect(['x', any]).toHavePattern('x.'); - expect(['x', any, 'x']).toHavePattern('x.x'); + expect(any).toHavePattern(/./); + expect(['x', any]).toHavePattern(/x./); + expect(['x', any, 'x']).toHavePattern(/x.x/); }); test('`digit` character class', () => { - expect(digit).toHavePattern('\\d'); - expect(['x', digit]).toHavePattern('x\\d'); - expect(['x', digit, 'x']).toHavePattern('x\\dx'); + expect(digit).toHavePattern(/\d/); + expect(['x', digit]).toHavePattern(/x\d/); + expect(['x', digit, 'x']).toHavePattern(/x\dx/); }); test('`word` character class', () => { - expect(word).toHavePattern('\\w'); - expect(['x', word]).toHavePattern('x\\w'); - expect(['x', word, 'x']).toHavePattern('x\\wx'); + expect(word).toHavePattern(/\w/); + expect(['x', word]).toHavePattern(/x\w/); + expect(['x', word, 'x']).toHavePattern(/x\wx/); }); test('`whitespace` character class', () => { - expect(whitespace).toHavePattern('\\s'); - expect(['x', whitespace]).toHavePattern('x\\s'); - expect(['x', whitespace, 'x']).toHavePattern('x\\sx'); + expect(whitespace).toHavePattern(/\s/); + expect(['x', whitespace]).toHavePattern(/x\s/); + expect(['x', whitespace, 'x']).toHavePattern(/x\sx/); }); test('`characterClass` base cases', () => { - expect(characterClass(characterRange('a', 'z'))).toHavePattern('[a-z]'); + expect(characterClass(characterRange('a', 'z'))).toHavePattern(/[a-z]/); expect(characterClass(characterRange('a', 'z'), characterRange('A', 'Z'))).toHavePattern( - '[a-zA-Z]' + /[a-zA-Z]/ ); - expect(characterClass(characterRange('a', 'z'), anyOf('05'))).toHavePattern('[a-z05]'); + expect(characterClass(characterRange('a', 'z'), anyOf('05'))).toHavePattern(/[a-z05]/); expect(characterClass(characterRange('a', 'z'), whitespace, anyOf('05'))).toHavePattern( - '[a-z\\s05]' + /[a-z\s05]/ ); }); @@ -53,9 +53,9 @@ test('`characterClass` throws on inverted arguments', () => { }); test('`characterRange` base cases', () => { - expect(characterRange('a', 'z')).toHavePattern('[a-z]'); - expect(['x', characterRange('0', '9')]).toHavePattern('x[0-9]'); - expect([characterRange('A', 'F'), 'x']).toHavePattern('[A-F]x'); + expect(characterRange('a', 'z')).toHavePattern(/[a-z]/); + expect(['x', characterRange('0', '9')]).toHavePattern(/x[0-9]/); + expect([characterRange('A', 'F'), 'x']).toHavePattern(/[A-F]x/); }); test('`characterRange` throws on incorrect arguments', () => { @@ -71,25 +71,25 @@ test('`characterRange` throws on incorrect arguments', () => { }); test('`anyOf` base cases', () => { - expect(anyOf('a')).toHavePattern('a'); - expect(['x', anyOf('a'), 'x']).toHavePattern('xax'); - expect(anyOf('ab')).toHavePattern('[ab]'); - expect(['x', anyOf('ab')]).toHavePattern('x[ab]'); - expect(['x', anyOf('ab'), 'x']).toHavePattern('x[ab]x'); + expect(anyOf('a')).toHavePattern(/a/); + expect(['x', anyOf('a'), 'x']).toHavePattern(/xax/); + expect(anyOf('ab')).toHavePattern(/[ab]/); + expect(['x', anyOf('ab')]).toHavePattern(/x[ab]/); + expect(['x', anyOf('ab'), 'x']).toHavePattern(/x[ab]x/); }); test('`anyOf` with quantifiers', () => { - expect(['x', oneOrMore(anyOf('abc')), 'x']).toHavePattern('x[abc]+x'); - expect(['x', optionally(anyOf('abc')), 'x']).toHavePattern('x[abc]?x'); - expect(['x', zeroOrMore(anyOf('abc')), 'x']).toHavePattern('x[abc]*x'); + expect(['x', oneOrMore(anyOf('abc')), 'x']).toHavePattern(/x[abc]+x/); + expect(['x', optionally(anyOf('abc')), 'x']).toHavePattern(/x[abc]?x/); + expect(['x', zeroOrMore(anyOf('abc')), 'x']).toHavePattern(/x[abc]*x/); }); test('`anyOf` escapes special characters', () => { - expect(anyOf('abc-+.]\\')).toHavePattern('[abc+.\\]\\\\-]'); + expect(anyOf('abc-+.]\\')).toHavePattern(/[abc+.\]\\-]/); }); test('`anyOf` moves hyphen to the last position', () => { - expect(anyOf('a-bc')).toHavePattern('[abc-]'); + expect(anyOf('a-bc')).toHavePattern(/[abc-]/); }); test('`anyOf` throws on empty text', () => { @@ -99,17 +99,17 @@ test('`anyOf` throws on empty text', () => { }); test('`inverted` character class', () => { - expect(inverted(anyOf('a'))).toHavePattern('[^a]'); - expect(inverted(anyOf('abc'))).toHavePattern('[^abc]'); + expect(inverted(anyOf('a'))).toHavePattern(/[^a]/); + expect(inverted(anyOf('abc'))).toHavePattern(/[^abc]/); }); test('`inverted` character class double inversion', () => { - expect(inverted(inverted(anyOf('a')))).toHavePattern('a'); - expect(inverted(inverted(anyOf('abc')))).toHavePattern('[abc]'); + expect(inverted(inverted(anyOf('a')))).toHavePattern(/a/); + expect(inverted(inverted(anyOf('abc')))).toHavePattern(/[abc]/); }); test('`inverted` character class execution', () => { - expect(inverted(anyOf('a'))).toMatchGroups('aa', []); + expect(inverted(anyOf('a'))).not.toMatchString('aa'); expect(inverted(anyOf('a'))).toMatchGroups('aba', ['b']); }); diff --git a/src/components/__tests__/choice-of.test.ts b/src/components/__tests__/choice-of.test.ts index 2847141..9ce9324 100644 --- a/src/components/__tests__/choice-of.test.ts +++ b/src/components/__tests__/choice-of.test.ts @@ -3,34 +3,34 @@ import { repeat } from '../repeat'; import { choiceOf } from '../choice-of'; test('`choiceOf` using basic strings', () => { - expect(choiceOf('a')).toHavePattern('a'); - expect(choiceOf('a', 'b')).toHavePattern('a|b'); - expect(choiceOf('a', 'b', 'c')).toHavePattern('a|b|c'); - expect(choiceOf('aaa', 'bbb')).toHavePattern('aaa|bbb'); + expect(choiceOf('a')).toHavePattern(/a/); + expect(choiceOf('a', 'b')).toHavePattern(/a|b/); + expect(choiceOf('a', 'b', 'c')).toHavePattern(/a|b|c/); + expect(choiceOf('aaa', 'bbb')).toHavePattern(/aaa|bbb/); }); test('`choiceOf` used in sequence', () => { - expect(['x', choiceOf('a'), 'x']).toHavePattern('xax'); - expect([choiceOf('a', 'b'), 'x']).toHavePattern('(?:a|b)x'); - expect(['x', choiceOf('a', 'b')]).toHavePattern('x(?:a|b)'); + expect(['x', choiceOf('a'), 'x']).toHavePattern(/xax/); + expect([choiceOf('a', 'b'), 'x']).toHavePattern(/(?:a|b)x/); + expect(['x', choiceOf('a', 'b')]).toHavePattern(/x(?:a|b)/); - expect(choiceOf('a', 'b', 'c')).toHavePattern('a|b|c'); - expect(['x', choiceOf('a', 'b', 'c')]).toHavePattern('x(?:a|b|c)'); - expect([choiceOf('a', 'b', 'c'), 'x']).toHavePattern('(?:a|b|c)x'); + expect(choiceOf('a', 'b', 'c')).toHavePattern(/a|b|c/); + expect(['x', choiceOf('a', 'b', 'c')]).toHavePattern(/x(?:a|b|c)/); + expect([choiceOf('a', 'b', 'c'), 'x']).toHavePattern(/(?:a|b|c)x/); - expect(choiceOf('aaa', 'bbb')).toHavePattern('aaa|bbb'); + expect(choiceOf('aaa', 'bbb')).toHavePattern(/aaa|bbb/); }); test('`choiceOf` with sequence options', () => { - expect([choiceOf(['a', 'b'])]).toHavePattern('ab'); - expect([choiceOf(['a', 'b'], ['c', 'd'])]).toHavePattern('ab|cd'); - expect([choiceOf(['a', zeroOrMore('b')], [oneOrMore('c'), 'd'])]).toHavePattern('ab*|c+d'); + expect([choiceOf(['a', 'b'])]).toHavePattern(/ab/); + expect([choiceOf(['a', 'b'], ['c', 'd'])]).toHavePattern(/ab|cd/); + expect([choiceOf(['a', zeroOrMore('b')], [oneOrMore('c'), 'd'])]).toHavePattern(/ab*|c+d/); }); test('`choiceOf` using nested regex', () => { - expect(choiceOf(oneOrMore('a'), zeroOrMore('b'))).toHavePattern('a+|b*'); + expect(choiceOf(oneOrMore('a'), zeroOrMore('b'))).toHavePattern(/a+|b*/); expect(choiceOf(repeat({ min: 1, max: 3 }, 'a'), repeat({ count: 5 }, 'bx'))).toHavePattern( - 'a{1,3}|(?:bx){5}' + /a{1,3}|(?:bx){5}/ ); }); diff --git a/src/components/__tests__/quantifiers.test.tsx b/src/components/__tests__/quantifiers.test.tsx index 852cccb..22a2584 100644 --- a/src/components/__tests__/quantifiers.test.tsx +++ b/src/components/__tests__/quantifiers.test.tsx @@ -1,46 +1,39 @@ -import { buildRegex } from '../../builders'; import { digit } from '../character-class'; import { oneOrMore, optionally, zeroOrMore } from '../quantifiers'; test('`oneOrMore` quantifier', () => { - expect(oneOrMore('a')).toHavePattern('a+'); - expect(oneOrMore('ab')).toHavePattern('(?:ab)+'); + expect(oneOrMore('a')).toHavePattern(/a+/); + expect(oneOrMore('ab')).toHavePattern(/(?:ab)+/); }); test('`optionally` quantifier', () => { - expect(optionally('a')).toHavePattern('a?'); - expect(optionally('ab')).toHavePattern('(?:ab)?'); + expect(optionally('a')).toHavePattern(/a?/); + expect(optionally('ab')).toHavePattern(/(?:ab)?/); }); test('`zeroOrMore` quantifier', () => { - expect(zeroOrMore('a')).toHavePattern('a*'); - expect(zeroOrMore('ab')).toHavePattern('(?:ab)*'); + expect(zeroOrMore('a')).toHavePattern(/a*/); + expect(zeroOrMore('ab')).toHavePattern(/(?:ab)*/); }); test('`oneOrMore` does not generate capture when grouping', () => { - const regex = buildRegex(oneOrMore('aa')); - const groups = [...'aa'.match(regex)!]; - expect(groups).toEqual(['aa']); + expect(oneOrMore('aa')).toMatchGroups('aa', ['aa']); }); test('`optionally` does not generate capture when grouping', () => { - const regex = buildRegex(optionally('aa')); - const groups = [...'aa'.match(regex)!]; - expect(groups).toEqual(['aa']); + expect(optionally('aa')).toMatchGroups('aa', ['aa']); }); test('`zeroOrMore` does not generate capture when grouping', () => { - const regex = buildRegex(zeroOrMore('aa')); - const groups = [...'aa'.match(regex)!]; - expect(groups).toEqual(['aa']); + expect(zeroOrMore('aa')).toMatchGroups('aa', ['aa']); }); test('base quantifiers optimize grouping for atoms', () => { - expect(oneOrMore(digit)).toHavePattern('\\d+'); - expect(optionally(digit)).toHavePattern('\\d?'); - expect(zeroOrMore(digit)).toHavePattern('\\d*'); + expect(oneOrMore(digit)).toHavePattern(/\d+/); + expect(optionally(digit)).toHavePattern(/\d?/); + expect(zeroOrMore(digit)).toHavePattern(/\d*/); - expect(oneOrMore('a')).toHavePattern('a+'); - expect(optionally('a')).toHavePattern('a?'); - expect(zeroOrMore('a')).toHavePattern('a*'); + expect(oneOrMore('a')).toHavePattern(/a+/); + expect(optionally('a')).toHavePattern(/a?/); + expect(zeroOrMore('a')).toHavePattern(/a*/); }); diff --git a/src/components/__tests__/repeat.test.tsx b/src/components/__tests__/repeat.test.tsx index e524b28..7941b82 100644 --- a/src/components/__tests__/repeat.test.tsx +++ b/src/components/__tests__/repeat.test.tsx @@ -3,18 +3,18 @@ import { oneOrMore, zeroOrMore } from '../quantifiers'; import { repeat } from '../repeat'; test('`repeat` quantifier', () => { - expect(['a', repeat({ min: 1, max: 5 }, 'b')]).toHavePattern('ab{1,5}'); - expect(['a', repeat({ min: 1 }, 'b')]).toHavePattern('ab{1,}'); - expect(['a', repeat({ count: 1 }, 'b')]).toHavePattern('ab{1}'); + expect(['a', repeat({ min: 1, max: 5 }, 'b')]).toHavePattern(/ab{1,5}/); + expect(['a', repeat({ min: 1 }, 'b')]).toHavePattern(/ab{1,}/); + expect(['a', repeat({ count: 1 }, 'b')]).toHavePattern(/ab{1}/); - expect(['a', repeat({ count: 1 }, ['a', zeroOrMore('b')])]).toHavePattern('a(?:ab*){1}'); - expect(repeat({ count: 5 }, ['text', ' ', oneOrMore('d')])).toHavePattern('(?:text d+){5}'); + expect(['a', repeat({ count: 1 }, ['a', zeroOrMore('b')])]).toHavePattern(/a(?:ab*){1}/); + expect(repeat({ count: 5 }, ['text', ' ', oneOrMore('d')])).toHavePattern(/(?:text d+){5}/); }); test('`repeat` optimizes grouping for atoms', () => { - expect(repeat({ count: 2 }, digit)).toHavePattern('\\d{2}'); - expect(repeat({ min: 2 }, digit)).toHavePattern('\\d{2,}'); - expect(repeat({ min: 1, max: 5 }, digit)).toHavePattern('\\d{1,5}'); + expect(repeat({ count: 2 }, digit)).toHavePattern(/\d{2}/); + expect(repeat({ min: 2 }, digit)).toHavePattern(/\d{2,}/); + expect(repeat({ min: 1, max: 5 }, digit)).toHavePattern(/\d{1,5}/); }); test('`repeat` throws on no children', () => { diff --git a/src/encoder/__tests__/encoder.test.tsx b/src/encoder/__tests__/encoder.test.tsx index a71a28c..0418e01 100644 --- a/src/encoder/__tests__/encoder.test.tsx +++ b/src/encoder/__tests__/encoder.test.tsx @@ -3,49 +3,44 @@ import { oneOrMore, optionally, zeroOrMore } from '../../components/quantifiers' import { repeat } from '../../components/repeat'; test('basic quantifies', () => { - expect('a').toHavePattern('a'); - expect(['a', 'b']).toHavePattern('ab'); + expect('a').toHavePattern(/a/); + expect(['a', 'b']).toHavePattern(/ab/); - expect(oneOrMore('a')).toHavePattern('a+'); - expect(optionally('a')).toHavePattern('a?'); + expect(oneOrMore('a')).toHavePattern(/a+/); + expect(optionally('a')).toHavePattern(/a?/); - expect(['a', oneOrMore('b')]).toHavePattern('ab+'); - expect(['a', oneOrMore('bc')]).toHavePattern('a(?:bc)+'); - expect(['a', oneOrMore('bc')]).toHavePattern('a(?:bc)+'); + expect(['a', oneOrMore('b')]).toHavePattern(/ab+/); + expect(['a', oneOrMore('bc')]).toHavePattern(/a(?:bc)+/); + expect(['a', oneOrMore('bc')]).toHavePattern(/a(?:bc)+/); - expect(['a', repeat({ min: 1, max: 5 }, 'b')]).toHavePattern('ab{1,5}'); + expect(['a', repeat({ min: 1, max: 5 }, 'b')]).toHavePattern(/ab{1,5}/); - expect(['a', zeroOrMore('b')]).toHavePattern('ab*'); - expect(['a', zeroOrMore('bc')]).toHavePattern('a(?:bc)*'); - expect(['a', zeroOrMore('bc')]).toHavePattern('a(?:bc)*'); + expect(['a', zeroOrMore('b')]).toHavePattern(/ab*/); + expect(['a', zeroOrMore('bc')]).toHavePattern(/a(?:bc)*/); + expect(['a', zeroOrMore('bc')]).toHavePattern(/a(?:bc)*/); - expect([optionally('a'), 'b']).toHavePattern('a?b'); + expect([optionally('a'), 'b']).toHavePattern(/a?b/); - expect([optionally('a'), 'b', oneOrMore('d')]).toHavePattern('a?bd+'); -}); - -test('regex constructor', () => { - expect(buildRegex('a').test('a')).toBeTruthy(); - expect(buildRegex('a').test('b')).toBeFalsy(); + expect([optionally('a'), 'b', oneOrMore('d')]).toHavePattern(/a?bd+/); }); test('`buildPattern` escapes special characters', () => { - expect('.').toHavePattern('\\.'); - expect('*').toHavePattern('\\*'); - expect('+').toHavePattern('\\+'); - expect('?').toHavePattern('\\?'); - expect('^').toHavePattern('\\^'); - expect('$').toHavePattern('\\$'); - expect('{').toHavePattern('\\{'); - expect('}').toHavePattern('\\}'); - expect('|').toHavePattern('\\|'); - expect('[').toHavePattern('\\['); - expect(']').toHavePattern('\\]'); - expect('\\').toHavePattern('\\\\'); - - expect('*.*').toHavePattern('\\*\\.\\*'); - - expect([oneOrMore('.*'), zeroOrMore('[]{}')]).toHavePattern('(?:\\.\\*)+(?:\\[\\]\\{\\})*'); + expect('.').toHavePattern(/\./); + expect('*').toHavePattern(/\*/); + expect('+').toHavePattern(/\+/); + expect('?').toHavePattern(/\?/); + expect('^').toHavePattern(/\^/); + expect('$').toHavePattern(/\$/); + expect('{').toHavePattern(/\{/); + expect('}').toHavePattern(/\}/); + expect('|').toHavePattern(/\|/); + expect('[').toHavePattern(/\[/); + expect(']').toHavePattern(/\]/); + expect('\\').toHavePattern(/\\/); + + expect('*.*').toHavePattern(/\*\.\*/); + + expect([oneOrMore('.*'), zeroOrMore('[]{}')]).toHavePattern(/(?:\.\*)+(?:\[\]\{\})*/); }); test('`buildRegex` throws error on unknown element', () => { diff --git a/test-utils/to-have-pattern.ts b/test-utils/to-have-pattern.ts index b3b4652..8157113 100644 --- a/test-utils/to-have-pattern.ts +++ b/test-utils/to-have-pattern.ts @@ -1,33 +1,25 @@ -import { buildPattern } from '../src/builders'; import type { RegexNode } from '../src/types'; -import { asNodeArray } from '../src/utils/nodes'; -import { isRegexNode } from './utils'; +import { asRegExp } from './utils'; export function toHavePattern( this: jest.MatcherContext, - nodes: RegexNode | RegexNode[], - expected: string + received: RegExp | RegexNode | RegexNode[], + expected: RegExp ) { - nodes = asNodeArray(nodes); + const receivedPattern = asRegExp(received).source; + const expectedPattern = expected.source; - nodes.forEach((e) => { - if (!isRegexNode(e)) { - throw new Error(`\`toHavePattern()\` received an array of RegexElements and strings.`); - } - }); - - const received = buildPattern(nodes); const options = { isNot: this.isNot, }; return { - pass: expected === received, + pass: expectedPattern === receivedPattern, message: () => this.utils.matcherHint('toHavePattern', undefined, undefined, options) + '\n\n' + - `Expected: ${this.isNot ? 'not ' : ''}${this.utils.printExpected(expected)}\n` + - `Received: ${this.utils.printReceived(received)}`, + `Expected: ${this.isNot ? 'not ' : ''}${this.utils.printExpected(expectedPattern)}\n` + + `Received: ${this.utils.printReceived(receivedPattern)}`, }; } @@ -37,7 +29,7 @@ declare global { namespace jest { // eslint-disable-next-line @typescript-eslint/no-unused-vars interface Matchers { - toHavePattern(expected: string): R; + toHavePattern(expected: RegExp): R; } } } diff --git a/test-utils/to-match-groups.ts b/test-utils/to-match-groups.ts index 8d912d7..5a5f271 100644 --- a/test-utils/to-match-groups.ts +++ b/test-utils/to-match-groups.ts @@ -1,42 +1,26 @@ -import { buildRegex } from '../src/builders'; import type { RegexNode } from '../src/types'; -import { asNodeArray } from '../src/utils/nodes'; -import { isRegexNode } from './utils'; +import { asRegExp } from './utils'; export function toMatchGroups( this: jest.MatcherContext, received: RegExp | RegexNode | RegexNode[], - input: string, - expected: string[] + expectedString: string, + expectedGroups: string[] ) { - let regex; - if (received instanceof RegExp) { - regex = received; - } else { - const nodes = asNodeArray(received); - nodes.forEach((e) => { - if (!isRegexNode(e)) { - throw new Error(`\`toMatchGroups()\` received an array of RegexElements and strings.`); - } - }); - - regex = buildRegex(nodes); - } - + const receivedRegex = asRegExp(received); + const matchResult = expectedString.match(receivedRegex); + const receivedGroups = matchResult ? [...matchResult] : null; const options = { isNot: this.isNot, }; - const execResult = regex.exec(input); - const actual = execResult ? [...execResult] : []; - return { - pass: this.equals(actual, expected), + pass: this.equals(receivedGroups, expectedGroups), message: () => this.utils.matcherHint('toMatchGroups', undefined, undefined, options) + '\n\n' + - `Expected: ${this.isNot ? 'not ' : ''}${this.utils.printExpected(expected)}\n` + - `Received: ${this.utils.printReceived(actual)}`, + `Expected: ${this.isNot ? 'not ' : ''}${this.utils.printExpected(expectedGroups)}\n` + + `Received: ${this.utils.printReceived(receivedGroups)}`, }; } diff --git a/test-utils/to-match-string.ts b/test-utils/to-match-string.ts new file mode 100644 index 0000000..5a87d03 --- /dev/null +++ b/test-utils/to-match-string.ts @@ -0,0 +1,34 @@ +import type { RegexNode } from '../src/types'; +import { asRegExp } from './utils'; + +export function toMatchString( + this: jest.MatcherContext, + received: RegExp | RegexNode | RegexNode[], + expected: string +) { + const receivedRegex = asRegExp(received); + const matchResult = expected.match(receivedRegex); + const options = { + isNot: this.isNot, + }; + + return { + pass: matchResult !== null, + message: () => + this.utils.matcherHint('toMatchGroups', undefined, undefined, options) + + '\n\n' + + `Expected string: ${this.isNot ? 'not ' : ''}${this.utils.printExpected(expected)}\n` + + `Received pattern: ${this.utils.printReceived(receivedRegex.source)}`, + }; +} + +expect.extend({ toMatchString }); + +declare global { + namespace jest { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + interface Matchers { + toMatchString(expected: string): R; + } + } +} diff --git a/test-utils/utils.ts b/test-utils/utils.ts index 66d48d7..b97cb0e 100644 --- a/test-utils/utils.ts +++ b/test-utils/utils.ts @@ -1,3 +1,4 @@ +import { buildRegex } from '../src/builders'; import type { RegexElement, RegexNode } from '../src/types'; export function isRegexNode(node: unknown): node is RegexNode { @@ -12,3 +13,11 @@ export function isRegexElement(element: unknown): element is RegexElement { typeof element.encode === 'function' ); } + +export function asRegExp(regex: RegExp | RegexNode | RegexNode[]) { + if (regex instanceof RegExp) { + return regex; + } + + return buildRegex(regex); +}