lighthouse 9.5.0-dev.20220613 → 9.5.0-dev.20220616
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.
- package/changelog.md +4 -4
- package/dist/report/bundle.esm.js +6 -2
- package/dist/report/flow.js +1 -1
- package/dist/report/standalone.js +1 -1
- package/lighthouse-core/fraggle-rock/user-flow.js +55 -5
- package/package.json +1 -1
- package/report/renderer/dom.js +6 -2
- package/report/test/renderer/dom-test.js +18 -2
|
@@ -108,13 +108,64 @@ class UserFlow {
|
|
|
108
108
|
*/
|
|
109
109
|
async navigate(requestor, stepOptions) {
|
|
110
110
|
if (this.currentTimespan) throw new Error('Timespan already in progress');
|
|
111
|
+
if (this.currentNavigation) throw new Error('Navigation already in progress');
|
|
111
112
|
|
|
112
113
|
const options = this._getNextNavigationOptions(stepOptions);
|
|
113
114
|
const gatherResult = await navigationGather(requestor, options);
|
|
114
115
|
|
|
115
116
|
this._addGatherStep(gatherResult, options);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* This is an alternative to `navigate()` that can be used to analyze a navigation triggered by user interaction.
|
|
121
|
+
* For more on user triggered navigations, see https://github.com/GoogleChrome/lighthouse/blob/master/docs/user-flows.md#triggering-a-navigation-via-user-interactions.
|
|
122
|
+
*
|
|
123
|
+
* @param {StepOptions=} stepOptions
|
|
124
|
+
*/
|
|
125
|
+
async startNavigation(stepOptions) {
|
|
126
|
+
/** @type {(value: () => void) => void} */
|
|
127
|
+
let completeSetup;
|
|
128
|
+
/** @type {(value: any) => void} */
|
|
129
|
+
let rejectDuringSetup;
|
|
130
|
+
|
|
131
|
+
// This promise will resolve once the setup is done
|
|
132
|
+
// and Lighthouse is waiting for a page navigation to be triggered.
|
|
133
|
+
const navigationSetupPromise = new Promise((resolve, reject) => {
|
|
134
|
+
completeSetup = resolve;
|
|
135
|
+
rejectDuringSetup = reject;
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
// The promise in this callback will not resolve until `continueNavigation` is invoked,
|
|
139
|
+
// because `continueNavigation` is passed along to `navigateSetupPromise`
|
|
140
|
+
// and extracted into `continueAndAwaitResult` below.
|
|
141
|
+
const navigationResultPromise = this.navigate(
|
|
142
|
+
() => new Promise(continueNavigation => completeSetup(continueNavigation)),
|
|
143
|
+
stepOptions
|
|
144
|
+
).catch(err => {
|
|
145
|
+
if (this.currentNavigation) {
|
|
146
|
+
// If the navigation already started, re-throw the error so it is emitted when `navigationResultPromise` is awaited.
|
|
147
|
+
throw err;
|
|
148
|
+
} else {
|
|
149
|
+
// If the navigation has not started, reject the `navigationSetupPromise` so the error throws when it is awaited in `startNavigation`.
|
|
150
|
+
rejectDuringSetup(err);
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
const continueNavigation = await navigationSetupPromise;
|
|
116
155
|
|
|
117
|
-
|
|
156
|
+
async function continueAndAwaitResult() {
|
|
157
|
+
continueNavigation();
|
|
158
|
+
await navigationResultPromise;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
this.currentNavigation = {continueAndAwaitResult};
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
async endNavigation() {
|
|
165
|
+
if (this.currentTimespan) throw new Error('Timespan already in progress');
|
|
166
|
+
if (!this.currentNavigation) throw new Error('No navigation in progress');
|
|
167
|
+
await this.currentNavigation.continueAndAwaitResult();
|
|
168
|
+
this.currentNavigation = undefined;
|
|
118
169
|
}
|
|
119
170
|
|
|
120
171
|
/**
|
|
@@ -122,6 +173,7 @@ class UserFlow {
|
|
|
122
173
|
*/
|
|
123
174
|
async startTimespan(stepOptions) {
|
|
124
175
|
if (this.currentTimespan) throw new Error('Timespan already in progress');
|
|
176
|
+
if (this.currentNavigation) throw new Error('Navigation already in progress');
|
|
125
177
|
|
|
126
178
|
const options = {...this.options, ...stepOptions};
|
|
127
179
|
const timespan = await startTimespanGather(options);
|
|
@@ -130,14 +182,13 @@ class UserFlow {
|
|
|
130
182
|
|
|
131
183
|
async endTimespan() {
|
|
132
184
|
if (!this.currentTimespan) throw new Error('No timespan in progress');
|
|
185
|
+
if (this.currentNavigation) throw new Error('Navigation already in progress');
|
|
133
186
|
|
|
134
187
|
const {timespan, options} = this.currentTimespan;
|
|
135
188
|
const gatherResult = await timespan.endTimespanGather();
|
|
136
189
|
this.currentTimespan = undefined;
|
|
137
190
|
|
|
138
191
|
this._addGatherStep(gatherResult, options);
|
|
139
|
-
|
|
140
|
-
return gatherResult;
|
|
141
192
|
}
|
|
142
193
|
|
|
143
194
|
/**
|
|
@@ -145,13 +196,12 @@ class UserFlow {
|
|
|
145
196
|
*/
|
|
146
197
|
async snapshot(stepOptions) {
|
|
147
198
|
if (this.currentTimespan) throw new Error('Timespan already in progress');
|
|
199
|
+
if (this.currentNavigation) throw new Error('Navigation already in progress');
|
|
148
200
|
|
|
149
201
|
const options = {...this.options, ...stepOptions};
|
|
150
202
|
const gatherResult = await snapshotGather(options);
|
|
151
203
|
|
|
152
204
|
this._addGatherStep(gatherResult, options);
|
|
153
|
-
|
|
154
|
-
return gatherResult;
|
|
155
205
|
}
|
|
156
206
|
|
|
157
207
|
/**
|
package/package.json
CHANGED
package/report/renderer/dom.js
CHANGED
|
@@ -133,9 +133,13 @@ export class DOM {
|
|
|
133
133
|
const element = this.createElement('span');
|
|
134
134
|
|
|
135
135
|
for (const segment of Util.splitMarkdownLink(text)) {
|
|
136
|
+
const processedSegment = segment.text.includes('`') ?
|
|
137
|
+
this.convertMarkdownCodeSnippets(segment.text) :
|
|
138
|
+
segment.text;
|
|
139
|
+
|
|
136
140
|
if (!segment.isLink) {
|
|
137
141
|
// Plain text segment.
|
|
138
|
-
element.append(
|
|
142
|
+
element.append(processedSegment);
|
|
139
143
|
continue;
|
|
140
144
|
}
|
|
141
145
|
|
|
@@ -151,7 +155,7 @@ export class DOM {
|
|
|
151
155
|
const a = this.createElement('a');
|
|
152
156
|
a.rel = 'noopener';
|
|
153
157
|
a.target = '_blank';
|
|
154
|
-
a.
|
|
158
|
+
a.append(processedSegment);
|
|
155
159
|
this.safelySetHref(a, url.href);
|
|
156
160
|
element.append(a);
|
|
157
161
|
}
|
|
@@ -96,6 +96,21 @@ describe('DOM', () => {
|
|
|
96
96
|
'and some text afterwards.', 'link with spaces in brackets');
|
|
97
97
|
});
|
|
98
98
|
|
|
99
|
+
it('correctly converts code snippets', () => {
|
|
100
|
+
let result = dom.convertMarkdownLinkSnippets(
|
|
101
|
+
'Some `code`. [Learn more](http://example.com).');
|
|
102
|
+
assert.equal(result.innerHTML,
|
|
103
|
+
'<span>Some <code>code</code>. </span>' +
|
|
104
|
+
'<a rel="noopener" target="_blank" href="http://example.com/">Learn more</a>.');
|
|
105
|
+
|
|
106
|
+
result = dom.convertMarkdownLinkSnippets(
|
|
107
|
+
'[link with `code`](https://example.com/foo) and some text afterwards.');
|
|
108
|
+
assert.equal(result.innerHTML,
|
|
109
|
+
'<a rel="noopener" target="_blank" href="https://example.com/foo">' +
|
|
110
|
+
'<span>link with <code>code</code></span>' +
|
|
111
|
+
'</a> and some text afterwards.', 'link with code snippet inside');
|
|
112
|
+
});
|
|
113
|
+
|
|
99
114
|
it('handles invalid urls', () => {
|
|
100
115
|
const text = 'Text has [bad](https:///) link.';
|
|
101
116
|
assert.throws(() => {
|
|
@@ -120,8 +135,9 @@ describe('DOM', () => {
|
|
|
120
135
|
const text = 'Ensuring `<td>` cells using the `[headers]` are good. ' +
|
|
121
136
|
'[Learn more](https://dequeuniversity.com/rules/axe/3.1/td-headers-attr).';
|
|
122
137
|
const result = dom.convertMarkdownLinkSnippets(text);
|
|
123
|
-
assert.equal(result.innerHTML,
|
|
124
|
-
'
|
|
138
|
+
assert.equal(result.innerHTML,
|
|
139
|
+
'<span>Ensuring <code><td></code> cells using the <code>[headers]</code> are ' +
|
|
140
|
+
'good. </span><a rel="noopener" target="_blank" href="https://dequeuniversity.com/rules/axe/3.1/td-headers-attr">Learn more</a>.');
|
|
125
141
|
});
|
|
126
142
|
|
|
127
143
|
it('appends utm params to the URLs with https://developers.google.com origin', () => {
|