From 3fb4bba5c5a37406ee55ad427422e307f433d314 Mon Sep 17 00:00:00 2001 From: Eduardo San Martin Morote Date: Tue, 7 Apr 2020 13:57:21 +0200 Subject: [PATCH] test: refactor tests --- __tests__/matcher/addingRemoving.spec.ts | 2 +- __tests__/matcher/resolve.spec.ts | 1920 +++++++++++----------- 2 files changed, 959 insertions(+), 963 deletions(-) diff --git a/__tests__/matcher/addingRemoving.spec.ts b/__tests__/matcher/addingRemoving.spec.ts index 644b9014..40ec9f10 100644 --- a/__tests__/matcher/addingRemoving.spec.ts +++ b/__tests__/matcher/addingRemoving.spec.ts @@ -5,7 +5,7 @@ const currentLocation = { path: '/' } as MatcherLocation // @ts-ignore const component: RouteComponent = null -describe('normalizeRouteRecord', () => { +describe('Matcher: adding and removing records', () => { it('can add records', () => { const matcher = createRouterMatcher([], {}) matcher.addRoute({ path: '/', component, name: 'home' }) diff --git a/__tests__/matcher/resolve.spec.ts b/__tests__/matcher/resolve.spec.ts index fec63e26..3901845a 100644 --- a/__tests__/matcher/resolve.spec.ts +++ b/__tests__/matcher/resolve.spec.ts @@ -14,409 +14,290 @@ const component: RouteComponent = null // for normalized records const components = { default: component } -describe('Router Matcher', () => { - describe('resolve', () => { - function assertRecordMatch( - record: RouteRecordRaw | RouteRecordRaw[], - location: MatcherLocationRaw, - resolved: Partial, - start: MatcherLocation = START_LOCATION_NORMALIZED - ) { - record = Array.isArray(record) ? record : [record] - const matcher = createRouterMatcher(record, {}) - - if (!('meta' in resolved)) { - resolved.meta = record[0].meta || {} - } - - if (!('name' in resolved)) { - resolved.name = undefined - } - - // add location if provided as it should be the same value - if ('path' in location && !('path' in resolved)) { - resolved.path = location.path - } +describe('RouterMatcher.resolve', () => { + function assertRecordMatch( + record: RouteRecordRaw | RouteRecordRaw[], + location: MatcherLocationRaw, + resolved: Partial, + start: MatcherLocation = START_LOCATION_NORMALIZED + ) { + record = Array.isArray(record) ? record : [record] + const matcher = createRouterMatcher(record, {}) + + if (!('meta' in resolved)) { + resolved.meta = record[0].meta || {} + } - if ('redirect' in record) { - throw new Error('not handled') - } else { - // use one single record - if (!resolved.matched) - // @ts-ignore - resolved.matched = record.map(normalizeRouteRecord) - // allow passing an expect.any(Array) - else if (Array.isArray(resolved.matched)) - resolved.matched = resolved.matched.map(m => ({ - ...normalizeRouteRecord(m as any), - aliasOf: m.aliasOf, - })) - } + if (!('name' in resolved)) { + resolved.name = undefined + } - // allows not passing params - if ('params' in location) { - resolved.params = resolved.params || location.params - } else { - resolved.params = resolved.params || {} - } + // add location if provided as it should be the same value + if ('path' in location && !('path' in resolved)) { + resolved.path = location.path + } - const startCopy: MatcherLocation = { - ...start, - matched: start.matched.map(m => ({ - ...normalizeRouteRecord(m), + if ('redirect' in record) { + throw new Error('not handled') + } else { + // use one single record + if (!resolved.matched) + // @ts-ignore + resolved.matched = record.map(normalizeRouteRecord) + // allow passing an expect.any(Array) + else if (Array.isArray(resolved.matched)) + resolved.matched = resolved.matched.map(m => ({ + ...normalizeRouteRecord(m as any), aliasOf: m.aliasOf, - })) as MatcherLocation['matched'], - } - - // make matched non enumerable - Object.defineProperty(startCopy, 'matched', { enumerable: false }) + })) + } - const result = matcher.resolve(location, startCopy) - expect(result).toEqual(resolved) + // allows not passing params + if ('params' in location) { + resolved.params = resolved.params || location.params + } else { + resolved.params = resolved.params || {} } - /** - * - * @param record Record or records we are testing the matcher against - * @param location location we want to reolve against - * @param [start] Optional currentLocation used when resolving - * @returns error - */ - function assertErrorMatch( - record: RouteRecordRaw | RouteRecordRaw[], - location: MatcherLocationRaw, - start: MatcherLocation = START_LOCATION_NORMALIZED - ): any { - try { - assertRecordMatch(record, location, {}, start) - } catch (error) { - return error - } - throw new Error('Expected Error to be thrown') + const startCopy: MatcherLocation = { + ...start, + matched: start.matched.map(m => ({ + ...normalizeRouteRecord(m), + aliasOf: m.aliasOf, + })) as MatcherLocation['matched'], } - describe('alias', () => { - it('resolves an alias', () => { - assertRecordMatch( - { - path: '/', - alias: '/home', - name: 'Home', - components, - meta: { foo: true }, - }, - { path: '/home' }, - { - name: 'Home', - path: '/home', - params: {}, - meta: { foo: true }, - matched: [ - { - path: '/home', - name: 'Home', - components, - aliasOf: expect.objectContaining({ name: 'Home', path: '/' }), - meta: { foo: true }, - }, - ], - } - ) - }) + // make matched non enumerable + Object.defineProperty(startCopy, 'matched', { enumerable: false }) + + const result = matcher.resolve(location, startCopy) + expect(result).toEqual(resolved) + } + + /** + * + * @param record Record or records we are testing the matcher against + * @param location location we want to reolve against + * @param [start] Optional currentLocation used when resolving + * @returns error + */ + function assertErrorMatch( + record: RouteRecordRaw | RouteRecordRaw[], + location: MatcherLocationRaw, + start: MatcherLocation = START_LOCATION_NORMALIZED + ): any { + try { + assertRecordMatch(record, location, {}, start) + } catch (error) { + return error + } + throw new Error('Expected Error to be thrown') + } - it('multiple aliases', () => { - const record = { + describe('alias', () => { + it('resolves an alias', () => { + assertRecordMatch( + { path: '/', - alias: ['/home', '/start'], + alias: '/home', name: 'Home', components, meta: { foo: true }, + }, + { path: '/home' }, + { + name: 'Home', + path: '/home', + params: {}, + meta: { foo: true }, + matched: [ + { + path: '/home', + name: 'Home', + components, + aliasOf: expect.objectContaining({ name: 'Home', path: '/' }), + meta: { foo: true }, + }, + ], } + ) + }) - assertRecordMatch( - record, - { path: '/' }, - { - name: 'Home', - path: '/', - params: {}, - meta: { foo: true }, - matched: [ - { - path: '/', - name: 'Home', - components, - aliasOf: undefined, - meta: { foo: true }, - }, - ], - } - ) - assertRecordMatch( - record, - { path: '/home' }, - { - name: 'Home', - path: '/home', - params: {}, - meta: { foo: true }, - matched: [ - { - path: '/home', - name: 'Home', - components, - aliasOf: expect.objectContaining({ name: 'Home', path: '/' }), - meta: { foo: true }, - }, - ], - } - ) - assertRecordMatch( - record, - { path: '/start' }, - { - name: 'Home', - path: '/start', - params: {}, - meta: { foo: true }, - matched: [ - { - path: '/start', - name: 'Home', - components, - aliasOf: expect.objectContaining({ name: 'Home', path: '/' }), - meta: { foo: true }, - }, - ], - } - ) - }) + it('multiple aliases', () => { + const record = { + path: '/', + alias: ['/home', '/start'], + name: 'Home', + components, + meta: { foo: true }, + } - it('resolves the original record by name', () => { - assertRecordMatch( - { - path: '/', - alias: '/home', - name: 'Home', - components, - meta: { foo: true }, - }, - { name: 'Home' }, - { - name: 'Home', - path: '/', - params: {}, - meta: { foo: true }, - matched: [ - { - path: '/', - name: 'Home', - components, - aliasOf: undefined, - meta: { foo: true }, - }, - ], - } - ) - }) + assertRecordMatch( + record, + { path: '/' }, + { + name: 'Home', + path: '/', + params: {}, + meta: { foo: true }, + matched: [ + { + path: '/', + name: 'Home', + components, + aliasOf: undefined, + meta: { foo: true }, + }, + ], + } + ) + assertRecordMatch( + record, + { path: '/home' }, + { + name: 'Home', + path: '/home', + params: {}, + meta: { foo: true }, + matched: [ + { + path: '/home', + name: 'Home', + components, + aliasOf: expect.objectContaining({ name: 'Home', path: '/' }), + meta: { foo: true }, + }, + ], + } + ) + assertRecordMatch( + record, + { path: '/start' }, + { + name: 'Home', + path: '/start', + params: {}, + meta: { foo: true }, + matched: [ + { + path: '/start', + name: 'Home', + components, + aliasOf: expect.objectContaining({ name: 'Home', path: '/' }), + meta: { foo: true }, + }, + ], + } + ) + }) - it('resolves an alias with children to the alias when using the path', () => { - const children = [{ path: 'one', component, name: 'nested' }] - assertRecordMatch( - { - path: '/parent', - alias: '/p', - component, - children, - }, - { path: '/p/one' }, - { - path: '/p/one', - name: 'nested', - params: {}, - matched: [ - { - path: '/p', - children, - components, - aliasOf: expect.objectContaining({ path: '/parent' }), - }, - { - path: '/p/one', - name: 'nested', - components, - aliasOf: expect.objectContaining({ path: '/parent/one' }), - }, - ], - } - ) - }) + it('resolves the original record by name', () => { + assertRecordMatch( + { + path: '/', + alias: '/home', + name: 'Home', + components, + meta: { foo: true }, + }, + { name: 'Home' }, + { + name: 'Home', + path: '/', + params: {}, + meta: { foo: true }, + matched: [ + { + path: '/', + name: 'Home', + components, + aliasOf: undefined, + meta: { foo: true }, + }, + ], + } + ) + }) - describe('nested aliases', () => { - const children = [ - { - path: 'one', - component, - name: 'nested', - alias: 'o', - children: [ - { path: 'two', alias: 't', name: 'nestednested', component }, - ], - }, - { - path: 'other', - alias: 'otherAlias', - component, - name: 'other', - }, - ] - const record = { + it('resolves an alias with children to the alias when using the path', () => { + const children = [{ path: 'one', component, name: 'nested' }] + assertRecordMatch( + { path: '/parent', - name: 'parent', alias: '/p', component, children, - } - - it('resolves the parent as an alias', () => { - assertRecordMatch( - record, - { path: '/p' }, - expect.objectContaining({ + }, + { path: '/p/one' }, + { + path: '/p/one', + name: 'nested', + params: {}, + matched: [ + { path: '/p', - name: 'parent', - matched: [ - expect.objectContaining({ - path: '/p', - aliasOf: expect.objectContaining({ path: '/parent' }), - }), - ], - }) - ) - }) - - describe('multiple children', () => { - // tests concerning the /parent/other path and its aliases - - it('resolves the alias parent', () => { - assertRecordMatch( - record, - { path: '/p/other' }, - expect.objectContaining({ - path: '/p/other', - name: 'other', - matched: [ - expect.objectContaining({ - path: '/p', - aliasOf: expect.objectContaining({ path: '/parent' }), - }), - expect.objectContaining({ - path: '/p/other', - aliasOf: expect.objectContaining({ path: '/parent/other' }), - }), - ], - }) - ) - }) + children, + components, + aliasOf: expect.objectContaining({ path: '/parent' }), + }, + { + path: '/p/one', + name: 'nested', + components, + aliasOf: expect.objectContaining({ path: '/parent/one' }), + }, + ], + } + ) + }) - it('resolves the alias child', () => { - assertRecordMatch( - record, - { path: '/parent/otherAlias' }, - expect.objectContaining({ - path: '/parent/otherAlias', - name: 'other', - matched: [ - expect.objectContaining({ - path: '/parent', - aliasOf: undefined, - }), - expect.objectContaining({ - path: '/parent/otherAlias', - aliasOf: expect.objectContaining({ path: '/parent/other' }), - }), - ], - }) - ) - }) + describe('nested aliases', () => { + const children = [ + { + path: 'one', + component, + name: 'nested', + alias: 'o', + children: [ + { path: 'two', alias: 't', name: 'nestednested', component }, + ], + }, + { + path: 'other', + alias: 'otherAlias', + component, + name: 'other', + }, + ] + const record = { + path: '/parent', + name: 'parent', + alias: '/p', + component, + children, + } - it('resolves the alias parent and child', () => { - assertRecordMatch( - record, - { path: '/p/otherAlias' }, + it('resolves the parent as an alias', () => { + assertRecordMatch( + record, + { path: '/p' }, + expect.objectContaining({ + path: '/p', + name: 'parent', + matched: [ expect.objectContaining({ - path: '/p/otherAlias', - name: 'other', - matched: [ - expect.objectContaining({ - path: '/p', - aliasOf: expect.objectContaining({ path: '/parent' }), - }), - expect.objectContaining({ - path: '/p/otherAlias', - aliasOf: expect.objectContaining({ path: '/parent/other' }), - }), - ], - }) - ) + path: '/p', + aliasOf: expect.objectContaining({ path: '/parent' }), + }), + ], }) - }) - - it('resolves the original one with no aliases', () => { - assertRecordMatch( - record, - { path: '/parent/one/two' }, - expect.objectContaining({ - path: '/parent/one/two', - name: 'nestednested', - matched: [ - expect.objectContaining({ - path: '/parent', - aliasOf: undefined, - }), - expect.objectContaining({ - path: '/parent/one', - aliasOf: undefined, - }), - expect.objectContaining({ - path: '/parent/one/two', - aliasOf: undefined, - }), - ], - }) - ) - }) - - it.todo( - 'resolves when parent is an alias and child has an absolute path' ) + }) - it('resolves when parent is an alias', () => { - assertRecordMatch( - record, - { path: '/p/one/two' }, - expect.objectContaining({ - path: '/p/one/two', - name: 'nestednested', - matched: [ - expect.objectContaining({ - path: '/p', - aliasOf: expect.objectContaining({ path: '/parent' }), - }), - expect.objectContaining({ - path: '/p/one', - aliasOf: expect.objectContaining({ path: '/parent/one' }), - }), - expect.objectContaining({ - path: '/p/one/two', - aliasOf: expect.objectContaining({ path: '/parent/one/two' }), - }), - ], - }) - ) - }) + describe('multiple children', () => { + // tests concerning the /parent/other path and its aliases - it('resolves a different child when parent is an alias', () => { + it('resolves the alias parent', () => { assertRecordMatch( record, { path: '/p/other' }, @@ -437,125 +318,42 @@ describe('Router Matcher', () => { ) }) - it('resolves when the first child is an alias', () => { - assertRecordMatch( - record, - { path: '/parent/o/two' }, - expect.objectContaining({ - path: '/parent/o/two', - name: 'nestednested', - matched: [ - expect.objectContaining({ - path: '/parent', - aliasOf: undefined, - }), - expect.objectContaining({ - path: '/parent/o', - aliasOf: expect.objectContaining({ path: '/parent/one' }), - }), - expect.objectContaining({ - path: '/parent/o/two', - aliasOf: expect.objectContaining({ path: '/parent/one/two' }), - }), - ], - }) - ) - }) - - it('resolves when the second child is an alias', () => { - assertRecordMatch( - record, - { path: '/parent/one/t' }, - expect.objectContaining({ - path: '/parent/one/t', - name: 'nestednested', - matched: [ - expect.objectContaining({ - path: '/parent', - aliasOf: undefined, - }), - expect.objectContaining({ - path: '/parent/one', - aliasOf: undefined, - }), - expect.objectContaining({ - path: '/parent/one/t', - aliasOf: expect.objectContaining({ path: '/parent/one/two' }), - }), - ], - }) - ) - }) - - it('resolves when the two last children are aliases', () => { + it('resolves the alias child', () => { assertRecordMatch( record, - { path: '/parent/o/t' }, + { path: '/parent/otherAlias' }, expect.objectContaining({ - path: '/parent/o/t', - name: 'nestednested', + path: '/parent/otherAlias', + name: 'other', matched: [ expect.objectContaining({ path: '/parent', aliasOf: undefined, }), expect.objectContaining({ - path: '/parent/o', - aliasOf: expect.objectContaining({ path: '/parent/one' }), - }), - expect.objectContaining({ - path: '/parent/o/t', - aliasOf: expect.objectContaining({ path: '/parent/one/two' }), - }), - ], - }) - ) - }) - - it('resolves when all are aliases', () => { - assertRecordMatch( - record, - { path: '/p/o/t' }, - expect.objectContaining({ - path: '/p/o/t', - name: 'nestednested', - matched: [ - expect.objectContaining({ - path: '/p', - aliasOf: expect.objectContaining({ path: '/parent' }), - }), - expect.objectContaining({ - path: '/p/o', - aliasOf: expect.objectContaining({ path: '/parent/one' }), - }), - expect.objectContaining({ - path: '/p/o/t', - aliasOf: expect.objectContaining({ path: '/parent/one/two' }), + path: '/parent/otherAlias', + aliasOf: expect.objectContaining({ path: '/parent/other' }), }), ], }) ) }) - it('resolves when first and last are aliases', () => { + it('resolves the alias parent and child', () => { assertRecordMatch( record, - { path: '/p/one/t' }, + { path: '/p/otherAlias' }, expect.objectContaining({ - path: '/p/one/t', - name: 'nestednested', + path: '/p/otherAlias', + name: 'other', matched: [ expect.objectContaining({ path: '/p', aliasOf: expect.objectContaining({ path: '/parent' }), }), expect.objectContaining({ - path: '/p/one', - aliasOf: expect.objectContaining({ path: '/parent/one' }), - }), - expect.objectContaining({ - path: '/p/one/t', - aliasOf: expect.objectContaining({ path: '/parent/one/two' }), + path: '/p/otherAlias', + aliasOf: expect.objectContaining({ path: '/parent/other' }), }), ], }) @@ -563,588 +361,786 @@ describe('Router Matcher', () => { }) }) - it('resolves the original path of the named children of a route with an alias', () => { - const children = [{ path: 'one', component, name: 'nested' }] + it('resolves the original one with no aliases', () => { assertRecordMatch( - { - path: '/parent', - alias: '/p', - component, - children, - }, - { name: 'nested' }, - { - path: '/parent/one', - name: 'nested', - params: {}, + record, + { path: '/parent/one/two' }, + expect.objectContaining({ + path: '/parent/one/two', + name: 'nestednested', matched: [ - { + expect.objectContaining({ path: '/parent', - children, - components, aliasOf: undefined, - }, - { path: '/parent/one', name: 'nested', components }, + }), + expect.objectContaining({ + path: '/parent/one', + aliasOf: undefined, + }), + expect.objectContaining({ + path: '/parent/one/two', + aliasOf: undefined, + }), ], - } + }) ) }) - }) - describe('LocationAsPath', () => { - it('resolves a normal path', () => { - assertRecordMatch( - { path: '/', name: 'Home', components }, - { path: '/' }, - { name: 'Home', path: '/', params: {} } - ) - }) + it.todo('resolves when parent is an alias and child has an absolute path') - it('resolves a normal path without name', () => { + it('resolves when parent is an alias', () => { assertRecordMatch( - { path: '/', components }, - { path: '/' }, - { name: undefined, path: '/', params: {} } - ) - }) - - it('resolves a path with params', () => { - assertRecordMatch( - { path: '/users/:id', name: 'User', components }, - { path: '/users/posva' }, - { name: 'User', params: { id: 'posva' } } - ) - }) - - it('resolves an array of params for a repeatable params', () => { - assertRecordMatch( - { path: '/a/:p+', name: 'a', components }, - { name: 'a', params: { p: ['b', 'c', 'd'] } }, - { name: 'a', path: '/a/b/c/d', params: { p: ['b', 'c', 'd'] } } - ) - }) - - it('resolves single params for a repeatable params', () => { - assertRecordMatch( - { path: '/a/:p+', name: 'a', components }, - { name: 'a', params: { p: 'b' } }, - { name: 'a', path: '/a/b', params: { p: 'b' } } + record, + { path: '/p/one/two' }, + expect.objectContaining({ + path: '/p/one/two', + name: 'nestednested', + matched: [ + expect.objectContaining({ + path: '/p', + aliasOf: expect.objectContaining({ path: '/parent' }), + }), + expect.objectContaining({ + path: '/p/one', + aliasOf: expect.objectContaining({ path: '/parent/one' }), + }), + expect.objectContaining({ + path: '/p/one/two', + aliasOf: expect.objectContaining({ path: '/parent/one/two' }), + }), + ], + }) ) }) - it('keeps repeated params as a single one when provided through path', () => { + it('resolves a different child when parent is an alias', () => { assertRecordMatch( - { path: '/a/:p+', name: 'a', components }, - { path: '/a/b/c' }, - { name: 'a', params: { p: ['b', 'c'] } } + record, + { path: '/p/other' }, + expect.objectContaining({ + path: '/p/other', + name: 'other', + matched: [ + expect.objectContaining({ + path: '/p', + aliasOf: expect.objectContaining({ path: '/parent' }), + }), + expect.objectContaining({ + path: '/p/other', + aliasOf: expect.objectContaining({ path: '/parent/other' }), + }), + ], + }) ) }) - it('resolves a path with multiple params', () => { + it('resolves when the first child is an alias', () => { assertRecordMatch( - { path: '/users/:id/:other', name: 'User', components }, - { path: '/users/posva/hey' }, - { name: 'User', params: { id: 'posva', other: 'hey' } } + record, + { path: '/parent/o/two' }, + expect.objectContaining({ + path: '/parent/o/two', + name: 'nestednested', + matched: [ + expect.objectContaining({ + path: '/parent', + aliasOf: undefined, + }), + expect.objectContaining({ + path: '/parent/o', + aliasOf: expect.objectContaining({ path: '/parent/one' }), + }), + expect.objectContaining({ + path: '/parent/o/two', + aliasOf: expect.objectContaining({ path: '/parent/one/two' }), + }), + ], + }) ) }) - it('resolves a path with multiple params but no name', () => { + it('resolves when the second child is an alias', () => { assertRecordMatch( - { path: '/users/:id/:other', components }, - { path: '/users/posva/hey' }, - { name: undefined, params: { id: 'posva', other: 'hey' } } + record, + { path: '/parent/one/t' }, + expect.objectContaining({ + path: '/parent/one/t', + name: 'nestednested', + matched: [ + expect.objectContaining({ + path: '/parent', + aliasOf: undefined, + }), + expect.objectContaining({ + path: '/parent/one', + aliasOf: undefined, + }), + expect.objectContaining({ + path: '/parent/one/t', + aliasOf: expect.objectContaining({ path: '/parent/one/two' }), + }), + ], + }) ) }) - it('returns an empty match when the path does not exist', () => { + it('resolves when the two last children are aliases', () => { assertRecordMatch( - { path: '/', components }, - { path: '/foo' }, - { name: undefined, params: {}, path: '/foo', matched: [] } + record, + { path: '/parent/o/t' }, + expect.objectContaining({ + path: '/parent/o/t', + name: 'nestednested', + matched: [ + expect.objectContaining({ + path: '/parent', + aliasOf: undefined, + }), + expect.objectContaining({ + path: '/parent/o', + aliasOf: expect.objectContaining({ path: '/parent/one' }), + }), + expect.objectContaining({ + path: '/parent/o/t', + aliasOf: expect.objectContaining({ path: '/parent/one/two' }), + }), + ], + }) ) }) - it('allows an optional trailing slash', () => { + it('resolves when all are aliases', () => { assertRecordMatch( - { path: '/home/', name: 'Home', components }, - { path: '/home/' }, - { name: 'Home', path: '/home/', matched: expect.any(Array) } + record, + { path: '/p/o/t' }, + expect.objectContaining({ + path: '/p/o/t', + name: 'nestednested', + matched: [ + expect.objectContaining({ + path: '/p', + aliasOf: expect.objectContaining({ path: '/parent' }), + }), + expect.objectContaining({ + path: '/p/o', + aliasOf: expect.objectContaining({ path: '/parent/one' }), + }), + expect.objectContaining({ + path: '/p/o/t', + aliasOf: expect.objectContaining({ path: '/parent/one/two' }), + }), + ], + }) ) }) - // FIXME: - it.skip('keeps required trailing slash (strict: true)', () => { - const record = { - path: '/home/', - name: 'Home', - components, - options: { strict: true }, - } - assertErrorMatch(record, { path: '/home' }) + it('resolves when first and last are aliases', () => { assertRecordMatch( record, - { path: '/home/' }, - { name: 'Home', path: '/home/', matched: expect.any(Array) } + { path: '/p/one/t' }, + expect.objectContaining({ + path: '/p/one/t', + name: 'nestednested', + matched: [ + expect.objectContaining({ + path: '/p', + aliasOf: expect.objectContaining({ path: '/parent' }), + }), + expect.objectContaining({ + path: '/p/one', + aliasOf: expect.objectContaining({ path: '/parent/one' }), + }), + expect.objectContaining({ + path: '/p/one/t', + aliasOf: expect.objectContaining({ path: '/parent/one/two' }), + }), + ], + }) ) }) + }) - it('rejects a trailing slash when strict', () => { - const record = { - path: '/home', - name: 'Home', - components, - options: { strict: true }, + it('resolves the original path of the named children of a route with an alias', () => { + const children = [{ path: 'one', component, name: 'nested' }] + assertRecordMatch( + { + path: '/parent', + alias: '/p', + component, + children, + }, + { name: 'nested' }, + { + path: '/parent/one', + name: 'nested', + params: {}, + matched: [ + { + path: '/parent', + children, + components, + aliasOf: undefined, + }, + { path: '/parent/one', name: 'nested', components }, + ], } - assertRecordMatch( - record, - { path: '/home' }, - { name: 'Home', path: '/home', matched: expect.any(Array) } - ) - assertErrorMatch(record, { path: '/home/' }) - }) + ) }) + }) - describe('LocationAsName', () => { - it('matches a name', () => { - assertRecordMatch( - { path: '/home', name: 'Home', components }, - { name: 'Home' }, - { name: 'Home', path: '/home' } - ) - }) + describe('LocationAsPath', () => { + it('resolves a normal path', () => { + assertRecordMatch( + { path: '/', name: 'Home', components }, + { path: '/' }, + { name: 'Home', path: '/', params: {} } + ) + }) - it('matches a name and fill params', () => { - assertRecordMatch( - { path: '/users/:id/m/:role', name: 'UserEdit', components }, - { name: 'UserEdit', params: { id: 'posva', role: 'admin' } }, - { name: 'UserEdit', path: '/users/posva/m/admin' } - ) - }) + it('resolves a normal path without name', () => { + assertRecordMatch( + { path: '/', components }, + { path: '/' }, + { name: undefined, path: '/', params: {} } + ) + }) - it('throws if the named route does not exists', () => { - expect( - assertErrorMatch({ path: '/', components }, { name: 'Home' }) - ).toMatchSnapshot() - }) + it('resolves a path with params', () => { + assertRecordMatch( + { path: '/users/:id', name: 'User', components }, + { path: '/users/posva' }, + { name: 'User', params: { id: 'posva' } } + ) }) - describe('LocationAsRelative', () => { - it('matches with nothing', () => { - const record = { path: '/home', name: 'Home', components } - assertRecordMatch( - record, - {}, - { name: 'Home', path: '/home' }, - { - name: 'Home', - params: {}, - path: '/home', - matched: [record] as any, - meta: {}, - } - ) - }) + it('resolves an array of params for a repeatable params', () => { + assertRecordMatch( + { path: '/a/:p+', name: 'a', components }, + { name: 'a', params: { p: ['b', 'c', 'd'] } }, + { name: 'a', path: '/a/b/c/d', params: { p: ['b', 'c', 'd'] } } + ) + }) - it('replace params even with no name', () => { - const record = { path: '/users/:id/m/:role', components } - assertRecordMatch( - record, - { params: { id: 'posva', role: 'admin' } }, - { name: undefined, path: '/users/posva/m/admin' }, - { - path: '/users/ed/m/user', - name: undefined, - params: { id: 'ed', role: 'user' }, - matched: [record] as any, - meta: {}, - } - ) - }) + it('resolves single params for a repeatable params', () => { + assertRecordMatch( + { path: '/a/:p+', name: 'a', components }, + { name: 'a', params: { p: 'b' } }, + { name: 'a', path: '/a/b', params: { p: 'b' } } + ) + }) + + it('keeps repeated params as a single one when provided through path', () => { + assertRecordMatch( + { path: '/a/:p+', name: 'a', components }, + { path: '/a/b/c' }, + { name: 'a', params: { p: ['b', 'c'] } } + ) + }) + + it('resolves a path with multiple params', () => { + assertRecordMatch( + { path: '/users/:id/:other', name: 'User', components }, + { path: '/users/posva/hey' }, + { name: 'User', params: { id: 'posva', other: 'hey' } } + ) + }) + + it('resolves a path with multiple params but no name', () => { + assertRecordMatch( + { path: '/users/:id/:other', components }, + { path: '/users/posva/hey' }, + { name: undefined, params: { id: 'posva', other: 'hey' } } + ) + }) + + it('returns an empty match when the path does not exist', () => { + assertRecordMatch( + { path: '/', components }, + { path: '/foo' }, + { name: undefined, params: {}, path: '/foo', matched: [] } + ) + }) + + it('allows an optional trailing slash', () => { + assertRecordMatch( + { path: '/home/', name: 'Home', components }, + { path: '/home/' }, + { name: 'Home', path: '/home/', matched: expect.any(Array) } + ) + }) + + // FIXME: + it.skip('keeps required trailing slash (strict: true)', () => { + const record = { + path: '/home/', + name: 'Home', + components, + options: { strict: true }, + } + assertErrorMatch(record, { path: '/home' }) + assertRecordMatch( + record, + { path: '/home/' }, + { name: 'Home', path: '/home/', matched: expect.any(Array) } + ) + }) + + it('rejects a trailing slash when strict', () => { + const record = { + path: '/home', + name: 'Home', + components, + options: { strict: true }, + } + assertRecordMatch( + record, + { path: '/home' }, + { name: 'Home', path: '/home', matched: expect.any(Array) } + ) + assertErrorMatch(record, { path: '/home/' }) + }) + }) - it('replace params', () => { - const record = { - path: '/users/:id/m/:role', + describe('LocationAsName', () => { + it('matches a name', () => { + assertRecordMatch( + { path: '/home', name: 'Home', components }, + { name: 'Home' }, + { name: 'Home', path: '/home' } + ) + }) + + it('matches a name and fill params', () => { + assertRecordMatch( + { path: '/users/:id/m/:role', name: 'UserEdit', components }, + { name: 'UserEdit', params: { id: 'posva', role: 'admin' } }, + { name: 'UserEdit', path: '/users/posva/m/admin' } + ) + }) + + it('throws if the named route does not exists', () => { + expect( + assertErrorMatch({ path: '/', components }, { name: 'Home' }) + ).toMatchSnapshot() + }) + }) + + describe('LocationAsRelative', () => { + it('matches with nothing', () => { + const record = { path: '/home', name: 'Home', components } + assertRecordMatch( + record, + {}, + { name: 'Home', path: '/home' }, + { + name: 'Home', + params: {}, + path: '/home', + matched: [record] as any, + meta: {}, + } + ) + }) + + it('replace params even with no name', () => { + const record = { path: '/users/:id/m/:role', components } + assertRecordMatch( + record, + { params: { id: 'posva', role: 'admin' } }, + { name: undefined, path: '/users/posva/m/admin' }, + { + path: '/users/ed/m/user', + name: undefined, + params: { id: 'ed', role: 'user' }, + matched: [record] as any, + meta: {}, + } + ) + }) + + it('replace params', () => { + const record = { + path: '/users/:id/m/:role', + name: 'UserEdit', + components, + } + assertRecordMatch( + record, + { params: { id: 'posva', role: 'admin' } }, + { name: 'UserEdit', path: '/users/posva/m/admin' }, + { + path: '/users/ed/m/user', name: 'UserEdit', - components, + params: { id: 'ed', role: 'user' }, + matched: [], + meta: {}, } - assertRecordMatch( - record, - { params: { id: 'posva', role: 'admin' } }, - { name: 'UserEdit', path: '/users/posva/m/admin' }, - { - path: '/users/ed/m/user', - name: 'UserEdit', - params: { id: 'ed', role: 'user' }, - matched: [], - meta: {}, - } - ) - }) + ) + }) - it('keep params if not provided', () => { - const record = { - path: '/users/:id/m/:role', + it('keep params if not provided', () => { + const record = { + path: '/users/:id/m/:role', + name: 'UserEdit', + components, + } + assertRecordMatch( + record, + {}, + { name: 'UserEdit', - components, + path: '/users/ed/m/user', + params: { id: 'ed', role: 'user' }, + }, + { + path: '/users/ed/m/user', + name: 'UserEdit', + params: { id: 'ed', role: 'user' }, + matched: [record] as any, + meta: {}, } - assertRecordMatch( - record, - {}, - { - name: 'UserEdit', - path: '/users/ed/m/user', - params: { id: 'ed', role: 'user' }, - }, - { - path: '/users/ed/m/user', - name: 'UserEdit', - params: { id: 'ed', role: 'user' }, - matched: [record] as any, - meta: {}, - } - ) - }) + ) + }) - it('keep params if not provided even with no name', () => { - const record = { path: '/users/:id/m/:role', components } - assertRecordMatch( + it('keep params if not provided even with no name', () => { + const record = { path: '/users/:id/m/:role', components } + assertRecordMatch( + record, + {}, + { + name: undefined, + path: '/users/ed/m/user', + params: { id: 'ed', role: 'user' }, + }, + { + path: '/users/ed/m/user', + name: undefined, + params: { id: 'ed', role: 'user' }, + matched: [record] as any, + meta: {}, + } + ) + }) + + it('throws if the current named route does not exists', () => { + const record = { path: '/', components } + const start = { + name: 'home', + params: {}, + path: '/', + matched: [record], + } + // the property should be non enumerable + Object.defineProperty(start, 'matched', { enumerable: false }) + expect( + assertErrorMatch( record, - {}, - { - name: undefined, - path: '/users/ed/m/user', - params: { id: 'ed', role: 'user' }, - }, + { params: { a: 'foo' } }, { - path: '/users/ed/m/user', - name: undefined, - params: { id: 'ed', role: 'user' }, - matched: [record] as any, + ...start, + matched: start.matched.map(normalizeRouteRecord), meta: {}, } ) - }) + ).toMatchSnapshot() + }) + }) - it('throws if the current named route does not exists', () => { - const record = { path: '/', components } - const start = { - name: 'home', + describe('children', () => { + const ChildA = { path: 'a', name: 'child-a', components } + const ChildB = { path: 'b', name: 'child-b', components } + const ChildC = { path: 'c', name: 'child-c', components } + const ChildD = { path: '/absolute', name: 'absolute', components } + const ChildWithParam = { path: ':p', name: 'child-params', components } + const NestedChildWithParam = { + ...ChildWithParam, + name: 'nested-child-params', + } + const NestedChildA = { ...ChildA, name: 'nested-child-a' } + const NestedChildB = { ...ChildB, name: 'nested-child-b' } + const NestedChildC = { ...ChildC, name: 'nested-child-c' } + const Nested = { + path: 'nested', + name: 'nested', + components, + children: [NestedChildA, NestedChildB, NestedChildC], + } + const NestedWithParam = { + path: 'nested/:n', + name: 'nested', + components, + children: [NestedChildWithParam], + } + + it('resolves children', () => { + const Foo = { + path: '/foo', + name: 'Foo', + components, + children: [ChildA, ChildB, ChildC], + } + assertRecordMatch( + Foo, + { path: '/foo/b' }, + { + name: 'child-b', + path: '/foo/b', params: {}, - path: '/', - matched: [record], + matched: [Foo, { ...ChildB, path: `${Foo.path}/${ChildB.path}` }], } - // the property should be non enumerable - Object.defineProperty(start, 'matched', { enumerable: false }) - expect( - assertErrorMatch( - record, - { params: { a: 'foo' } }, - { - ...start, - matched: start.matched.map(normalizeRouteRecord), - meta: {}, - } - ) - ).toMatchSnapshot() - }) + ) }) - describe('children', () => { - const ChildA = { path: 'a', name: 'child-a', components } - const ChildB = { path: 'b', name: 'child-b', components } - const ChildC = { path: 'c', name: 'child-c', components } - const ChildD = { path: '/absolute', name: 'absolute', components } - const ChildWithParam = { path: ':p', name: 'child-params', components } - const NestedChildWithParam = { - ...ChildWithParam, - name: 'nested-child-params', + it('resolves children with empty paths', () => { + const Nested = { path: '', name: 'nested', components } + const Foo = { + path: '/foo', + name: 'Foo', + components, + children: [Nested], } - const NestedChildA = { ...ChildA, name: 'nested-child-a' } - const NestedChildB = { ...ChildB, name: 'nested-child-b' } - const NestedChildC = { ...ChildC, name: 'nested-child-c' } + assertRecordMatch( + Foo, + { path: '/foo' }, + { + name: 'nested', + path: '/foo', + params: {}, + matched: [Foo, { ...Nested, path: `${Foo.path}` }], + } + ) + }) + + it('resolves nested children with empty paths', () => { + const NestedNested = { path: '', name: 'nested', components } const Nested = { - path: 'nested', - name: 'nested', + path: '', + name: 'nested-nested', components, - children: [NestedChildA, NestedChildB, NestedChildC], + children: [NestedNested], } - const NestedWithParam = { - path: 'nested/:n', - name: 'nested', + const Foo = { + path: '/foo', + name: 'Foo', components, - children: [NestedChildWithParam], + children: [Nested], } - - it('resolves children', () => { - const Foo = { - path: '/foo', - name: 'Foo', - components, - children: [ChildA, ChildB, ChildC], - } - assertRecordMatch( - Foo, - { path: '/foo/b' }, - { - name: 'child-b', - path: '/foo/b', - params: {}, - matched: [Foo, { ...ChildB, path: `${Foo.path}/${ChildB.path}` }], - } - ) - }) - - it('resolves children with empty paths', () => { - const Nested = { path: '', name: 'nested', components } - const Foo = { - path: '/foo', - name: 'Foo', - components, - children: [Nested], - } - assertRecordMatch( - Foo, - { path: '/foo' }, - { - name: 'nested', - path: '/foo', - params: {}, - matched: [Foo, { ...Nested, path: `${Foo.path}` }], - } - ) - }) - - it('resolves nested children with empty paths', () => { - const NestedNested = { path: '', name: 'nested', components } - const Nested = { - path: '', - name: 'nested-nested', - components, - children: [NestedNested], - } - const Foo = { + assertRecordMatch( + Foo, + { path: '/foo' }, + { + name: 'nested', path: '/foo', - name: 'Foo', - components, - children: [Nested], + params: {}, + matched: [ + Foo, + { ...Nested, path: `${Foo.path}` }, + { ...NestedNested, path: `${Foo.path}` }, + ], } - assertRecordMatch( - Foo, - { path: '/foo' }, - { - name: 'nested', - path: '/foo', - params: {}, - matched: [ - Foo, - { ...Nested, path: `${Foo.path}` }, - { ...NestedNested, path: `${Foo.path}` }, - ], - } - ) - }) + ) + }) - it('resolves nested children', () => { - const Foo = { - path: '/foo', - name: 'Foo', - components, - children: [Nested], + it('resolves nested children', () => { + const Foo = { + path: '/foo', + name: 'Foo', + components, + children: [Nested], + } + assertRecordMatch( + Foo, + { path: '/foo/nested/a' }, + { + name: 'nested-child-a', + path: '/foo/nested/a', + params: {}, + matched: [ + Foo, + { ...Nested, path: `${Foo.path}/${Nested.path}` }, + { + ...NestedChildA, + path: `${Foo.path}/${Nested.path}/${NestedChildA.path}`, + }, + ], } - assertRecordMatch( - Foo, - { path: '/foo/nested/a' }, - { - name: 'nested-child-a', - path: '/foo/nested/a', - params: {}, - matched: [ - Foo, - { ...Nested, path: `${Foo.path}/${Nested.path}` }, - { - ...NestedChildA, - path: `${Foo.path}/${Nested.path}/${NestedChildA.path}`, - }, - ], - } - ) - }) + ) + }) - it('resolves nested children with named location', () => { - const Foo = { - path: '/foo', - name: 'Foo', - components, - children: [Nested], + it('resolves nested children with named location', () => { + const Foo = { + path: '/foo', + name: 'Foo', + components, + children: [Nested], + } + assertRecordMatch( + Foo, + { name: 'nested-child-a' }, + { + name: 'nested-child-a', + path: '/foo/nested/a', + params: {}, + matched: [ + Foo, + { ...Nested, path: `${Foo.path}/${Nested.path}` }, + { + ...NestedChildA, + path: `${Foo.path}/${Nested.path}/${NestedChildA.path}`, + }, + ], } - assertRecordMatch( - Foo, - { name: 'nested-child-a' }, - { - name: 'nested-child-a', - path: '/foo/nested/a', - params: {}, - matched: [ - Foo, - { ...Nested, path: `${Foo.path}/${Nested.path}` }, - { - ...NestedChildA, - path: `${Foo.path}/${Nested.path}/${NestedChildA.path}`, - }, - ], - } - ) - }) + ) + }) - it('resolves nested children with relative location', () => { - const Foo = { - path: '/foo', - name: 'Foo', - components, - children: [Nested], + it('resolves nested children with relative location', () => { + const Foo = { + path: '/foo', + name: 'Foo', + components, + children: [Nested], + } + assertRecordMatch( + Foo, + {}, + { + name: 'nested-child-a', + path: '/foo/nested/a', + params: {}, + matched: [ + Foo, + { ...Nested, path: `${Foo.path}/${Nested.path}` }, + { + ...NestedChildA, + path: `${Foo.path}/${Nested.path}/${NestedChildA.path}`, + }, + ], + }, + { + name: 'nested-child-a', + matched: [], + params: {}, + path: '/foo/nested/a', + meta: {}, } - assertRecordMatch( - Foo, - {}, - { - name: 'nested-child-a', - path: '/foo/nested/a', - params: {}, - matched: [ - Foo, - { ...Nested, path: `${Foo.path}/${Nested.path}` }, - { - ...NestedChildA, - path: `${Foo.path}/${Nested.path}/${NestedChildA.path}`, - }, - ], - }, - { - name: 'nested-child-a', - matched: [], - params: {}, - path: '/foo/nested/a', - meta: {}, - } - ) - }) + ) + }) - it('resolves nested children with params', () => { - const Foo = { - path: '/foo', - name: 'Foo', - components, - children: [NestedWithParam], + it('resolves nested children with params', () => { + const Foo = { + path: '/foo', + name: 'Foo', + components, + children: [NestedWithParam], + } + assertRecordMatch( + Foo, + { path: '/foo/nested/a/b' }, + { + name: 'nested-child-params', + path: '/foo/nested/a/b', + params: { p: 'b', n: 'a' }, + matched: [ + Foo, + { + ...NestedWithParam, + path: `${Foo.path}/${NestedWithParam.path}`, + }, + { + ...NestedChildWithParam, + path: `${Foo.path}/${NestedWithParam.path}/${NestedChildWithParam.path}`, + }, + ], } - assertRecordMatch( - Foo, - { path: '/foo/nested/a/b' }, - { - name: 'nested-child-params', - path: '/foo/nested/a/b', - params: { p: 'b', n: 'a' }, - matched: [ - Foo, - { - ...NestedWithParam, - path: `${Foo.path}/${NestedWithParam.path}`, - }, - { - ...NestedChildWithParam, - path: `${Foo.path}/${NestedWithParam.path}/${NestedChildWithParam.path}`, - }, - ], - } - ) - }) + ) + }) - it('resolves nested children with params with named location', () => { - const Foo = { - path: '/foo', - name: 'Foo', - components, - children: [NestedWithParam], + it('resolves nested children with params with named location', () => { + const Foo = { + path: '/foo', + name: 'Foo', + components, + children: [NestedWithParam], + } + assertRecordMatch( + Foo, + { name: 'nested-child-params', params: { p: 'a', n: 'b' } }, + { + name: 'nested-child-params', + path: '/foo/nested/b/a', + params: { p: 'a', n: 'b' }, + matched: [ + Foo, + { + ...NestedWithParam, + path: `${Foo.path}/${NestedWithParam.path}`, + }, + { + ...NestedChildWithParam, + path: `${Foo.path}/${NestedWithParam.path}/${NestedChildWithParam.path}`, + }, + ], } - assertRecordMatch( - Foo, - { name: 'nested-child-params', params: { p: 'a', n: 'b' } }, - { - name: 'nested-child-params', - path: '/foo/nested/b/a', - params: { p: 'a', n: 'b' }, - matched: [ - Foo, - { - ...NestedWithParam, - path: `${Foo.path}/${NestedWithParam.path}`, - }, - { - ...NestedChildWithParam, - path: `${Foo.path}/${NestedWithParam.path}/${NestedChildWithParam.path}`, - }, - ], - } - ) - }) + ) + }) - it('resolves absolute path children', () => { - const Foo = { - path: '/foo', - name: 'Foo', - components, - children: [ChildA, ChildD], + it('resolves absolute path children', () => { + const Foo = { + path: '/foo', + name: 'Foo', + components, + children: [ChildA, ChildD], + } + assertRecordMatch( + Foo, + { path: '/absolute' }, + { + name: 'absolute', + path: '/absolute', + params: {}, + matched: [Foo, ChildD], } - assertRecordMatch( - Foo, - { path: '/absolute' }, - { - name: 'absolute', - path: '/absolute', - params: {}, - matched: [Foo, ChildD], - } - ) - }) + ) + }) - it('resolves children with root as the parent', () => { - const Nested = { path: 'nested', name: 'nested', components } - const Parent = { - path: '/', - name: 'parent', - components, - children: [Nested], + it('resolves children with root as the parent', () => { + const Nested = { path: 'nested', name: 'nested', components } + const Parent = { + path: '/', + name: 'parent', + components, + children: [Nested], + } + assertRecordMatch( + Parent, + { path: '/nested' }, + { + name: 'nested', + path: '/nested', + params: {}, + matched: [Parent, { ...Nested, path: `/nested` }], } - assertRecordMatch( - Parent, - { path: '/nested' }, - { - name: 'nested', - path: '/nested', - params: {}, - matched: [Parent, { ...Nested, path: `/nested` }], - } - ) - }) + ) + }) - it('resolves children with parent with trailing slash', () => { - const Nested = { path: 'nested', name: 'nested', components } - const Parent = { - path: '/parent/', - name: 'parent', - components, - children: [Nested], + it('resolves children with parent with trailing slash', () => { + const Nested = { path: 'nested', name: 'nested', components } + const Parent = { + path: '/parent/', + name: 'parent', + components, + children: [Nested], + } + assertRecordMatch( + Parent, + { path: '/parent/nested' }, + { + name: 'nested', + path: '/parent/nested', + params: {}, + matched: [Parent, { ...Nested, path: `/parent/nested` }], } - assertRecordMatch( - Parent, - { path: '/parent/nested' }, - { - name: 'nested', - path: '/parent/nested', - params: {}, - matched: [Parent, { ...Nested, path: `/parent/nested` }], - } - ) - }) + ) }) }) }) -- 2.39.5