@@ -13,7 +13,7 @@ console.log(`renderVisualizations.js: dirname=${__dirname}`);
1313
1414/**
1515 * Crops the image in the buffer so that there is no empty frame around it.
16- * @param {Buffer } buffer
16+ * @param {Buffer } buffer
1717 * @returns Buffer
1818 */
1919const autoCropImageBuffer = async ( buffer ) => {
@@ -31,41 +31,72 @@ const autoCropImageBuffer = async (buffer) => {
3131 */
3232const camelToKebabCase = ( str ) => str . replace ( / [ A - Z ] / g, ( letter ) => `-${ letter . toLowerCase ( ) } ` ) ;
3333
34+ /**
35+ * Take a screenshot after an error happened.
36+ *
37+ * @param {string } htmlFilename
38+ * @param {string } reason
39+ */
40+ const makeScreenshotOfError = async ( page , htmlFilename , reason ) => {
41+ const reportName = basename ( htmlFilename , ".html" ) ;
42+ const directoryName = camelToKebabCase ( reportName ) ;
43+ console . log ( `Taking an error screenshot of report ${ reportName } . Reason: ${ reason } ` ) ;
44+ await page . screenshot ( { path : `./${ directoryName } /error-${ reportName } -${ reason } .png` , omitBackground : false } ) ;
45+ } ;
46+
47+ /**
48+ * Handle a catched error by taking a screenshot.
49+ *
50+ * @param {string } htmlFilename
51+ * @param {string } reason
52+ * @return
53+ */
54+ const handleErrorWithScreenshot = ( page , htmlFilename , reason ) => async ( error ) => {
55+ await makeScreenshotOfError ( page , htmlFilename , reason ) ;
56+ throw new Error ( error ) ;
57+ } ;
3458/**
3559 * Creates a new page and takes a screenshot of all canvas tags that are contained within a div.
3660 * Note: Don't run this in parallel. See https://github.com/puppeteer/puppeteer/issues/1479
3761 * @param {Browser } browser
3862 * @param {string } htmlFilename
3963 */
4064const takeCanvasScreenshots = async ( browser , htmlFilename ) => {
65+ const reportName = basename ( htmlFilename , ".html" ) ;
66+ const directoryName = camelToKebabCase ( reportName ) ;
67+ if ( ! existsSync ( directoryName ) ) {
68+ mkdirSync ( directoryName ) ;
69+ }
70+
4171 const page = await browser . newPage ( ) ;
72+ page . on ( "requestfailed" , ( request ) => console . log ( `${ request . failure ( ) . errorText } ${ request . url ( ) } ` ) ) ;
4273 await page . setViewport ( { width : 1500 , height : 1000 , isMobile : false , isLandscape : true , hasTouch : false , deviceScaleFactor : 1 } ) ;
4374
4475 console . log ( `Loading ${ htmlFilename } ` ) ;
4576 await page . goto ( `file://${ htmlFilename } ` ) ;
4677
78+ if ( ! process . env . NEO4J_INITIAL_PASSWORD ) {
79+ throw new Error ( "Missing environment variable NEO4J_INITIAL_PASSWORD" ) ;
80+ }
4781 // Login with Neo4j server password from the environment variable NEO4J_INITIAL_PASSWORD
4882 const loginButton = await page . waitForSelector ( "#neo4j-server-login" ) ;
4983 await page . type ( "#neo4j-server-password" , process . env . NEO4J_INITIAL_PASSWORD ) ;
5084 await loginButton . click ( ) ;
5185
5286 // Wait for the graph visualization to be rendered onto a HTML5 canvas
5387 console . log ( `Waiting for visualizations to be finished` ) ;
54- await page . waitForSelector ( ".visualization-finished" , { timeout : 90_000 } ) ;
88+ await page
89+ . waitForSelector ( ".visualization-finished" , { timeout : 90_000 } )
90+ . catch ( handleErrorWithScreenshot ( page , htmlFilename , "visualization-did-not-finish" ) ) ;
5591
5692 // Get all HTML canvas tag elements
5793 const canvasElements = await page . $$ ( "canvas" ) ;
5894 if ( canvasElements . length <= 0 ) {
59- console . error ( `No elements with CSS selector ' canvas' found in ${ htmlFilename } ` ) ;
95+ await makeScreenshotOfError ( page , htmlFilename , "no- canvas- found" ) ;
6096 }
6197 console . log ( `Found ${ canvasElements . length } visualizations` ) ;
6298
6399 // Take a png screenshot of every canvas element and save them with increasing indices
64- const reportName = basename ( htmlFilename , ".html" ) ;
65- const directoryName = camelToKebabCase ( reportName ) ;
66- if ( ! existsSync ( directoryName ) ) {
67- mkdirSync ( directoryName ) ;
68- }
69100 await Promise . all (
70101 Array . from ( canvasElements ) . map ( async ( canvasElement , index ) => {
71102 console . log ( `Exporting image ${ reportName } -${ index } .png...` ) ;
@@ -74,10 +105,8 @@ const takeCanvasScreenshots = async (browser, htmlFilename) => {
74105 } , canvasElement ) ;
75106 let data = Buffer . from ( dataUrl . split ( "," ) . pop ( ) , "base64" ) ;
76107 console . log ( `Cropping image ${ reportName } -${ index } .png...` ) ;
77- data = await autoCropImageBuffer ( data ) ;
108+ data = await autoCropImageBuffer ( data ) . catch ( handleErrorWithScreenshot ( page , htmlFilename , `failed-to-crop-image- ${ index } ` ) ) ;
78109 writeFileSync ( `./${ directoryName } /${ reportName } -${ index } .png` , data ) ;
79- // console.log(`Taking screenshot ${reportName} of canvas ${index} in ${htmlFilename} of element...`);
80- // await canvasElement.screenshot({ path: `./${directoryName}/${reportName}-${index}.png`, omitBackground: true });
81110 } )
82111 ) ;
83112} ;
@@ -89,17 +118,34 @@ let browser;
89118 * and takes a screenshot of the canvas elements using {@link takeCanvasScreenshots}.
90119 */
91120( async ( ) => {
92- console . log ( 'renderVisualizations.js: Starting headless browser...' ) ;
93- browser = await puppeteer . launch ( { headless : "new" } ) ; // { headless: false } for testing
121+ console . log ( "renderVisualizations.js: Starting headless browser..." ) ;
122+ browser = await puppeteer . launch ( {
123+ headless : "new" ,
124+ dumpio : true ,
125+ args : [
126+ "--enable-logging" ,
127+ "--disable-search-engine-choice-screen" ,
128+ "--ash-no-nudges" ,
129+ "--no-first-run" ,
130+ "--no-default-browser-check" ,
131+ "--hide-scrollbars" ,
132+ "--disable-features=Translate" ,
133+ "--disable-features=InterestFeedContentSuggestions" ,
134+ "--disable-extensions" ,
135+ "--disable-default-apps" ,
136+ "--disable-component-extensions-with-background-pages" ,
137+ "--disable-client-side-phishing-detection" ,
138+ "--use-gl=disabled" ,
139+ "--disable-features=Vulkan" ,
140+ ] ,
141+ } ) ; // { headless: false } for testing
94142
95143 // Get all *.html files in this (script) directory and its subdirectories
96- // The separate filter is needed to ignore the "node_modules" directory.
144+ // The separate filter is needed to ignore the "node_modules" directory.
97145 // Glob's build-in filter doesn't seem to work on Windows.
98- const htmlFiles = globSync ( `${ __dirname } /**/*.html` , { absolute : true } ) . filter ( file => ! file . includes ( ' node_modules' ) ) ;
146+ const htmlFiles = globSync ( `${ __dirname } /**/*.html` , { absolute : true } ) . filter ( ( file ) => ! file . includes ( " node_modules" ) ) ;
99147 for ( const htmlFile of htmlFiles ) {
100148 await takeCanvasScreenshots ( browser , htmlFile ) ;
101149 }
102150 console . log ( `renderVisualizations.js: Successfully rendered ${ htmlFiles . length } html file(s)` ) ;
103- } ) ( )
104- . catch ( ( err ) => console . error ( err ) )
105- . finally ( ( ) => browser ?. close ( ) ) ;
151+ } ) ( ) . finally ( ( ) => browser ?. close ( ) ) ;
0 commit comments