link: verify that routes have trailing slash (#1001)

Summary:
This serves as a regression test for #1000.

Test Plan:
Note that `yarn unit` passes with this patch but fails if the change to
the code is reverted, or if the patch in #1000 is reverted. Note that
`yarn build` also passes but fails if the patch in #1000 is reverted.
Note also that `yarn test --full` passes.

wchargin-branch: link-verify-trailing-slash
This commit is contained in:
William Chargin 2018-11-08 20:53:30 -08:00 committed by GitHub
parent 24c1873dca
commit 0a6eca7d79
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 21 additions and 3 deletions

View File

@ -41,6 +41,10 @@ export default class Link extends Component<LinkProps> {
</Tag> </Tag>
); );
if ("to" in this.props) { if ("to" in this.props) {
if (!this.props.to.endsWith("/")) {
// All our routes have trailing slashes. This must be an error.
throw new Error("'to' prop must specify route with trailing slash.");
}
return make(RouterLink); return make(RouterLink);
} else if ("href" in this.props) { } else if ("href" in this.props) {
return make("a"); return make("a");

View File

@ -18,7 +18,7 @@ describe("webutil/Link", () => {
void [ void [
// Must specify either `href` or `to` // Must specify either `href` or `to`
<Link href="https://example.com/">click me</Link>, <Link href="https://example.com/">click me</Link>,
<Link to="/prototype">click me, too</Link>, <Link to="/prototype/">click me, too</Link>,
// $ExpectFlowError // $ExpectFlowError
<Link>missing to/href</Link>, <Link>missing to/href</Link>,
@ -38,9 +38,9 @@ describe("webutil/Link", () => {
}); });
it("renders a styled router link", () => { it("renders a styled router link", () => {
const element = shallow(<Link to="/prototype">check it out</Link>); const element = shallow(<Link to="/prototype/">check it out</Link>);
expect(element.type()).toEqual(RouterLink); expect(element.type()).toEqual(RouterLink);
expect(element.prop("to")).toEqual("/prototype"); expect(element.prop("to")).toEqual("/prototype/");
expect(element.children().text()).toEqual("check it out"); expect(element.children().text()).toEqual("check it out");
expect(typeof element.prop("className")).toBe("string"); expect(typeof element.prop("className")).toBe("string");
}); });
@ -53,6 +53,20 @@ describe("webutil/Link", () => {
}).toThrow("Must specify either 'to' or 'href'."); }).toThrow("Must specify either 'to' or 'href'.");
}); });
it("fails if router link omits a trailing slash", () => {
const component = <Link to="/foo" />;
expect(() => {
shallow(component);
}).toThrow("'to' prop must specify route with trailing slash.");
});
it("permits external link to omit a trailing slash", () => {
const component = <Link href="/foo" />;
expect(() => {
shallow(component);
}).not.toThrow();
});
it("has deterministic className", () => { it("has deterministic className", () => {
const e1 = shallow(<Link href="#" />); const e1 = shallow(<Link href="#" />);
const e2 = shallow(<Link href="#" />); const e2 = shallow(<Link href="#" />);