chrome-devtools-frontend 1.0.1545096 → 1.0.1547147

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (124) hide show
  1. package/docs/styleguide/ux/styles.md +1 -1
  2. package/eslint.config.mjs +1 -1
  3. package/front_end/Images/src/arrow-down.svg +8 -1
  4. package/front_end/Images/src/arrow-up.svg +8 -1
  5. package/front_end/core/host/AidaClient.ts +1 -1
  6. package/front_end/core/host/InspectorFrontendHostAPI.ts +0 -1
  7. package/front_end/core/host/UserMetrics.ts +0 -5
  8. package/front_end/core/platform/HostRuntime.ts +18 -0
  9. package/front_end/core/platform/KeyboardUtilities.ts +2 -2
  10. package/front_end/core/platform/StringUtilities.ts +1 -1
  11. package/front_end/core/platform/api/HostRuntime.ts +20 -0
  12. package/front_end/core/platform/api/api.ts +7 -0
  13. package/front_end/core/platform/browser/HostRuntime.ts +14 -0
  14. package/front_end/core/platform/browser/browser.ts +7 -0
  15. package/front_end/core/platform/node/HostRuntime.ts +13 -0
  16. package/front_end/core/platform/node/node.ts +7 -0
  17. package/front_end/core/platform/platform.ts +2 -2
  18. package/front_end/core/sdk/SourceMapScopesInfo.ts +141 -23
  19. package/front_end/core/sdk/Target.ts +5 -14
  20. package/front_end/core/sdk/TargetManager.ts +26 -4
  21. package/front_end/core/sdk/sdk-meta.ts +62 -0
  22. package/front_end/devtools_compatibility.js +0 -1
  23. package/front_end/entrypoints/main/MainImpl.ts +2 -2
  24. package/front_end/foundation/Universe.ts +2 -2
  25. package/front_end/generated/Deprecation.ts +7 -0
  26. package/front_end/generated/InspectorBackendCommands.ts +1 -1
  27. package/front_end/generated/SupportedCSSProperties.js +4 -2
  28. package/front_end/generated/protocol.ts +3 -2
  29. package/front_end/models/ai_assistance/AiConversation.ts +188 -0
  30. package/front_end/models/ai_assistance/AiHistoryStorage.ts +1 -172
  31. package/front_end/models/ai_assistance/ConversationHandler.ts +5 -5
  32. package/front_end/models/ai_assistance/agents/AiAgent.ts +1 -3
  33. package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +6 -2
  34. package/front_end/models/ai_assistance/agents/StylingAgent.snapshot.txt +1 -1
  35. package/front_end/models/ai_assistance/agents/StylingAgent.ts +3 -9
  36. package/front_end/models/ai_assistance/ai_assistance.ts +2 -0
  37. package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.snapshot.txt +313 -313
  38. package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.ts +8 -6
  39. package/front_end/models/ai_assistance/performance/AICallTree.snapshot.txt +33 -33
  40. package/front_end/models/ai_assistance/performance/AICallTree.ts +9 -3
  41. package/front_end/models/bindings/CSSWorkspaceBinding.ts +5 -3
  42. package/front_end/models/bindings/SASSSourceMapping.ts +6 -4
  43. package/front_end/models/cpu_profile/CPUProfileDataModel.ts +10 -7
  44. package/front_end/models/crux-manager/CrUXManager.ts +7 -4
  45. package/front_end/models/issues_manager/GenericIssue.ts +12 -9
  46. package/front_end/models/javascript_metadata/NativeFunctions.js +4 -0
  47. package/front_end/models/trace/handlers/SamplesHandler.ts +3 -0
  48. package/front_end/models/trace/helpers/Trace.ts +13 -0
  49. package/front_end/models/trace/types/TraceEvents.ts +2 -1
  50. package/front_end/models/trace_source_maps_resolver/SourceMapsResolver.ts +29 -0
  51. package/front_end/models/workspace/IgnoreListManager.ts +1 -2
  52. package/front_end/models/workspace/UISourceCode.ts +50 -0
  53. package/front_end/panels/ai_assistance/AiAssistancePanel.ts +9 -9
  54. package/front_end/panels/ai_assistance/ai_assistance-meta.ts +8 -0
  55. package/front_end/panels/ai_assistance/components/ChatView.ts +2 -2
  56. package/front_end/panels/animation/AnimationTimeline.ts +0 -8
  57. package/front_end/panels/application/FrameDetailsView.ts +8 -8
  58. package/front_end/panels/application/components/StackTrace.ts +84 -85
  59. package/front_end/panels/common/AiCodeGenerationTeaser.ts +80 -0
  60. package/front_end/panels/common/common.ts +2 -1
  61. package/front_end/panels/console/ConsolePrompt.ts +3 -1
  62. package/front_end/panels/console/ConsoleViewport.ts +1 -2
  63. package/front_end/panels/elements/ElementIssueUtils.ts +2 -2
  64. package/front_end/panels/elements/StylePropertyTreeElement.ts +23 -19
  65. package/front_end/panels/elements/StylesSidebarPane.ts +1 -1
  66. package/front_end/panels/elements/cssValueTraceView.css +1 -1
  67. package/front_end/panels/elements/elements-meta.ts +1 -0
  68. package/front_end/panels/explain/components/ConsoleInsight.ts +44 -57
  69. package/front_end/panels/explain/components/consoleInsight.css +46 -1
  70. package/front_end/panels/layer_viewer/LayerTreeOutline.ts +1 -2
  71. package/front_end/panels/mobile_throttling/NetworkThrottlingSelector.ts +19 -0
  72. package/front_end/panels/network/RequestConditionsDrawer.ts +54 -24
  73. package/front_end/panels/network/networkLogView.css +11 -0
  74. package/front_end/panels/network/networkTimingTable.css +8 -6
  75. package/front_end/panels/network/requestConditionsDrawer.css +10 -1
  76. package/front_end/panels/profiler/ProfilesPanel.ts +1 -2
  77. package/front_end/panels/settings/KeybindsSettingsTab.ts +20 -21
  78. package/front_end/panels/sources/CoveragePlugin.ts +5 -5
  79. package/front_end/panels/sources/Plugin.ts +1 -1
  80. package/front_end/panels/sources/ProfilePlugin.ts +22 -14
  81. package/front_end/panels/sources/UISourceCodeFrame.ts +2 -1
  82. package/front_end/panels/sources/sources-meta.ts +0 -62
  83. package/front_end/panels/timeline/README.md +1 -9
  84. package/front_end/panels/timeline/ThreadAppender.ts +0 -7
  85. package/front_end/panels/timeline/TimelinePanel.ts +1 -1
  86. package/front_end/panels/timeline/TimelineUIUtils.ts +2 -0
  87. package/front_end/panels/timeline/components/ExportTraceOptions.ts +15 -1
  88. package/front_end/panels/timeline/components/LiveMetricsView.ts +37 -1
  89. package/front_end/panels/timeline/components/exportTraceOptions.css +11 -2
  90. package/front_end/third_party/chromium/README.chromium +1 -1
  91. package/front_end/ui/components/markdown_view/MarkdownLinksMap.ts +1 -0
  92. package/front_end/ui/legacy/ARIAUtils.ts +2 -2
  93. package/front_end/ui/legacy/ActionRegistration.ts +11 -0
  94. package/front_end/ui/legacy/SoftDropDown.ts +2 -2
  95. package/front_end/ui/legacy/TextPrompt.ts +3 -2
  96. package/front_end/ui/legacy/Treeoutline.ts +2 -1
  97. package/front_end/ui/legacy/UIUtils.ts +11 -10
  98. package/front_end/ui/legacy/Widget.ts +3 -2
  99. package/front_end/ui/legacy/components/data_grid/DataGrid.ts +2 -2
  100. package/front_end/ui/legacy/components/perf_ui/LineLevelProfile.ts +62 -39
  101. package/front_end/ui/legacy/components/perf_ui/OverviewGrid.ts +1 -1
  102. package/front_end/ui/legacy/components/perf_ui/TimelineGrid.ts +2 -2
  103. package/front_end/ui/legacy/components/source_frame/SourceFrame.ts +2 -7
  104. package/front_end/ui/legacy/components/utils/JSPresentationUtils.ts +1 -2
  105. package/front_end/ui/legacy/inspectorCommon.css +2 -2
  106. package/front_end/ui/legacy/legacy.ts +2 -0
  107. package/front_end/ui/visual_logging/KnownContextValues.ts +1 -0
  108. package/package.json +1 -1
  109. package/front_end/panels/explain/components/consoleInsightSourcesList.css +0 -51
  110. package/front_end/ui/components/docs/README.md +0 -6
  111. package/front_end/ui/components/docs/building-ui-documentation/ComponentEvents.md +0 -54
  112. package/front_end/ui/components/docs/building-ui-documentation/ComponentPerformance.md +0 -136
  113. package/front_end/ui/components/docs/building-ui-documentation/CreatingComponents.md +0 -242
  114. package/front_end/ui/components/docs/building-ui-documentation/README.md +0 -23
  115. package/front_end/ui/components/docs/building-ui-documentation/StylingComponents.md +0 -66
  116. package/front_end/ui/components/docs/building-ui-documentation/TestingComponents.md +0 -111
  117. package/front_end/ui/components/docs/component_docs.ts +0 -24
  118. package/front_end/ui/components/docs/component_docs_styles.css +0 -53
  119. package/front_end/ui/components/docs/create_breadcrumbs.ts +0 -44
  120. package/front_end/ui/components/docs/slider/basic.html +0 -20
  121. package/front_end/ui/components/docs/switch/basic.html +0 -20
  122. /package/front_end/models/issues_manager/descriptions/{genericFormAriaLabelledByToNonExistingId.md → genericFormAriaLabelledByToNonExistingIdError.md} +0 -0
  123. /package/front_end/models/issues_manager/descriptions/{genericFormLabelHasNeitherForNorNestedInput.md → genericFormLabelHasNeitherForNorNestedInputError.md} +0 -0
  124. /package/front_end/{core/platform → ui/legacy}/DOMUtilities.ts +0 -0
