Skip to content

Commit

Permalink
Add heading tests and testbed (#52)
Browse files Browse the repository at this point in the history
- fix bug where id not added to heading (regression from 5c3728d)
- add heading link to topmost h1 afterall
- change `innerText` to `textContent` for support in jest (jsdom)
- add section of routes for dev-only test routes
- make testbed page for testing out and experimenting with component look and feel
- make test for app heading component to see that auto level and link work
  • Loading branch information
vincerubinetti committed Oct 26, 2021
1 parent 8d785a2 commit f3a9767
Show file tree
Hide file tree
Showing 7 changed files with 122 additions and 29 deletions.
3 changes: 2 additions & 1 deletion src/components/AppGallery.vue
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ $cell: minmax(100px, 1fr);
}
}
// force no margins for children since grid already provides gap
.gallery :deep(*) {
margin: 0;
margin: 0 !important;
}
</style>
44 changes: 17 additions & 27 deletions src/components/AppHeading.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<component :is="tag || 'div'" ref="heading">
<component :is="tag || 'div'" ref="heading" :id="link">
<!-- heading content -->
<slot />

Expand Down Expand Up @@ -30,27 +30,22 @@ function setTag(this: Heading) {
}
// otherwise, determine automatically based on heading's position in document
// https://dequeuniversity.com/rules/axe/4.1/page-has-heading-one
else {
// heading element
const element = this?.$refs?.heading as HTMLElement;
// parent section element
const section = element.closest("section") as HTMLElement;
// is there an existing h1 (besides self)
let h1 = document.querySelector("h1");
if (h1 === element) h1 = null;
// if heading is first element in section
if (element.matches(":first-child")) {
// if section is first section in <main> and if no other h1s already
// (only one h1 per page for accessibility)
if (section.matches(":first-child") && !h1) level = 1;
// if section is latter
else level = 2;
}
// if heading is latter
else {
level = 3;
}
// if heading is first in parent
const firstInParent = element.matches("*:first-child");
// if heading is first in document
const firstInDoc = element.matches(
"main > section:first-child > *:first-child, main > *:first-child"
);
// determine level
if (firstInDoc) level = 1;
else if (firstInParent) level = 2;
else level = 3;
}
// set tag/component
Expand All @@ -61,14 +56,9 @@ function setTag(this: Heading) {
function setLink(this: Heading) {
// heading element
const element = this?.$refs?.heading as HTMLElement;
// parent section element
const section = element.closest("section") as HTMLElement;
// if heading right at top of page, don't have link because no point
if (element.matches(":first-child") && section.matches(":first-child"))
this.link = "";
// otherwise, determine link from text content of heading
else this.link = kebabCase(element.innerText);
// determine link from text content of heading
this.link = kebabCase(element.textContent || "");
}
// heading component with anchor link and (optionally) automatic level
Expand Down
12 changes: 12 additions & 0 deletions src/router/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import Publications from "@/views/about/Publications.vue";
import Sources from "@/views/about/Sources.vue";
import Terms from "@/views/about/Terms.vue";
import Help from "@/views/help/Help.vue";
import Testbed from "@/views/Testbed.vue";
import { sleep } from "@/util/debug";

// handle redirect from 404
Expand Down Expand Up @@ -84,6 +85,17 @@ export const routes: Array<RouteRecordRaw> = [
name: "Help",
component: Help,
},

// test routes (pages to only include during development)
...(process.env.NODE_ENV === "development"
? [
{
path: "/testbed",
name: "Testbed",
component: Testbed,
},
]
: []),
];

const scrollBehavior: RouterScrollBehavior = async (
Expand Down
28 changes: 28 additions & 0 deletions src/views/Testbed.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<!--
dev page for experimenting with design and behavior of components. also a
place for seeing all variations at once to check for coherence. not included
in production build of site.
-->
<template>
<!-- status component -->
<AppSection>
<AppGallery>
<AppStatus code="loading" text="Loading some results" />
<AppStatus code="success" text="Action was a success" />
<AppStatus code="warning" text="Be careful" />
<AppStatus code="error" text="There was an error" />
<AppStatus code="paused" text="Action is paused" />
<AppStatus code="unknown" text="Unexpected result" />
</AppGallery>
</AppSection>
<AppSection>
<AppGallery>
<AppStatus code="loading" design="big" text="Loading some results" />
<AppStatus code="success" design="big" text="Action was a success" />
<AppStatus code="warning" design="big" text="Be careful" />
<AppStatus code="error" design="big" text="There was an error" />
<AppStatus code="paused" design="big" text="Action is paused" />
<AppStatus code="unknown" design="big" text="Unexpected result" />
</AppGallery>
</AppSection>
</template>
2 changes: 1 addition & 1 deletion src/views/about/publications.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@
issue: "2:32"
link: "[pubmed](http://www.ncbi.nlm.nih.gov/pubmed/31119199)"

- year: 2019
- year: 2018
list:
- title: "Classification, Ontology, and Precision Medicine (2018)"
authors: "Haendel MA, Chute CG, Robinson PN 2018"
Expand Down
45 changes: 45 additions & 0 deletions tests/unit/AppHeading.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { sleep } from "./../../src/util/debug";
import { flushPromises, mount } from "@vue/test-utils";
import AppHeadings from "./AppHeadings.vue";
import { mountOptions } from "../setup";

const tags = "h1, h2, h3, h4";

test("Chooses heading levels correctly", async () => {
// mount hoc
const wrapper = mount(AppHeadings, mountOptions);

// wait for everything to render
await flushPromises();

// find all heading components
const headings = wrapper.findAll(tags);

// go through each
for (const heading of headings) {
// compare expected tag to actual rendered tag
const received = heading.element.tagName.toLowerCase();
const expected = heading.attributes("data-tag")?.toLowerCase();
expect(received).toBe(expected);
}
});

test("Creates heading links correctly", async () => {
// mount hoc
const wrapper = mount(AppHeadings, mountOptions);

// wait for everything to render
await flushPromises();
await sleep();

// find all heading components
const headings = wrapper.findAll(tags);

// go through each
for (const heading of headings) {
// compare expected link to actual rendered link
const received = heading.attributes("id");
const expected = heading.attributes("data-link");
expect(received).toBe(expected);
}
});
17 changes: 17 additions & 0 deletions tests/unit/AppHeadings.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<template>
<!--
higher-order component (hoc) to test heading auto-levels/links. use data
attributes to indicate expected.
-->
<main>
<AppSection>
<AppHeading data-tag="h1" data-link="abc-def-gih">ABC-def_gih</AppHeading>
</AppSection>
<AppSection>
<AppHeading data-tag="h2" data-link="123-alphabet-street">
123 Alphabet Street
</AppHeading>
<AppHeading data-tag="h3" data-link="aeo">áéó</AppHeading>
</AppSection>
</main>
</template>

0 comments on commit f3a9767

Please sign in to comment.