one
Version:
One is a new React Framework that makes Vite serve both native and web.
341 lines (316 loc) • 8.36 kB
text/typescript
import { beforeEach, describe, expect, it } from 'vitest'
import { getMockConfig } from '../testing-utils'
import { getPathFromState } from './getPathFromState'
import { getStateFromPath } from './getStateFromPath'
import { getUrlWithReactNavigationConcessions, stripBaseUrl } from './getStateFromPath-mods'
describe(stripBaseUrl, () => {
;[
[
// Input
'/',
// Base Path
'',
// Result
'/',
],
['/one/two', '/one', '/two'],
['/one/two', '/one/two', ''],
['/one/two/', '/one/two', '/'],
['///one/', '/one', '/'],
['one/', '/one', 'one/'],
['/a/b', '/one', '/a/b'],
].forEach(([path, baseUrl, result]) => {
it(`strips baseUrl "${path}"`, () => {
expect(stripBaseUrl(path, baseUrl)).toBe(result)
})
})
})
describe('baseUrl', () => {
beforeEach(() => {
process.env.ONE_DEFAULT_RENDER_MODE = 'spa'
})
it('accounts for baseUrl', () => {
process.env.EXPO_BASE_URL = '/expo/prefix'
const path = '/expo/prefix/bar'
const config = getMockConfig(['_layout.tsx', 'bar.tsx', 'index.tsx'])
expect(getStateFromPath<object>(path, config)).toEqual({
routes: [{ name: 'bar', path: '/bar' }],
})
expect(getPathFromState(getStateFromPath<object>(path, config)!, config)).toBe(
'/expo/prefix/bar'
)
})
it('has baseUrl and state that does not match', () => {
process.env.EXPO_BASE_URL = '/expo'
const path = '/bar'
const config = getMockConfig(['_layout.tsx', 'bar.tsx', 'index.tsx'])
expect(getStateFromPath<object>(path, config)).toEqual({
routes: [{ name: 'bar', path: '/bar' }],
})
expect(getPathFromState(getStateFromPath<object>(path, config)!, config)).toBe('/expo/bar')
})
})
describe(getUrlWithReactNavigationConcessions, () => {
beforeEach(() => {
delete process.env.EXPO_BASE_URL
})
;['/', 'foo/', 'foo/bar/', 'foo/bar/baz/'].forEach((path) => {
it(`returns the pathname for ${path}`, () => {
expect(getUrlWithReactNavigationConcessions(path).nonstandardPathname).toBe(path)
})
})
;[
['', '/'],
['https://acme.com/hello/world?foo=bar#123', 'hello/world/'],
['https://acme.com/hello/world/?foo=bar#123', 'hello/world/'],
].forEach(([url, expected]) => {
it(`returns the pathname for ${url}`, () => {
expect(getUrlWithReactNavigationConcessions(url).nonstandardPathname).toBe(expected)
})
})
;[
['/gh-pages/', '/'],
['https://acme.com/gh-pages/hello/world?foo=bar#123', 'hello/world/'],
['https://acme.com/gh-pages/hello/world/?foo=bar#123', 'hello/world/'],
].forEach(([url, expected]) => {
it(`returns the pathname for ${url}`, () => {
expect(getUrlWithReactNavigationConcessions(url, 'gh-pages').nonstandardPathname).toBe(
expected
)
})
})
})
describe('hash', () => {
it(`parses hashes`, () => {
expect(
getStateFromPath('/hello#123', {
screens: {
hello: 'hello',
},
} as any)
).toEqual({
routes: [
{
name: 'hello',
path: '/hello#123',
params: {
'#': '123',
},
},
],
})
})
it('parses hashes with dynamic routes', () => {
expect(getStateFromPath('/hello#123', getMockConfig(['[hello]']))).toEqual({
routes: [
{
name: '[hello]',
params: {
hello: 'hello',
'#': '123',
},
path: '/hello#123',
},
],
})
})
it('parses hashes with query params', () => {
expect(getStateFromPath('/?#123', getMockConfig(['index']))).toEqual({
routes: [
{
name: 'index',
path: '/?#123',
params: {
'#': '123',
},
},
],
})
// TODO: Test rest params
})
})
it(`supports spaces`, () => {
expect(
getStateFromPath('/hello%20world', {
screens: {
'hello world': 'hello world',
},
} as any)
).toEqual({
routes: [
{
name: 'hello world',
path: '/hello%20world',
},
],
})
expect(getStateFromPath('/hello%20world', getMockConfig(['[hello world]']))).toEqual({
routes: [
{
name: '[hello world]',
params: {
'hello world': 'hello world',
},
path: '/hello%20world',
},
],
})
// TODO: Test rest params
})
// TODO
it.skip(`matches against dynamic groups`, () => {
/*
* This will match (app)/([user])/[user]/index with a user = '(explore)'
* It may appear that '(explore)' is a group name but there is not value to match '[user]'
* So it doesn't match any routes in the '(explore)' group
* Therefore, '(explore)' is used as the value for '[user]'
*/
expect(
getStateFromPath(
'/(app)/(explore)',
getMockConfig([
'+not-found',
'(app)/_layout',
'(app)/(explore)/_layout',
'(app)/(explore)/[user]/index',
'(app)/(explore)/explore',
'(app)/([user])/_layout',
'(app)/([user])/[user]/index',
'(app)/([user])/explore',
])
)
).toEqual({
routes: [
{
name: '(app)',
params: { user: '(explore)' },
state: {
routes: [
{
name: '([user])',
params: { user: '(explore)' },
state: {
routes: [
{
name: '[user]/index',
params: { user: '(explore)' },
path: '',
},
],
},
},
],
},
},
],
})
})
it(`adds dynamic route params from all levels of the path`, () => {
// A route at `app/[foo]/bar/[baz]/other` should get all of the params from the path.
expect(
getStateFromPath(
'/foo/bar/baz/other',
getMockConfig([
'[foo]/_layout.tsx',
'[foo]/bar/_layout.tsx',
'[foo]/bar/[baz]/_layout.tsx',
'[foo]/bar/[baz]/other.tsx',
])
)
).toEqual({
routes: [
{
name: '[foo]',
params: { baz: 'baz', foo: 'foo' },
state: {
routes: [
{
name: 'bar',
params: { baz: 'baz', foo: 'foo' },
state: {
routes: [
{
name: '[baz]',
params: { baz: 'baz', foo: 'foo' },
state: {
routes: [
{
name: 'other',
params: {
baz: 'baz',
foo: 'foo',
},
path: '/foo/bar/baz/other',
},
],
},
},
],
},
},
],
},
},
],
})
})
it(`handles not-found routes`, () => {
expect(getStateFromPath('/missing-page', getMockConfig(['+not-found', 'index']))).toEqual({
routes: [
{
name: '+not-found',
params: {
'not-found': ['missing-page'],
},
path: '/missing-page',
},
],
})
})
it(`handles query params`, () => {
expect(
getStateFromPath('/?test=true&hello=world&array=1&array=2', getMockConfig(['index.tsx']))
).toEqual({
routes: [
{
name: 'index',
params: {
test: 'true',
hello: 'world',
array: ['1', '2'],
},
path: '/?test=true&hello=world&array=1&array=2',
},
],
})
})
it(`handles query params`, () => {
expect(
getStateFromPath('/?test=true&hello=world&array=1&array=2', getMockConfig(['index.tsx']))
).toEqual({
routes: [
{
name: 'index',
params: {
test: 'true',
hello: 'world',
array: ['1', '2'],
},
path: '/?test=true&hello=world&array=1&array=2',
},
],
})
})
// TODO
it.skip(`prioritizes hoisted index routes over dynamic groups`, () => {
expect(
getStateFromPath('/(one)', getMockConfig(['(one,two)/index.tsx', '(one,two)/[slug].tsx']))
).toEqual({
routes: [
{
name: '(one)/index',
path: '',
},
],
})
})