• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..16-Feb-2021-

BUILD.gnH A D16-Feb-2021779 2824

DOMHelpers.tsH A D16-Feb-20215.8 KiB176105

EnvironmentHelpers.tsH A D16-Feb-20215.3 KiB12592

InspectorOverlayHelpers.tsH A D16-Feb-202110.4 KiB279229

MockConnection.tsH A D16-Feb-20213.4 KiB10268

MutationHelpers.tsH A D16-Feb-20218.6 KiB243178

MutationHelpers_test.tsH A D16-Feb-20218.8 KiB280241

README.mdH A D16-Feb-20214.2 KiB8657

README.md

1This folder contains helpers for writing Karma unit tests, most of which exist to help render and test components.
2
3
4# DOM Helpers
5
6## Rendering a component in a test
7
8When running a Karma unit test, the DOM that you create during a test is automatically cleaned up for you before the next test, ensuring that no tests are impacted by stray DOM left behind from a previous test.
9
10To ensure you render your component into the test DOM, use the `renderElementIntoDOM` helper, which takes any `HTMLElement` and renders it. By using this helper you ensure that it's cleaned up at the end of the test.
11
12## Asserting presence of variables for TypeScript
13
14When trying to read a component's shadow DOM, TypeScript will ask that you check it's not null first:
15
16```
17component.shadowRoot.querySelector('.foo') // TS will error here: shadowRoot may be `null`.
18```
19
20The `assertShadowRoot` helper will do this for you and fail the test if the shadow root is not present:
21
22```
23assertShadowRoot(component.shadowRoot);
24component.shadowRoot.querySelector('.foo') // TS is happy!
25```
26
27When you query elements from the DOM, you can use `assertElement` or `assertElements` to check that an element is the expected type. This will ensure the test fails if the DOM is not as expected, and satisfy TypeScript:
28
29```
30const button = component.shadowRoot.querySelector('button.foo');
31assertElement(button, HTMLButtonElement);
32
33const allDivs = component.shadowRoot.querySelectorAll('div');
34assertElements(allDivs, HTMLDivElement);
35```
36
37# Mutation helpers
38
39When building components we want to ensure that they are efficient and do not update the DOM more than necessary. We can use the mutation helpers to assert on the amount of DOM changes in a given test. These use a [Mutation Observer](https://developer.mozilla.org/en/docs/Web/API/MutationObserver) to track any mutations.
40
41_Important!_: These tests are async, so you must `await` them.
42
43## Expecting mutations
44
45If you are expecting mutations, you can wrap the part of the test that triggers the mutation in a `withMutation` call. The first argument is an array of mutations you expect (read on for the structure of it), the second is the element to observe (will nearly always be `component.shadowRoot`, and a callback function that takes the observed shadow root. It is this function that will be executed whilst the DOM is being observed for mutations.
46
47```
48it('adds a new button when the data changes', async () => {
49  const component = new MyComponent();
50  component.data = {...}
51  renderElementIntoDOM(component);
52
53  await withMutations([{
54    type: MutationType.ADD, // MutationType is an exported enum from MutationHelpers
55    tagName: 'button',
56    max: 2, // the maximum number of mutations to allow; defaults to 10
57  }], component.shadowRoot, shadowRoot => {
58    // do something that updates the component and causes mutations
59    component.data = {...}
60  })
61})
62```
63
64This test will assert that updating the component causes _at most 2 additions_ to the component's shadow DOM. You can pass `MutationType.ADD` or `MutationType.REMOVE` as the `type` to watch for just additions/removals, or you can omit the `type` key and have the test watch for both additions and removals.
65
66You don't need to wrap every test in a `withMutation` block, but if you are testing some code that should update the DOM, it's a good idea to ensure we aren't unexpectedly doing much more work than expected.
67
68## Expecting no mutations
69
70If you have a test where no DOM should mutate, you can use `withNoMutations`. This is the opposite of `withMutations`; it will fail the test should it detect any DOM mutations. Using this helper when testing the `ElementBreadcrumbs` component discovered that when we scrolled the breadcrumbs we caused _over 70 DOM mutations_ (!), which is what lead to the creation of this helper. It's a great way to verify that we're not doing work that can be avoided.
71
72```
73it('does not mutate the DOM when we scroll the component', async () => {
74  const component = new MyComponent();
75  component.data = {...}
76  renderElementIntoDOM(component);
77
78  await withNoMutations(component.shadowRoot, shadowRoot => {
79    // Imagine there's code here to cause the component to scroll
80  })
81})
82```
83
84The above test will fail if any DOM mutations are detected.
85
86