@@ -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,71 @@ 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 ( ) ;
4272 await page . setViewport ( { width : 1500 , height : 1000 , isMobile : false , isLandscape : true , hasTouch : false , deviceScaleFactor : 1 } ) ;
4373
4474 console . log ( `Loading ${ htmlFilename } ` ) ;
4575 await page . goto ( `file://${ htmlFilename } ` ) ;
4676
77+ if ( ! process . env . NEO4J_INITIAL_PASSWORD ) {
78+ throw new Error ( "Missing environment variable NEO4J_INITIAL_PASSWORD" ) ;
79+ }
4780 // Login with Neo4j server password from the environment variable NEO4J_INITIAL_PASSWORD
4881 const loginButton = await page . waitForSelector ( "#neo4j-server-login" ) ;
4982 await page . type ( "#neo4j-server-password" , process . env . NEO4J_INITIAL_PASSWORD ) ;
5083 await loginButton . click ( ) ;
5184
5285 // Wait for the graph visualization to be rendered onto a HTML5 canvas
5386 console . log ( `Waiting for visualizations to be finished` ) ;
54- await page . waitForSelector ( ".visualization-finished" , { timeout : 90_000 } ) ;
87+ await page
88+ . waitForSelector ( ".visualization-finished" , { timeout : 90_000 } )
89+ . catch ( handleErrorWithScreenshot ( page , htmlFilename , "visualization-did-not-finish" ) ) ;
5590
5691 // Get all HTML canvas tag elements
5792 const canvasElements = await page . $$ ( "canvas" ) ;
5893 if ( canvasElements . length <= 0 ) {
59- console . error ( `No elements with CSS selector ' canvas' found in ${ htmlFilename } ` ) ;
94+ await makeScreenshotOfError ( page , htmlFilename , "no- canvas- found" ) ;
6095 }
6196 console . log ( `Found ${ canvasElements . length } visualizations` ) ;
6297
6398 // 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- }
6999 await Promise . all (
70100 Array . from ( canvasElements ) . map ( async ( canvasElement , index ) => {
71101 console . log ( `Exporting image ${ reportName } -${ index } .png...` ) ;
@@ -74,10 +104,8 @@ const takeCanvasScreenshots = async (browser, htmlFilename) => {
74104 } , canvasElement ) ;
75105 let data = Buffer . from ( dataUrl . split ( "," ) . pop ( ) , "base64" ) ;
76106 console . log ( `Cropping image ${ reportName } -${ index } .png...` ) ;
77- data = await autoCropImageBuffer ( data ) ;
107+ data = await autoCropImageBuffer ( data ) . catch ( handleErrorWithScreenshot ( page , htmlFilename , `failed-to-crop-image- ${ index } ` ) ) ;
78108 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 });
81109 } )
82110 ) ;
83111} ;
@@ -89,13 +117,13 @@ let browser;
89117 * and takes a screenshot of the canvas elements using {@link takeCanvasScreenshots}.
90118 */
91119( async ( ) => {
92- console . log ( ' renderVisualizations.js: Starting headless browser...' ) ;
120+ console . log ( " renderVisualizations.js: Starting headless browser..." ) ;
93121 browser = await puppeteer . launch ( { headless : "new" } ) ; // { headless: false } for testing
94122
95123 // Get all *.html files in this (script) directory and its subdirectories
96- // The separate filter is needed to ignore the "node_modules" directory.
124+ // The separate filter is needed to ignore the "node_modules" directory.
97125 // 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' ) ) ;
126+ const htmlFiles = globSync ( `${ __dirname } /**/*.html` , { absolute : true } ) . filter ( ( file ) => ! file . includes ( " node_modules" ) ) ;
99127 for ( const htmlFile of htmlFiles ) {
100128 await takeCanvasScreenshots ( browser , htmlFile ) ;
101129 }
0 commit comments