})
it('param?', () => {
- matchRegExp('^(?:/(\\d+))?$', [
+ matchRegExp(
+ '^(?:/(\\d+))?/?$',
[
- {
- type: TokenType.Param,
- value: 'id',
- regexp: '\\d+',
- repeatable: false,
- optional: true,
- },
+ [
+ {
+ type: TokenType.Param,
+ value: 'id',
+ regexp: '\\d+',
+ repeatable: false,
+ optional: true,
+ },
+ ],
],
- ])
+ { strict: false }
+ )
})
it('static and param?', () => {
matchParams('/:a*', '/', { a: '' })
})
+ it('static then empty param optional', () => {
+ matchParams('/a/:a?', '/a', { a: '' })
+ matchParams('/a/:a?', '/a/a', { a: 'a' })
+ matchParams('/a/:a?', '/a/a/', { a: 'a' })
+ matchParams('/a/:a?', '/a/', { a: '' })
+ matchParams('/a/:a*', '/a', { a: '' })
+ matchParams('/a/:a*', '/a/', { a: '' })
+ })
+
it('static then param optional', () => {
matchParams('/one/:a?', '/one/two', { a: 'two' })
matchParams('/one/:a?', '/one/', { a: '' })
matchStringify('/:a*', { a: ['one', 'two'] }, '/one/two')
})
+ it('static then optional param?', () => {
+ matchStringify('/a/:a?', { a: '' }, '/a')
+ matchStringify('/a/:a?', {}, '/a')
+ })
+
it('optional param?', () => {
matchStringify('/:a?/other', { a: '' }, '/other')
matchStringify('/:a?/other', {}, '/other')
}
// allows not passing params
- if ('params' in location) {
- resolved.params = resolved.params || location.params
- } else {
- resolved.params = resolved.params || {}
- }
+ resolved.params =
+ resolved.params || ('params' in location ? location.params : {})
const startCopy: MatcherLocation = {
...start,
)
})
+ it('allows an optional trailing slash with optional param', () => {
+ assertRecordMatch(
+ { path: '/:a', components, name: 'a' },
+ { path: '/a/' },
+ { path: '/a/', params: { a: 'a' }, name: 'a' }
+ )
+ assertRecordMatch(
+ { path: '/a/:a', components, name: 'a' },
+ { path: '/a/a/' },
+ { path: '/a/a/', params: { a: 'a' }, name: 'a' }
+ )
+ })
+
+ it('allows an optional trailing slash with missing optional param', () => {
+ assertRecordMatch(
+ { path: '/:a?', components, name: 'a' },
+ { path: '/' },
+ { path: '/', params: { a: '' }, name: 'a' }
+ )
+ assertRecordMatch(
+ { path: '/a/:a?', components, name: 'a' },
+ { path: '/a/' },
+ { path: '/a/', params: { a: '' }, name: 'a' }
+ )
+ })
+
// FIXME:
it.skip('keeps required trailing slash (strict: true)', () => {
const record = {
}
)
})
+
+ it('drops optional params', () => {
+ assertRecordMatch(
+ { path: '/:a/:b?', name: 'p', components },
+ { name: 'p', params: { a: 'b' } },
+ { name: 'p', path: '/b', params: { a: 'b' } },
+ {
+ params: { a: 'a', b: 'b' },
+ path: '/a',
+ matched: [],
+ meta: {},
+ name: undefined,
+ }
+ )
+ })
})
describe('LocationAsRelative', () => {
)
})
+ it('keep optional params', () => {
+ assertRecordMatch(
+ { path: '/:a/:b?', name: 'p', components },
+ {},
+ { name: 'p', path: '/a/b', params: { a: 'a', b: 'b' } },
+ {
+ name: 'p',
+ params: { a: 'a', b: 'b' },
+ path: '/a/b',
+ matched: [],
+ meta: {},
+ }
+ )
+ })
+
+ it('merges optional params', () => {
+ assertRecordMatch(
+ { path: '/:a/:b?', name: 'p', components },
+ { params: { a: 'c' } },
+ { name: 'p', path: '/c/b', params: { a: 'c', b: 'b' } },
+ {
+ name: 'p',
+ params: { a: 'a', b: 'b' },
+ path: '/a/b',
+ matched: [],
+ meta: {},
+ }
+ )
+ })
+
it('throws if the current named route does not exists', () => {
const record = { path: '/', components }
const start = {
// for optional parameters to allow to be empty
let avoidDuplicatedSlash: boolean = false
for (const segment of segments) {
- if (!avoidDuplicatedSlash || path[path.length - 1] !== '/') path += '/'
+ if (!avoidDuplicatedSlash || !path.endsWith('/')) path += '/'
avoidDuplicatedSlash = false
for (const token of segment) {
)
const text: string = Array.isArray(param) ? param.join('/') : param
if (!text) {
- // do not append a slash on the next iteration
- if (optional) avoidDuplicatedSlash = true
- else throw new Error(`Missing required param "${value}"`)
+ if (optional) {
+ // remove the last slash
+ if (path.endsWith('/')) path = path.slice(0, -1)
+ // do not append a slash on the next iteration
+ else avoidDuplicatedSlash = true
+ } else throw new Error(`Missing required param "${value}"`)
}
path += text
}