diff --git a/__tests__/routing.test.ts b/__tests__/routing.test.ts index 65cef0f..30cf69e 100644 --- a/__tests__/routing.test.ts +++ b/__tests__/routing.test.ts @@ -1,20 +1,47 @@ import { createRouting, number, segment } from '../src/index'; -describe('routing', () => { - it('should create routing', () => { +describe('createRouting', () => { + it('creates a simple route', () => { const routes = createRouting({ - company: segment`/companies/${number('companyId')}`, - contact: segment`/contacts/${number('contactId')}`, - insight: segment`/insight/${number('insightId')}`, - admin: { - ...segment`/admin`, + products: segment`/products`, + } as const); + + const route = routes.products(); + + expect(route).toEqual('/products'); + }); + + it('creates nested routes', () => { + const routes = createRouting({ + products: { + ...segment`/products`, + children: { + create: segment`/create`, + }, + }, + } as const); + + const mainRoute = routes.products(); + const nestedRoute = routes.products.create(); + + expect(mainRoute).toEqual('/products'); + expect(nestedRoute).toEqual('/products/create'); + }); + + it('creates nested routes with params', () => { + const routes = createRouting({ + products: { + ...segment`/products/${number('productId')}`, children: { - users: segment`/users`, + edit: segment`/edit`, }, }, - onetime: segment`/onetime`, } as const); - routes.company({ companyId: '20' }); + const mainRoute = routes.products({ productId: '2' }); + const nestedRoute = routes.products.edit({ productId: '2' }); + + expect(mainRoute).toEqual('/products/2'); + expect(nestedRoute).toEqual('/products/2/edit'); }); }); diff --git a/__tests__/segments/arg.test.ts b/__tests__/segments/arg.test.ts new file mode 100644 index 0000000..7be1cc9 --- /dev/null +++ b/__tests__/segments/arg.test.ts @@ -0,0 +1,47 @@ +import { arg, createRouting, segment } from '../../src'; + +describe('arg segment', () => { + it('creates route with an arg segment', () => { + const routes = createRouting({ + product: segment`/product/${arg('productId')}`, + } as const); + + const route = routes.product({ productId: 'id' }); + + expect(route).toEqual('/product/id'); + }); + + it('creates route with an optional arg segment', () => { + const routes = createRouting({ + product: segment`/product/${arg('productId', { + optional: true, + })}`, + } as const); + + const route = routes.product(); + + expect(route).toEqual('/product'); + }); + + it('creates route with a custom pattern param', () => { + const routes = createRouting({ + product: segment`/product/${arg('productId', { + pattern: /[0-9]{2}/.source, + })}`, + } as const); + + const route = routes.product({ productId: '23' }); + + expect(route).toEqual('/product/23'); + }); + + it('route with a custom pattern param gets correctly validated', () => { + const routes = createRouting({ + product: segment`/product/${arg('productId', { + pattern: /[0-9]{2}/.source, + })}`, + } as const); + + expect(() => routes.product({ productId: '123' })).toThrow(); + }); +}); diff --git a/__tests__/segments/number.test.ts b/__tests__/segments/number.test.ts new file mode 100644 index 0000000..3484d0b --- /dev/null +++ b/__tests__/segments/number.test.ts @@ -0,0 +1,31 @@ +import { createRouting, number, segment } from '../../src'; + +describe('number segment', () => { + it('creates route with an optional number param', () => { + const routes = createRouting({ + product: segment`/product/${number('productId', true)}`, + } as const); + + const route = routes.product(); + + expect(route).toEqual('/product'); + }); + + it('creates route with a required number param', () => { + const routes = createRouting({ + product: segment`/product/${number('productId')}`, + } as const); + + const route = routes.product({ productId: '1' }); + + expect(route).toEqual('/product/1'); + }); + + it('throws when given an invalid number param', () => { + const routes = createRouting({ + product: segment`/product/${number('productId')}`, + } as const); + + expect(() => routes.product({ productId: 'aaa' })).toThrow(); + }); +}); diff --git a/__tests__/segments/query.test.ts b/__tests__/segments/query.test.ts new file mode 100644 index 0000000..2583715 --- /dev/null +++ b/__tests__/segments/query.test.ts @@ -0,0 +1,36 @@ +import { createRouting, number, query, segment } from '../../src'; + +describe('query segment', () => { + it('creates route with an optional query param', () => { + const routes = createRouting({ + product: segment`/product${query({ productId: false })}`, + } as const); + + const route = routes.product(); + + expect(route).toEqual('/product'); + }); + + it('creates route with a required query param', () => { + const routes = createRouting({ + product: segment`/product${query({ productId: true })}`, + } as const); + + const route = routes.product({}, { productId: '2' }); + + expect(route).toEqual('/product?productId=2'); + }); + + it('creates route with multiple query params and they are sorted in alphabetical order', () => { + const routes = createRouting({ + product: segment`/product${query({ + productId: true, + details: true, + })}`, + } as const); + + const route = routes.product({}, { productId: '2', details: 'false' }); + + expect(route).toEqual(`/product?details=false&productId=2`); + }); +}); diff --git a/__tests__/segments/uuid.test.ts b/__tests__/segments/uuid.test.ts new file mode 100644 index 0000000..1cec77a --- /dev/null +++ b/__tests__/segments/uuid.test.ts @@ -0,0 +1,43 @@ +import { createRouting, number, segment, uuid } from '../../src'; + +describe('uuid segment', () => { + const testUuid = '3d368832-0bc0-4fcc-bf75-5bd8794c1ad3'; + + it('creates route with an optional uuid param', () => { + const routes = createRouting({ + product: segment`/product/${uuid('productId', true)}`, + } as const); + + const route = routes.product(); + + expect(route).toEqual('/product'); + }); + + it('creates route with a required uuid param', () => { + const routes = createRouting({ + product: segment`/product/${uuid('productId')}`, + } as const); + + const route = routes.product({ productId: testUuid }); + + expect(route).toEqual(`/product/${testUuid}`); + }); + + it('throws when given a plain string', () => { + const routes = createRouting({ + product: segment`/product/${uuid('productId')}`, + } as const); + + expect(() => routes.product({ productId: 'a' })).toThrow(); + }); + + it('throws when given an invalid uuid', () => { + const routes = createRouting({ + product: segment`/product/${uuid('productId')}`, + } as const); + + expect(() => + routes.product({ productId: '3d368832-0bc-4fcc-bf75-5bd8794c1ad3' }) + ).toThrow(); + }); +});