Skip to content

Commit

Permalink
Simple createRoute signatures
Browse files Browse the repository at this point in the history
  • Loading branch information
smikhalevski committed Jul 18, 2024
1 parent 8966394 commit db91b59
Show file tree
Hide file tree
Showing 2 changed files with 112 additions and 11 deletions.
59 changes: 52 additions & 7 deletions src/main/createRoute.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { ComponentType } from 'react';
import { Route } from './Route';
import { RouteOptions } from './types';

Expand All @@ -9,7 +10,7 @@ import { RouteOptions } from './types';
* @template Data Data loaded by a route.
* @template Context A context provided by a {@link Router} for a {@link RouteOptions.loader}.
*/
export function createRoute<Params extends object | void = void, Data = void, Context = any>(
export function createRoute<Params extends object | void = object | void, Data = void, Context = any>(
options?: RouteOptions<Params, Data, Context>
): Route<null, Params, Data, Context>;

Expand All @@ -23,14 +24,58 @@ export function createRoute<Params extends object | void = void, Data = void, Co
* @template Data Data loaded by a route.
* @template Context A context provided by a {@link Router} for a {@link RouteOptions.loader}.
*/
export function createRoute<Parent extends Route, Params extends object | void = void, Data = void>(
export function createRoute<Parent extends Route, Params extends object | void = object | void, Data = void>(
parent: Parent,
options?: RouteOptions<Params, Data, Parent['_context']>
): Route<Parent, Params, Data, Parent['_context']>;

export function createRoute(
parentOrOptions?: Route | RouteOptions<any, any, any>,
options?: RouteOptions<any, any, any>
) {
return parentOrOptions instanceof Route ? new Route(parentOrOptions, options) : new Route(null, parentOrOptions);
/**
* Creates a route that is rendered in the {@link Outlet} of a {@link Router}.
*
* @param pathname A URL {@link RouteOptions.pathname pathname} pattern.
* @param component A component that is rendered by a route.
* @template Params Route params.
*/
export function createRoute<Params extends object | void = object | void>(
pathname: string,
component?: ComponentType
): Route<null, Params, void>;

/**
* Creates a route that is rendered in the {@link Outlet} of a parent route.
*
* @param parent A parent route.
* @param pathname A URL {@link RouteOptions.pathname pathname} pattern.
* @param component A component that is rendered by a route.
* @template Parent A parent route.
* @template Params Route params.
*/
export function createRoute<Parent extends Route, Params extends object | void = object | void>(
parent: Parent,
pathname: string,
component?: ComponentType
): Route<Parent, Params, void>;

export function createRoute(arg1: any, arg2?: any, component?: ComponentType): Route {
return new Route(
arg1 instanceof Route ? arg1 : null,

typeof arg1 === 'string'
? // (pathname, component)
{
pathname: arg1,
component: arg2,
}
: arg1 instanceof Route && typeof arg2 === 'string'
? // (parent, pathname, component)
{
pathname: arg2,
component,
}
: arg1 instanceof Route
? // (parent, options)
arg2
: // (options)
arg1
);
}
64 changes: 60 additions & 4 deletions src/test/createRoute.test.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,70 @@
import { createRoute, Route } from '../main';
import { createRoute, Outlet, Route } from '../main';

describe('createRoute', () => {
test('creates a route without a parent', () => {
const Component = () => null;

test('no args signature', () => {
expect(createRoute()).toBeInstanceOf(Route);
expect(createRoute().parent).toBeNull();
});

test('creates a route with a parent', () => {
test('(options) signature', () => {
const route = createRoute({ pathname: '/rrr' });

expect(route.parent).toBeNull();
expect(route.pathnameTemplate.pattern).toBe('/rrr');
expect(route.getComponent()).toBe(Outlet);
});

test('(parent) signature', () => {
const aaaRoute = createRoute();
const route = createRoute(aaaRoute);

expect(route.parent).toBe(aaaRoute);
expect(route.pathnameTemplate.pattern).toBe('/');
expect(route.getComponent()).toBe(Outlet);
});

test('(parent, options) signature', () => {
const aaaRoute = createRoute();
const route = createRoute(aaaRoute, { pathname: '/rrr' });

expect(route.parent).toBe(aaaRoute);
expect(route.pathnameTemplate.pattern).toBe('/rrr');
expect(route.getComponent()).toBe(Outlet);
});

test('(pathname) signature', () => {
const route = createRoute('/rrr');

expect(route.parent).toBeNull();
expect(route.pathnameTemplate.pattern).toBe('/rrr');
expect(route.getComponent()).toBe(Outlet);
});

test('(pathname, component) signature', () => {
const route = createRoute('/rrr', Component);

expect(route.parent).toBeNull();
expect(route.pathnameTemplate.pattern).toBe('/rrr');
expect(route.getComponent()).toBe(Component);
});

test('(parent, pathname) signature', () => {
const aaaRoute = createRoute();
const route = createRoute(aaaRoute, '/rrr');

expect(route.parent).toBe(aaaRoute);
expect(route.pathnameTemplate.pattern).toBe('/rrr');
expect(route.getComponent()).toBe(Outlet);
});

test('(parent, pathname, component) signature', () => {
const aaaRoute = createRoute();
const route = createRoute(aaaRoute, '/rrr', Component);

expect(createRoute(aaaRoute).parent).toBe(aaaRoute);
expect(route.parent).toBe(aaaRoute);
expect(route.pathnameTemplate.pattern).toBe('/rrr');
expect(route.getComponent()).toBe(Component);
});
});

0 comments on commit db91b59

Please sign in to comment.