-
Notifications
You must be signed in to change notification settings - Fork 9.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
report(flow): embedded lighthouse report #12989
Changes from all commits
a13de8b
ca93fcd
9bb1a73
6d4c305
413dac6
732ef15
c714711
3036cb3
31f717a
50acb69
8932b44
5087757
c1ef57b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
/** | ||
* @license Copyright 2021 The Lighthouse Authors. All Rights Reserved. | ||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 | ||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. | ||
*/ | ||
|
||
import {FunctionComponent} from 'preact'; | ||
import {useEffect, useLayoutEffect, useRef} from 'preact/hooks'; | ||
import {useCurrentLhr, useHashParam} from '../util'; | ||
import {useReportRenderer} from './report-renderer'; | ||
|
||
/** | ||
* The default behavior of anchor links is not compatible with the flow report's hash navigation. | ||
* This function converts any anchor links under the provided element to a flow report link. | ||
* e.g. <a href="#link"> -> <a href="#index=0&anchor=link"> | ||
*/ | ||
export function convertChildAnchors(element: HTMLElement, index: number) { | ||
const links = element.querySelectorAll('a') as NodeListOf<HTMLAnchorElement>; | ||
for (const link of links) { | ||
// Check if the link destination is in the report. | ||
const currentUrl = new URL(location.href); | ||
currentUrl.hash = ''; | ||
currentUrl.search = ''; | ||
const linkUrl = new URL(link.href); | ||
linkUrl.hash = ''; | ||
linkUrl.search = ''; | ||
if (currentUrl.href !== linkUrl.href || !link.hash) continue; | ||
|
||
const nodeId = link.hash.substr(1); | ||
link.hash = `#index=${index}&anchor=${nodeId}`; | ||
} | ||
} | ||
|
||
export const Report: FunctionComponent = () => { | ||
const {dom, reportRenderer} = useReportRenderer(); | ||
const ref = useRef<HTMLDivElement>(null); | ||
const anchor = useHashParam('anchor'); | ||
const currentLhr = useCurrentLhr(); | ||
|
||
useLayoutEffect(() => { | ||
if (!currentLhr) return; | ||
|
||
if (ref.current) { | ||
dom.clearComponentCache(); | ||
reportRenderer.renderReport(currentLhr.value, ref.current); | ||
convertChildAnchors(ref.current, currentLhr.index); | ||
} | ||
|
||
return () => { | ||
if (ref.current) ref.current.textContent = ''; | ||
adamraine marked this conversation as resolved.
Show resolved
Hide resolved
|
||
}; | ||
}, [reportRenderer, currentLhr]); | ||
|
||
useEffect(() => { | ||
if (anchor) { | ||
const el = document.getElementById(anchor); | ||
if (el) { | ||
el.scrollIntoView({behavior: 'smooth'}); | ||
return; | ||
} | ||
} | ||
|
||
// Scroll to top no anchor is found. | ||
if (ref.current) ref.current.scrollIntoView(); | ||
}, [anchor, currentLhr]); | ||
|
||
return ( | ||
<div ref={ref} className="lh-root" data-testid="Report"/> | ||
); | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
/** | ||
* @license Copyright 2021 The Lighthouse Authors. All Rights Reserved. | ||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 | ||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. | ||
*/ | ||
|
||
import {jest} from '@jest/globals'; | ||
import {JSDOM} from 'jsdom'; | ||
|
||
/** | ||
* The jest environment "jsdom" does not work when preact is combined with the report renderer. | ||
*/ | ||
export function setupJsDom() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The default jsdom test environment was not cooperating with the report renderer. These changes basically setup our own environment for testing with JSDOM. The only problem I've encountered is that |
||
const {window} = new JSDOM(undefined, { | ||
url: 'file:///Users/example/report.html/', | ||
}); | ||
global.window = window as any; | ||
global.document = window.document; | ||
global.location = window.location; | ||
|
||
// Function not implemented in JSDOM. | ||
window.Element.prototype.scrollIntoView = jest.fn(); | ||
} | ||
|
||
global.beforeEach(setupJsDom); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