Tests I
parent
280608b08c
commit
d1be7c4817
|
@ -0,0 +1,42 @@
|
||||||
|
jest.mock("takeme", () => ({ navigate: jest.fn() }));
|
||||||
|
|
||||||
|
import { clickHandler, Link } from "../link";
|
||||||
|
import * as React from "react";
|
||||||
|
import { navigate } from "takeme";
|
||||||
|
import { shallow } from "enzyme";
|
||||||
|
|
||||||
|
describe("clickHandler", () => {
|
||||||
|
function setupClickTest(to: string) {
|
||||||
|
const onClick = jest.fn();
|
||||||
|
const handler = clickHandler({ to, onClick });
|
||||||
|
type ClickEvent = React.MouseEvent<HTMLAnchorElement>;
|
||||||
|
const e: Partial<ClickEvent> = { preventDefault: jest.fn() };
|
||||||
|
return {
|
||||||
|
e: e as ClickEvent,
|
||||||
|
handler,
|
||||||
|
onClick
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
it("handles clicks", () => {
|
||||||
|
const { e, handler } = setupClickTest("/clean_path");
|
||||||
|
handler(e);
|
||||||
|
expect(e.preventDefault).toHaveBeenCalled();
|
||||||
|
expect(navigate).toHaveBeenCalledWith("/clean_path");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("handles clicks, stripping out the `/app` part", () => {
|
||||||
|
const { e, handler } = setupClickTest("/app/foo/bar");
|
||||||
|
handler(e);
|
||||||
|
expect(e.preventDefault).toHaveBeenCalled();
|
||||||
|
expect(navigate).toHaveBeenCalledWith("/foo/bar");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("<Link/>", () => {
|
||||||
|
it("renders child elements", () => {
|
||||||
|
function Child(_: unknown) { return <p>Hey!</p>; }
|
||||||
|
const el = shallow(<Link to="/wherever"><Child /></Link>);
|
||||||
|
expect(el.html()).toContain("Hey!");
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,32 @@
|
||||||
|
import { UNBOUND_ROUTES, UnboundRouteConfig } from "../route_config";
|
||||||
|
import { RouteEnterEvent } from "takeme";
|
||||||
|
|
||||||
|
interface ConnectedComponent {
|
||||||
|
name: string;
|
||||||
|
WrappedComponent: React.ComponentType;
|
||||||
|
}
|
||||||
|
|
||||||
|
type Info = UnboundRouteConfig<{}, {}>;
|
||||||
|
|
||||||
|
function mapper(bind_to: Function, index: number) {
|
||||||
|
return bind_to((x: ConnectedComponent, y: ConnectedComponent | undefined, z: Info) => {
|
||||||
|
expect(index).toBeGreaterThan(-1);
|
||||||
|
expect(x.name).toBe("Connect");
|
||||||
|
expect(x.WrappedComponent.name).toContain(z.key);
|
||||||
|
if (y && z.children) {
|
||||||
|
expect(y.name).toBe("Connect");
|
||||||
|
expect(y.WrappedComponent.name).toContain(z.childKey);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
describe("UNBOUND_ROUTES", () => {
|
||||||
|
it("generates correct routes", () => {
|
||||||
|
const fake: RouteEnterEvent = {
|
||||||
|
params: { splat: "????" },
|
||||||
|
oldPath: "??",
|
||||||
|
newPath: "??"
|
||||||
|
};
|
||||||
|
UNBOUND_ROUTES.map(mapper).map(x => { x.enter && x.enter(fake); });
|
||||||
|
});
|
||||||
|
});
|
|
@ -3,7 +3,7 @@ import { navigate } from "takeme";
|
||||||
|
|
||||||
interface LinkProps extends React.AnchorHTMLAttributes<HTMLAnchorElement> {
|
interface LinkProps extends React.AnchorHTMLAttributes<HTMLAnchorElement> {
|
||||||
to: string;
|
to: string;
|
||||||
children: React.ReactChild | React.ReactChild[];
|
children?: React.ReactChild | React.ReactChild[];
|
||||||
style?: React.CSSProperties;
|
style?: React.CSSProperties;
|
||||||
className?: string;
|
className?: string;
|
||||||
}
|
}
|
||||||
|
@ -11,18 +11,18 @@ interface LinkProps extends React.AnchorHTMLAttributes<HTMLAnchorElement> {
|
||||||
export const maybeStripLegacyUrl =
|
export const maybeStripLegacyUrl =
|
||||||
(url: string) => url.startsWith("/app") ? url.replace("/app", "") : url;
|
(url: string) => url.startsWith("/app") ? url.replace("/app", "") : url;
|
||||||
|
|
||||||
|
export const clickHandler =
|
||||||
|
(props: LinkProps) => (e: React.MouseEvent<HTMLAnchorElement>) => {
|
||||||
|
e.preventDefault();
|
||||||
|
/** BEGIN LEGACY SHIMS */
|
||||||
|
const { onClick, to } = props;
|
||||||
|
navigate(maybeStripLegacyUrl(to));
|
||||||
|
onClick && onClick(e);
|
||||||
|
};
|
||||||
|
|
||||||
export class Link extends React.Component<LinkProps, {}> {
|
export class Link extends React.Component<LinkProps, {}> {
|
||||||
render() {
|
render() {
|
||||||
const { props } = this;
|
const { props } = this;
|
||||||
return <a
|
return <a {...props} href={props.to} onClick={clickHandler(props)} />;
|
||||||
{...props}
|
|
||||||
href={props.to}
|
|
||||||
onClick={(e: React.MouseEvent<HTMLAnchorElement>) => {
|
|
||||||
e.preventDefault();
|
|
||||||
/** BEGIN LEGACY SHIMS */
|
|
||||||
const { onClick, to } = props;
|
|
||||||
navigate(maybeStripLegacyUrl(to));
|
|
||||||
onClick && onClick(e);
|
|
||||||
}} />;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ interface UnboundRouteConfigChild<T, U> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The union of both route config types. */
|
/** The union of both route config types. */
|
||||||
type UnboundRouteConfig<T, U> =
|
export type UnboundRouteConfig<T, U> =
|
||||||
UnboundRouteConfigNoChild<T> | UnboundRouteConfigChild<T, U>;
|
UnboundRouteConfigNoChild<T> | UnboundRouteConfigChild<T, U>;
|
||||||
/** This is the preferred way to generate a route in the app.
|
/** This is the preferred way to generate a route in the app.
|
||||||
* PROBLEM:
|
* PROBLEM:
|
||||||
|
@ -61,9 +61,9 @@ function route<T, U>(info: UnboundRouteConfig<T, U>) {
|
||||||
const comp = (await info.getModule())[info.key];
|
const comp = (await info.getModule())[info.key];
|
||||||
if (info.children) {
|
if (info.children) {
|
||||||
const child = (await info.getChild())[info.childKey];
|
const child = (await info.getChild())[info.childKey];
|
||||||
callback(comp, child);
|
callback(comp, child, info);
|
||||||
} else {
|
} else {
|
||||||
callback((await info.getModule())[info.key]);
|
callback((await info.getModule())[info.key], undefined, info);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
|
|
Loading…
Reference in New Issue