@@ -43,7 +43,21 @@ const globals: {
4343 componentsDrop ?: Drop ;
4444} = { } ;
4545
46- async function execute ( ) : Promise < void > {
46+ init ( ) . catch ( ( e ) => print ( "unexpected error" , e ) ) ;
47+
48+ function init ( ) : Promise < void > {
49+ // this event discovered by "reverse-engineering GitHub"
50+ // https://github.com/refined-github/refined-github/blob/main/contributing.md#reverse-engineering-github
51+ // TODO: this event is not fired when navigating using the browser's back and forward buttons
52+ document . addEventListener ( "soft-nav:end" , ( ) => {
53+ clear ( ) ;
54+ main ( ) ;
55+ } ) ;
56+
57+ return main ( ) ;
58+ }
59+
60+ async function main ( ) : Promise < void > {
4761 let metadata : FileMetadata ;
4862
4963 try {
@@ -55,88 +69,123 @@ async function execute(): Promise<void> {
5569
5670 globals . coverageButton = createCoverageButton ( ) ;
5771
58- const flags = await getFlags ( metadata ) ;
72+ process ( metadata ) . catch ( ( e ) => {
73+ print ( "unexpected error" , e ) ;
74+ updateButton ( "Coverage: ⚠" ) ;
75+ } ) ;
76+ }
77+
78+ async function process ( metadata : FileMetadata ) : Promise < void > {
79+ const flags = await getFlags ( metadata ) . catch ( ( e ) => {
80+ print ( "error while fetching flags" , e ) ;
81+ return [ ] ;
82+ } ) ;
5983
6084 const selectedFlags : string [ ] = await browser . storage . local
6185 . get ( flagsStorageKey )
62- . then ( ( result ) => result [ flagsStorageKey ] || [ ] ) ;
86+ . then ( ( result ) => result [ flagsStorageKey ] || [ ] )
87+ . catch ( ( e ) => {
88+ print ( "error while fetching selected flags" , e ) ;
89+ return [ ] ;
90+ } ) ;
6391
6492 // TODO: allow setting selected flags for different files at the same time
6593 if (
6694 selectedFlags . length > 0 &&
6795 _ . intersection ( flags , selectedFlags ) . length === 0
6896 ) {
6997 await handleFlagClick ( [ ] ) ;
98+ return ;
7099 }
71100
72101 if ( flags . length > 0 ) {
73- const { button : flagsButton , list : flagsList } = await createDropdown ( {
102+ createDropdown ( {
74103 title : "Flags" ,
75104 tooltip : "Filter coverage by flag" ,
76105 options : flags ,
77- previousElement : globals . coverageButton ,
106+ previousElement : globals . coverageButton ! ,
78107 selectedOptions : selectedFlags ,
79108 onClick : handleFlagClick ,
80- } ) ;
81- globals . flagsButton = flagsButton ;
82- globals . flagsDrop = new Drop ( {
83- target : globals . flagsButton ,
84- content : flagsList ,
85- classes : "drop-theme-arrows codecov-z1 codecov-bg-white" ,
86- position : "bottom right" ,
87- openOn : "click" ,
88- } ) ;
109+ } )
110+ . then ( ( { button, list } ) => {
111+ globals . flagsButton = button ;
112+ globals . flagsDrop = new Drop ( {
113+ target : button ,
114+ content : list ,
115+ classes : "drop-theme-arrows codecov-z1 codecov-bg-white" ,
116+ position : "bottom right" ,
117+ openOn : "click" ,
118+ } ) ;
119+ } )
120+ . catch ( ( e ) => {
121+ print ( "error while rendering flags dropdown" , e ) ;
122+ } ) ;
89123 }
90124
91125 const components = await getComponents ( metadata ) ;
92126
93127 const selectedComponents : string [ ] = await browser . storage . local
94128 . get ( componentsStorageKey )
95- . then ( ( result ) => result [ componentsStorageKey ] || [ ] ) ;
129+ . then ( ( result ) => result [ componentsStorageKey ] || [ ] )
130+ . catch ( ( e ) => {
131+ print ( "error while fetching selected components" , e ) ;
132+ return [ ] ;
133+ } ) ;
96134
97135 // TODO: allow setting selected flags for different files at the same time
98136 if (
99137 selectedComponents . length > 0 &&
100138 _ . intersection ( components , selectedComponents ) . length === 0
101139 ) {
102140 await handleComponentClick ( [ ] ) ;
141+ return ;
103142 }
104143
105144 if ( components . length > 0 ) {
106- const { button : componentsButton , list : componentsList } =
107- await createDropdown ( {
108- title : "Components" ,
109- options : components ,
110- tooltip : "Filter coverage by component" ,
111- previousElement : globals . coverageButton ,
112- onClick : handleComponentClick ,
113- selectedOptions : selectedComponents ,
145+ createDropdown ( {
146+ title : "Components" ,
147+ options : components ,
148+ tooltip : "Filter coverage by component" ,
149+ previousElement : globals . coverageButton ! ,
150+ onClick : handleComponentClick ,
151+ selectedOptions : selectedComponents ,
152+ } )
153+ . then ( ( { button, list } ) => {
154+ globals . componentsButton = button ;
155+ globals . componentsDrop = new Drop ( {
156+ target : button ,
157+ content : list ,
158+ classes : "drop-theme-arrows codecov-z1 codecov-bg-white" ,
159+ position : "bottom right" ,
160+ openOn : "click" ,
161+ } ) ;
162+ } )
163+ . catch ( ( e ) => {
164+ print ( "error while rendering components dropdown" , e ) ;
114165 } ) ;
115- globals . componentsButton = componentsButton ;
116- globals . componentsDrop = new Drop ( {
117- target : globals . componentsButton ,
118- content : componentsList ,
119- classes : "drop-theme-arrows codecov-z1 codecov-bg-white" ,
120- position : "bottom right" ,
121- openOn : "click" ,
122- } ) ;
123166 }
124167
125168 let coverageReportResponses : Array < FileCoverageReportResponse > ;
126- if ( selectedFlags ?. length > 0 ) {
127- coverageReportResponses = await Promise . all (
128- selectedFlags . map ( ( flag ) => getCommitReport ( metadata , flag , undefined ) )
129- ) ;
130- } else if ( selectedComponents ?. length > 0 ) {
131- coverageReportResponses = await Promise . all (
132- selectedComponents . map ( ( component ) =>
133- getCommitReport ( metadata , undefined , component )
134- )
135- ) ;
136- } else {
137- coverageReportResponses = await Promise . all ( [
138- await getCommitReport ( metadata , undefined , undefined ) ,
139- ] ) ;
169+ try {
170+ if ( selectedFlags ?. length > 0 ) {
171+ coverageReportResponses = await Promise . all (
172+ selectedFlags . map ( ( flag ) => getCommitReport ( metadata , flag , undefined ) )
173+ ) ;
174+ } else if ( selectedComponents ?. length > 0 ) {
175+ coverageReportResponses = await Promise . all (
176+ selectedComponents . map ( ( component ) =>
177+ getCommitReport ( metadata , undefined , component )
178+ )
179+ ) ;
180+ } else {
181+ coverageReportResponses = await Promise . all ( [
182+ await getCommitReport ( metadata , undefined , undefined ) ,
183+ ] ) ;
184+ }
185+ } catch ( e ) {
186+ print ( "error while fetching coverage report(s)" , e as Error ) ;
187+ updateButton ( `Coverage: ⚠` ) ;
188+ return ;
140189 }
141190
142191 const coverageReports = coverageReportResponses . map (
@@ -170,13 +219,14 @@ async function execute(): Promise<void> {
170219 } , { } ) ;
171220 } ) ( ) ;
172221
173- if ( ! _ . isEmpty ( coverageReport ) ) {
174- const coveragePct = calculateCoveragePct ( coverageReport ) ;
175- updateButton ( `Coverage: ${ coveragePct . toFixed ( 2 ) } %` ) ;
176- } else {
222+ if ( _ . isEmpty ( coverageReport ) ) {
177223 updateButton ( `Coverage: N/A` ) ;
224+ return ;
178225 }
179226
227+ const coveragePct = calculateCoveragePct ( coverageReport ) ;
228+ updateButton ( `Coverage: ${ coveragePct . toFixed ( 2 ) } %` ) ;
229+
180230 globals . coverageReport = coverageReport ;
181231 animateAndAnnotateLines ( lineSelector , annotateLine ) ;
182232}
@@ -214,7 +264,7 @@ async function handleFlagClick(selectedFlags: string[]) {
214264 [ flagsStorageKey ] : selectedFlags ,
215265 } ) ;
216266 clear ( ) ;
217- await execute ( ) ;
267+ await main ( ) ;
218268}
219269
220270async function handleComponentClick ( selectedComponents : string [ ] ) {
@@ -225,7 +275,7 @@ async function handleComponentClick(selectedComponents: string[]) {
225275 [ componentsStorageKey ] : selectedComponents ,
226276 } ) ;
227277 clear ( ) ;
228- await execute ( ) ;
278+ await main ( ) ;
229279}
230280
231281function calculateCoveragePct ( coverageReport : FileCoverageReport ) : number {
@@ -243,7 +293,11 @@ function updateButton(text: string) {
243293
244294function annotateLine ( line : HTMLElement ) {
245295 const lineNumber = parseInt ( line . getAttribute ( "data-key" ) ! ) + 1 ;
246- const status = globals . coverageReport ! [ lineNumber ] ;
296+ // called from "Coverage: N/A" button on-click handler
297+ if ( ! globals . coverageReport ) {
298+ return ;
299+ }
300+ const status = globals . coverageReport [ lineNumber ] ;
247301 if ( status === CoverageStatus . COVERED ) {
248302 line . style . backgroundColor = alpha ( colors . green , 0.25 ) ;
249303 } else if ( status === CoverageStatus . UNCOVERED ) {
@@ -274,16 +328,3 @@ function clear() {
274328 clearButtons ( ) ;
275329 clearAnimationAndAnnotations ( ) ;
276330}
277-
278- async function main ( ) : Promise < void > {
279- await execute ( ) ;
280- // this event discovered by "reverse-engineering GitHub"
281- // https://github.com/refined-github/refined-github/blob/main/contributing.md#reverse-engineering-github
282- // TODO: this event is not fired when navigating using the browser's back and forward buttons
283- document . addEventListener ( "soft-nav:end" , ( ) => {
284- clear ( ) ;
285- execute ( ) ;
286- } ) ;
287- }
288-
289- main ( ) ;
0 commit comments