@@ -2,7 +2,10 @@ import { describe, expect, it } from 'vitest'
22import {
33 MatcherPatternPathStatic ,
44 MatcherPatternPathStar ,
5+ MatcherPatternPathCustom ,
56} from './matcher-pattern'
7+ import { pathEncoded } from '../resolver-abstract'
8+ import { invalid } from './errors'
69
710describe ( 'MatcherPatternPathStatic' , ( ) => {
811 describe ( 'match()' , ( ) => {
@@ -100,3 +103,126 @@ describe('MatcherPatternPathStar', () => {
100103 } )
101104 } )
102105} )
106+
107+ describe ( 'MatcherPatternPathCustom' , ( ) => {
108+ it ( 'single param' , ( ) => {
109+ const pattern = new MatcherPatternPathCustom (
110+ / ^ \/ t e a m s \/ ( [ ^ / ] + ?) \/ b $ / i,
111+ {
112+ // all defaults
113+ teamId : { } ,
114+ } ,
115+ ( { teamId } ) => {
116+ if ( typeof teamId !== 'string' ) {
117+ throw invalid ( 'teamId must be a string' )
118+ }
119+ return pathEncoded `/teams/${ teamId } /b`
120+ }
121+ )
122+
123+ expect ( pattern . match ( '/teams/123/b' ) ) . toEqual ( {
124+ teamId : '123' ,
125+ } )
126+ expect ( pattern . match ( '/teams/abc/b' ) ) . toEqual ( {
127+ teamId : 'abc' ,
128+ } )
129+ expect ( ( ) => pattern . match ( '/teams/123/c' ) ) . toThrow ( )
130+ expect ( ( ) => pattern . match ( '/teams/123/b/c' ) ) . toThrow ( )
131+ expect ( ( ) => pattern . match ( '/teams' ) ) . toThrow ( )
132+ expect ( ( ) => pattern . match ( '/teams/' ) ) . toThrow ( )
133+ } )
134+
135+ it ( 'decodes single param' , ( ) => {
136+ const pattern = new MatcherPatternPathCustom (
137+ / ^ \/ t e a m s \/ ( [ ^ / ] + ?) $ / i,
138+ {
139+ teamId : { } ,
140+ } ,
141+ ( { teamId } ) => {
142+ if ( typeof teamId !== 'string' ) {
143+ throw invalid ( 'teamId must be a string' )
144+ }
145+ return pathEncoded `/teams/${ teamId } `
146+ }
147+ )
148+ expect ( pattern . match ( '/teams/a%20b' ) ) . toEqual ( { teamId : 'a b' } )
149+ expect ( pattern . build ( { teamId : 'a b' } ) ) . toBe ( '/teams/a%20b' )
150+ } )
151+
152+ it ( 'optional param' , ( ) => {
153+ const pattern = new MatcherPatternPathCustom (
154+ / ^ \/ t e a m s (?: \/ ( [ ^ / ] + ?) ) ? \/ b $ / i,
155+ {
156+ teamId : { optional : true } ,
157+ } ,
158+ ( { teamId } ) => {
159+ if ( teamId != null && typeof teamId !== 'string' ) {
160+ throw invalid ( 'teamId must be a string' )
161+ }
162+ return teamId ? pathEncoded `/teams/${ teamId } /b` : '/teams/b'
163+ }
164+ )
165+
166+ expect ( pattern . match ( '/teams/b' ) ) . toEqual ( { teamId : null } )
167+ expect ( pattern . match ( '/teams/123/b' ) ) . toEqual ( { teamId : '123' } )
168+ expect ( ( ) => pattern . match ( '/teams/123/c' ) ) . toThrow ( )
169+ expect ( ( ) => pattern . match ( '/teams/123/b/c' ) ) . toThrow ( )
170+ expect ( pattern . build ( { teamId : '123' } ) ) . toBe ( '/teams/123/b' )
171+ expect ( pattern . build ( { teamId : null } ) ) . toBe ( '/teams/b' )
172+ } )
173+
174+ it ( 'repeatable param' , ( ) => {
175+ const pattern = new MatcherPatternPathCustom (
176+ / ^ \/ t e a m s \/ ( .+ ?) \/ b $ / i,
177+ {
178+ teamId : { repeat : true } ,
179+ } ,
180+ ( { teamId } ) => {
181+ if ( ! Array . isArray ( teamId ) ) {
182+ throw invalid ( 'teamId must be an array' )
183+ }
184+ return '/teams/' + teamId . join ( '/' ) + '/b'
185+ }
186+ )
187+
188+ expect ( pattern . match ( '/teams/123/b' ) ) . toEqual ( { teamId : [ '123' ] } )
189+ expect ( pattern . match ( '/teams/123/456/b' ) ) . toEqual ( {
190+ teamId : [ '123' , '456' ] ,
191+ } )
192+ expect ( ( ) => pattern . match ( '/teams/123/c' ) ) . toThrow ( )
193+ expect ( ( ) => pattern . match ( '/teams/123/b/c' ) ) . toThrow ( )
194+ expect ( pattern . build ( { teamId : [ '123' ] } ) ) . toBe ( '/teams/123/b' )
195+ expect ( pattern . build ( { teamId : [ '123' , '456' ] } ) ) . toBe ( '/teams/123/456/b' )
196+ } )
197+
198+ it ( 'repeatable optional param' , ( ) => {
199+ const pattern = new MatcherPatternPathCustom (
200+ / ^ \/ t e a m s (?: \/ ( .+ ?) ) ? \/ b $ / i,
201+ {
202+ teamId : { repeat : true , optional : true } ,
203+ } ,
204+ ( { teamId } ) => {
205+ if ( ! Array . isArray ( teamId ) ) {
206+ throw invalid ( 'teamId must be an array' )
207+ }
208+ const joined = teamId . join ( '/' )
209+ return teamId
210+ ? '/teams' + ( joined ? '/' + joined : '' ) + '/b'
211+ : '/teams/b'
212+ }
213+ )
214+
215+ expect ( pattern . match ( '/teams/123/b' ) ) . toEqual ( { teamId : [ '123' ] } )
216+ expect ( pattern . match ( '/teams/123/456/b' ) ) . toEqual ( {
217+ teamId : [ '123' , '456' ] ,
218+ } )
219+ expect ( pattern . match ( '/teams/b' ) ) . toEqual ( { teamId : [ ] } )
220+
221+ expect ( ( ) => pattern . match ( '/teams/123/c' ) ) . toThrow ( )
222+ expect ( ( ) => pattern . match ( '/teams/123/b/c' ) ) . toThrow ( )
223+
224+ expect ( pattern . build ( { teamId : [ '123' ] } ) ) . toBe ( '/teams/123/b' )
225+ expect ( pattern . build ( { teamId : [ '123' , '456' ] } ) ) . toBe ( '/teams/123/456/b' )
226+ expect ( pattern . build ( { teamId : [ ] } ) ) . toBe ( '/teams/b' )
227+ } )
228+ } )
0 commit comments