@@ -1,242 +0,0 @@
1
- # Creating components
2
-
3
- A component is created by extending `HTMLElement`. The name of the component should match the filename. The component should be exported by the file.
4
-
5
- ```ts
6
- // ElementBreadcrumbs.ts
7
- export class ElementBreadcrumbs extends HTMLElement {
8
- }
9
- ```
10
-
11
- ## Where to put components
12
-
13
- If the component is for a specific panel, and not expected to be re-usable, it should be created within the panel's folder, within a sub-directory of `components`:
14
-
15
- ```
16
- front_end/panels/elements/components/ElementsBreadcrumbs.ts
17
- ```
18
-
19
- If a component is designed to be re-usable, it should live in `front_end/ui/components`, in its own folder. That folder also contains an entrypoint, along with files for the component's definition.
20
-
21
- ```
22
- front_end/ui/components/button/button.ts // entrypoint
23
- front_end/ui/components/button/Button.ts // component definition
24
- ```
25
-
26
- ## Defining and naming a component
27
-
28
- All custom elements **must** contain a hyphen. Use `devtools-` as the prefix. Use `customElements.define` to define the component and register it with the browser:
29
-
30
- ```ts
31
- customElements.define('devtools-elements-breadcrumbs', ElementsBreadcrumbs);
32
- ```
33
-
34
- And finally we tell TypeScript that this component exists:
35
-
36
- ```ts
37
- declare global {
38
- interface HTMLElementTagNameMap {
39
- 'devtools-elements-breadcrumbs': ElementsBreadcrumbs;
40
- }
41
- }
42
- ```
43
-
44
- By doing this, TypeScript understands that `document.querySelector('devtools-elements-breadcrumbs')` returns an `ElementsBreadcrumbs` instance.
45
-
46
- We use lit-analyzer in a lint state to verify that component definitions are imported where the component is used.
47
-
48
- ## Creating a shadow root
49
-
50
- Each component gets its own Shadow Root to ensure that styles and events that occur within it are encapsulated and do not leak out:
51
-
52
- ```ts
53
- export class ElementsBreadcrumbs extends HTMLElement {
54
- readonly #shadow = this.attachShadow({mode: 'open'});
55
- }
56
- ```
57
-
58
- > We set the mode to `open` so it's open to inspection via DevTools. [See this MDN explainer](https://developer.mozilla.org/en-US/docs/Web/API/ShadowRoot/mode) for more details.
59
-
60
- ## Rendering a component
61
-
62
- Each component defines a `#render` method which is responsible for invoking LitHtml and having the component render HTML into the DOM.
63
-
64
- > The `#` symbol indicates a [private class method](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/Private_class_fields).
65
-
66
- The `#render` method calls `LitHtml.render`, building up a template with `LitHtml.html`:
67
-
68
- ```ts
69
- LitHtml.render(html`<p>hello world!</p>`, this.#shadow, {host: this});
70
- ```
71
-
72
- The third argument (`{host: this}`) tells LitHtml to automatically bind event listeners to the component. This can save you some painful debugging where event listeners do not have the right `this` reference; so we enforce the use of `{host: this}` via a custom ESLint rule.
73
-
74
- There is unfortunately a [clang-format bug](crbug.com/1079231) which makes its auto-formatting of LitHtml templates very unreadable, so we usually disable clang-format round the call:
75
-
76
- ```ts
77
- // clang-format off
78
- LitHtml.render(...)
79
- // clang-format on
80
- ```
81
-
82
- ## Scheduled and batched rendering
83
-
84
- To have your component render, you could manually call `this.#render()`. However, if you were to have multiple updates to a component (perhaps some values it's passed get changed), we want to avoid having multiple renders where possible and instead batch them.
85
-
86
- We can use the `ScheduledRender` helper (`front_end/ui/components/helpers/scheduled-render.ts`) to achieve this. Rather than call `this.#render()` directly, you instead call the scheduler:
87
-
88
- ```ts
89
- void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#render);
90
- ```
91
-
92
- > `scheduleRender` returns a promise; we use the `void` keyword to instruct TypeScript that we are purposefully not using `await` to wait for the promise to resolve. When scheduling a render it's most common to "fire and forget".
93
-
94
- To summarise, most components start off life looking like:
95
-
96
- ```ts
97
- export class ElementsBreadcrumbs extends HTMLElement {
98
- readonly #shadow = this.attachShadow({mode: 'open'});
99
-
100
- #render(): void {
101
- LitHtml.render(html``, this.#shadow, {host:this});
102
- }
103
- }
104
- ```
105
-
106
- ## Triggering a render
107
-
108
- One of the most important aspects to understand about our component system is that **rendering does not happen automatically**.
109
-
110
- To ensure we trigger a render once the component is added to the DOM, we can define [`connectedCallback`](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements#:~:text=lifecycle.%20For%20example%2C-,connectedCallback,-is%20invoked%20each):
111
-
112
- ```ts
113
- export class ElementsBreadcrumbs extends HTMLElement {
114
- readonly #shadow = this.attachShadow({mode: 'open'});
115
-
116
- connectedCallback(): void {
117
- void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#render);
118
- }
119
-
120
- #render(): void {
121
- LitHtml.render(html``, this.#shadow, {host:this});
122
- }
123
- }
124
- ```
125
-
126
- ## Passing data into a component
127
-
128
- Most of our components will require data that is passed into them. For example, `ElementsBreadcrumbs` takes in an array of `DOMNode` objects.
129
-
130
- To provide a component some data, we define a `data` setter. This setter takes an object with any data the component requires. This object should have a TypeScript interface defined for it:
131
-
132
- ```ts
133
- export interface ElementsBreadcrumbsData {
134
- selectedNode: DOMNode|null;
135
- crumbs: DOMNode[];
136
- }
137
-
138
- export class ElementsBreadcrumbs extends HTMLElement {
139
- // ...
140
- #crumbs: DOMNode[] = [];
141
- #selectedNode: DOMNode|null = null;
142
-
143
- set data(data: ElementsBreadcrumbsData) {
144
- this.#crumbs = data.crumbs;
145
- this.#selectedNode = data.selectedNode;
146
- void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#render);
147
- }
148
- }
149
- ```
150
-
151
- ## Rendering components
152
-
153
- Now we know how to create components that can take data, let's render them!
154
-
155
- ### From a DevTools Widget
156
-
157
- If you are rendering a component from the DevTools widget system, you should instantiate the component, pass any `data` to it, and then append it into the DOM:
158
-
159
- ```ts
160
- // Within a Widget
161
- const breadcrumbs = new ElementsBreadcrumbs();
162
- breadcrumbs.data = {selectedNode: node, crumbs: [...]};
163
- this.appendChild(breadcrumbs);
164
- ```
165
-
166
- ### From another component
167
-
168
- If you are rendering a component from within another component, import the module defining it and render within the call to `LitHtml.html`:
169
-
170
- ```ts
171
- // Within some component
172
- LitHtml.render(html`
173
- <devtools-elements-breadcrumbs></devtools-elements-breadcrumbs>
174
- `, this.#shadow, {host: this});
175
- ```
176
-
177
- To pass data, we use [LitHtml's dot syntax](https://lit.dev/docs/templates/expressions/#property-expressions) to set the `data` property (and invoke our `set data` setter):
178
-
179
- ```ts
180
- // Within some component
181
- LitHtml.render(html`
182
- <devtools-elements-breadcrumbs .data=${{
183
- selectedNode: node,
184
- crumbs: [...],
185
- }}>
186
- </devtools-elements-breadcrumbs>
187
- `, this.#shadow, {host: this});
188
- ```
189
-
190
- ## Performance concerns with data passing
191
-
192
- The approach of `set data(data)` was chosen because:
193
-
194
- 1. It requires few lines of code.
195
- 2. It provides some form of type safety via the `as FooData` check.
196
- 3. At the time we didn't have a solution for scheduled and batched renders, and didn't want multiple setters to trigger multiple unnecessary renders.
197
-
198
- However, using `set data(data)` does come with some negative performance costs:
199
-
200
- 1. LitHtml will always think the value has changed, because it's an object. If a component renders twice with `.data=${{name: 'Jack'}}`, Lit will think that the value has changed because it's a new object, even though we can see it's holding the same data.
201
- 2. This approach causes these objects to be created (and subsequently garbage collected) on/after each render.
202
-
203
- For most components in DevTools, these trade-offs are acceptable, and we prefer the type-safety of `set data` and take the usually imperceivable performance hit. However, in rare circumstances, this performance hit is noticeable. A good example of this is in Performance Insights, where we have to constantly re-render components as the user scrolls through their performance timeline. We noticed that this caused a large amount of garbage collection from all the objects being created per-render and then immediately disposed.
204
-
205
- For these situations, we can instead move to an approach where we set properties individually. We still define the interface as before, and then define an individual setter for each property:
206
-
207
- ```ts
208
- interface ElementsBreadcrumbsData {
209
- selectedNode: DOMNode|null;
210
- crumbs: DOMNode[];
211
- }
212
-
213
- class ElementsBreadcrumbs extends HTMLElement {
214
- #crumbs: DOMNode[] = [];
215
- #selectedNode: DOMNode|null = null;
216
-
217
- set crumbs(crumbs: ElementsBreadcrumbsData['crumbs']) {
218
- this.#crumbs = crumbs;
219
- void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#render);
220
- }
221
-
222
- set selectedNode(selectedNode: ElementsBreadcrumbsData['selectedNode']) {
223
- this.#selectedNode = selectedNode;
224
- void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#render);
225
- }
226
- }
227
- ```
228
-
229
- Rendering this component within another Lit component would now be done like so:
230
-
231
- ```ts
232
- // Within some component
233
- LitHtml.render(html`
234
- <devtools-elements-breadcrumbs .crumbs=${[...]} .selectedNode=${node}>
235
- </devtools-elements-breadcrumbs>
236
- `, this.#shadow, {host: this});
237
- ```
238
-
239
- This solution is more performant, but less type-safe as TypeScript has no means of checking those values. This is something we may rectify using the `as` pattern, but for now it's preferred to use the `set data` method by default.
240
-
241
-
242
-
@@ -1,23 +0,0 @@
1
- # Building UI elements in DevTools
2
-
3
- This is the documentation containing all the information you need to be able to build UI in DevTools and get familiar with our front-end stack.
4
-
5
- Note that this documentation is a work in progress as it is migrated from the [original Google Doc](https://docs.google.com/document/d/1Gwd-w7LoW1qnWu3uku438-MQ82m4AinKDIdy9z3fl3Q/edit?resourcekey=0-vxHqiKAvfJ4JAOj4bZ4EFA#). crbug.com/1344124 tracks this work.
6
-
7
- ## Table of Contents
8
-
9
- 1. [Creating components](./CreatingComponents.md)
10
- 1. [Styling components](./StylingComponents.md)
11
- 1. [Component performance](./ComponentPerformance.md)
12
- 1. [Testing components](./TestingComponents.md)
13
- 1. [Components and events](./ComponentEvents.md)
14
-
15
- ## FAQs
16
-
17
- > Wasn't this a google doc before?
18
-
19
- Yes. The original version of this documentation was a publicly accessible Google Doc. However, keeping the documentation apart from the code was a challenge, along with the fact that Docs aren't the best for dealing with lots of code. That motivated the change to move the documentation into the repository, hopefully helping it keep up to date and still remaining public.
20
-
21
- > What should I do if I want to make a change?
22
-
23
- Please send a CL and ask jacktfranklin@ to review it. If you're not sure on the change, feel free to ping jacktfranklin@ to discuss.
@@ -1,66 +0,0 @@
1
- # Styling Components
2
-
3
- Components are styled by a CSS file that is co-located next to the TypeScript source file. The only difference in file name is the extension and that for CSS files, the first letter is lowercase:
4
-
5
- ```
6
- - ElementsBreadcrumbs.ts
7
- - elementsBreadcrumbs.css
8
- ```
9
-
10
- To import this file you use a regular `import` statement, and import the filename with `.js` appended:
11
-
12
- ```ts
13
- import elementsBreadcrumbsStyles from './elementsBreadcrumbs.css.js';
14
- ```
15
-
16
- As part of the build tool step, each CSS file is converted into a JS file that exports a `CSSInJS` string.
17
-
18
- ## `BUILD.gn` changes
19
-
20
- Use the `generate_css` action (`scripts/build/ninja/generate_css.gni`) to declare stylesheets:
21
-
22
- ```gn
23
- import("scripts/build/ninja/generate_css.gni") // Edit path correctly: this must be relative
24
-
25
- generate_css("css_files") {
26
- sources = [ "elementsBreadcrumbs.css"]
27
- }
28
- ```
29
-
30
- And then add `:css_files` as a dependency to the `devtools_entrypoint`:
31
-
32
- ```gn
33
- devtools_entrypoint("bundle") {
34
- deps = [ ":css_files" , "..."]
35
- }
36
- ```
37
-
38
- ## Using the stylesheet
39
-
40
- Importing the stylesheet is not enough to have it apply to the component's ShadowDOM, it must be inserted into
41
- a `<style>` tag in the template. The `#render` method is the best place for this:
42
-
43
- ```ts
44
- #render() {
45
- render(html`
46
- <style>${elementsBreadcrumbsStyles}</style>
47
- ...
48
- `, this.#shadow, {host: this});
49
- }
50
- ```
51
-
52
- ## Tips for writing CSS.
53
-
54
- Use `:host` to style the component itself. By default elements are `display: inline`. Often it can be useful to set `display: block`.
55
-
56
- Remember to use theme colors (`var(--sys-color-on-surface)`) when styling elements to ensure consistency across DevTools.
57
-
58
- If you want your component to have its colors configurable by users, consider defining `--override` variables. In your component's CSS, you would have something like:
59
-
60
- ```css
61
- :host {
62
- color: var(--override-custom-color, var(--sys-color-on-surface));
63
- }
64
- ```
65
-
66
- This allows someone to define that `--override-custom-color` variable, but also ensures if it isn't defined that the default `color-text-primary` will be used. **Be careful with this!** We try to ensure consistent colors across DevTools; so most of the time you shouldn't allow configurable colors and should use the correct theme variables.
@@ -1,111 +0,0 @@
1
- # Testing components
2
-
3
- One of the main ways that we test our components is with thorough unit tests. In these tests we render the component into the page, and query the DOM to assert that the component behaves and outputs the HTML as we expect.
4
-
5
- ## Initialising a component in a unit test
6
-
7
- Within a unit test, you can create the component by initialising it and calling any methods on it to set data:
8
-
9
- ```ts
10
- it('outputs the user name onto the screen', async () => {
11
- const component = new DummyComponent();
12
- component.data = {name: 'Jack' /* whatever data the component needs */}
13
- })
14
- ```
15
-
16
- Now we have a component, we need to render it into the page. You can use the `renderElementIntoDOM` helper method, which is defined in `test/unittests/front_end/helpers/DOMHelpers.js`. It is recommended to use this helper because it will automatically remove the component from the page after the test is done. It is important that the DOM is cleaned after each test to ensure that tests don't inadvertently change the behaviour of future tests.
17
-
18
- ```ts
19
- import {
20
- renderElementIntoDOM,
21
- // adjust this path as required depending on the location of your test file
22
- } from '../../helpers/DOMHelpers.js';
23
-
24
- it('outputs the user name onto the screen', async () => {
25
- const component = new DummyComponent();
26
- component.data = {name: 'Jack' /* whatever data the component needs */}
27
- renderElementIntoDOM(component)
28
- })
29
- ```
30
-
31
- ## Waiting for the component to render
32
-
33
- If your component is implemented using the scheduled renderer, you will need to wait for the render to be complete before continuing with the test. Otherwise you may try to query the DOM before the component has finished rendering.
34
-
35
- ```ts
36
- import * as RenderCoordinator from '../../../../../front_end/ui/components/render_coordinator/render_coordinator.js';
37
-
38
- it('outputs the user name onto the screen', async () => {
39
- const component = new DummyComponent();
40
- component.data = {name: 'Jack' /* whatever data the component needs */}
41
- renderElementIntoDOM(component);
42
- await RenderCoordinator.done(); // Ensure the component is rendered onto the page.
43
- })
44
- ```
45
-
46
- ## Querying the component
47
-
48
- Most of our components use the [shadow DOM](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_shadow_DOM) to render their content. Therefore when querying the contents of the component in a test we need to query the contents of its shadow DOM.
49
-
50
- The shadow DOM for a component can be accessed via `component.shadowRoot`. In TypeScript, this is typed as `ShadowRoot | null`. We therefore have another helper in `DOMHelpers.js` that can check that the shadow root is available, and fail the test otherwise. This will also satisfy TypeScript that the shadow root is present, and avoids you having to continually guard against it being `null`:
51
-
52
- ```ts
53
- it('outputs the user name onto the screen', async () => {
54
- const component = new DummyComponent();
55
- component.data = {name: 'Jack' /* whatever data the component needs */}
56
- renderElementIntoDOM(component);
57
- await RenderCoordinator.done();
58
- assert.isNotNull(component.shadowRoot); // Check that the Shadow Root exists.
59
- })
60
- ```
61
-
62
- Now we are ready to query the DOM and make assertions! You can use the regular DOM APIs such as `querySelector` / `querySelectorAll`:
63
-
64
- ```ts
65
- it('outputs the user name onto the screen', async () => {
66
- const component = new DummyComponent();
67
- component.data = {name: 'Jack' /* whatever data the component needs */}
68
- renderElementIntoDOM(component);
69
- await RenderCoordinator.done();
70
- assert.isNotNull(component.shadowRoot);
71
- const name = component.shadowRoot.querySelector<HTMLElement>('span.name');
72
- })
73
- ```
74
-
75
- Note that by default TypeScript will type the result as `Element|null`. Sometimes it is useful to tell TypeScript more specifically what type of element you are expecting, as not all APIs (such as `textContent`) are available on the `Element` type.
76
-
77
- ## Ensuring queries returned elements
78
-
79
- Any DOM querying API could return back `null` if the element was not found. You can use the `assert.instanceOf` method from Chai to ensure that if the element was not found, the test fails. This also satisfies TypeScript and (much like with the shadow root check earlier) avoids you having to continually code against the element not being found.
80
-
81
-
82
- ```ts
83
- it('outputs the user name onto the screen', async () => {
84
- const component = new DummyComponent();
85
- component.data = {name: 'Jack' /* whatever data the component needs */}
86
- renderElementIntoDOM(component);
87
- await RenderCoordinator.done();
88
- assert.isNotNull(component.shadowRoot);
89
- const name = component.shadowRoot.querySelector<HTMLElement>('span.name');
90
- assert.instanceOf(name, HTMLSpanElement);
91
- })
92
- ```
93
-
94
- ## Asserting on the contents
95
-
96
- Now we have an element that exists, we can query for its contents and assert against them:
97
-
98
- ```ts
99
- it('outputs the user name onto the screen', async () => {
100
- const component = new DummyComponent();
101
- component.data = {name: 'Jack' /* whatever data the component needs */}
102
- renderElementIntoDOM(component);
103
- await RenderCoordinator.done();
104
- assert.isNotNull(component.shadowRoot);
105
- const name = component.shadowRoot.querySelector<HTMLElement>('span.name');
106
- assert.instanceOf(name, HTMLSpanElement);
107
- assert.strictEqual(name.innerText, 'Jack');
108
- })
109
- ```
110
-
111
- And with that, our basic unit test is written.
@@ -1,24 +0,0 @@
1
- // Copyright 2020 The Chromium Authors
2
- // Use of this source code is governed by a BSD-style license that can be
3
- // found in the LICENSE file.
4
-
5
- // Ensure all image variables are defined in the component docs.
6
- import '../../../Images/Images.js';
7
-
8
- import * as CreateBreadcrumbs from './create_breadcrumbs.js';
9
-
10
- CreateBreadcrumbs.init();
11
-
12
- // This can be used by tests to hide the UI elements that are part of the component docs interface.
13
- // E.g., this is useful for screenshot tests.
14
- window.addEventListener('hidecomponentdocsui', () => {
15
- for (const node of document.querySelectorAll<HTMLElement>('.component-docs-ui')) {
16
- node.style.display = 'none';
17
- }
18
- });
19
-
20
- window.addEventListener('showcomponentdocsui', () => {
21
- for (const node of document.querySelectorAll<HTMLElement>('.component-docs-ui')) {
22
- node.style.display = '';
23
- }
24
- });
@@ -1,53 +0,0 @@
1
- /*
2
- * Copyright 2021 The Chromium Authors
3
- * Use of this source code is governed by a BSD-style license that can be
4
- * found in the LICENSE file.
5
- */
6
-
7
- @import url('https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100..900;1,100..900&display=swap');
8
-
9
- body {
10
- margin: 0;
11
- padding: 0;
12
- }
13
-
14
- #index-page h1 {
15
- text-align: left;
16
- border-bottom: 1px solid var(--sys-color-divider);
17
- padding: 10px;
18
- width: 100%;
19
- margin-bottom: 10px;
20
- }
21
-
22
- .components-list {
23
- display: flex;
24
- flex-wrap: wrap;
25
- list-style: none;
26
- margin: 0;
27
- padding: 10px;
28
- }
29
-
30
- .components-list li {
31
- width: 20%;
32
- min-width: 150px;
33
- max-width: 300px;
34
- margin: 0 12px 12px 0;
35
- }
36
-
37
- .components-list a {
38
- display: block;
39
- font-size: 14px;
40
- padding: 10px;
41
- }
42
-
43
- .components-list a:link,
44
- .components-list a:visited {
45
- text-transform: capitalize;
46
- color: var(--sys-color-primary);
47
- text-decoration: none;
48
- box-shadow: var(--drop-shadow);
49
- }
50
-
51
- .components-list a:hover {
52
- box-shadow: var(--drop-shadow-depth-3);
53
- }
@@ -1,44 +0,0 @@
1
- // Copyright 2020 The Chromium Authors
2
- // Use of this source code is governed by a BSD-style license that can be
3
- // found in the LICENSE file.
4
- import * as Lit from '../../lit/lit.js';
5
-
6
- const {html} = Lit;
7
-
8
- export function init(): void {
9
- const container = document.createElement('ul');
10
- // clang-format off
11
- // eslint-disable-next-line @devtools/no-a-tags-in-lit
12
- Lit.render(html`
13
-
14
- <style>
15
- .docs-breadcrumbs {
16
- display: flex;
17
- list-style: none;
18
- position: fixed;
19
- background: rgb(255 255 255 / .8);
20
- padding: 5px;
21
- bottom: 0;
22
- left: 10px;
23
- width: 300px;
24
- }
25
-
26
- .docs-breadcrumbs li a {
27
- display: block;
28
- padding: 10px;
29
- font-size: 16px;
30
- }
31
-
32
- .docs-breadcrumbs span {
33
- font-size: 20px;
34
- }
35
- </style>
36
-
37
- <ul class="docs-breadcrumbs component-docs-ui">
38
- <li><a href="/">Index</a></li>
39
- <li><a href=".">All component examples</a></li>
40
- </ul>`, container);
41
- // clang-format on
42
-
43
- document.body.appendChild(container);
44
- }
@@ -1,20 +0,0 @@
1
- <!--
2
- Copyright 2024 The Chromium Authors
3
- Use of this source code is governed by a BSD-style license that can be
4
- found in the LICENSE file.
5
- -->
6
- <!DOCTYPE html>
7
- <html>
8
- <head>
9
- <meta charset="UTF-8" />
10
- <meta name="viewport" content="width=device-width" />
11
- <title>Basic Slider example</title>
12
- </head>
13
- <body>
14
-
15
- <div id="container">
16
- </div>
17
-
18
- <script type="module" src="./basic.js"></script>
19
- </body>
20
- </html>
@@ -1,20 +0,0 @@
1
- <!--
2
- Copyright 2024 The Chromium Authors
3
- Use of this source code is governed by a BSD-style license that can be
4
- found in the LICENSE file.
5
- -->
6
- <!DOCTYPE html>
7
- <html>
8
- <head>
9
- <meta charset="UTF-8" />
10
- <meta name="viewport" content="width=device-width" />
11
- <title>Basic Switch example</title>
12
- </head>
13
- <body>
14
-
15
- <div id="container">
16
- </div>
17
-
18
- <script type="module" src="./basic.js"></script>
19
- </body>
20
- </html>