1+ "use strict" ;
2+
3+ const path = require ( 'path' ) ;
4+ const child_process = require ( 'child_process' ) ;
5+ const mapnik = require ( 'mapnik' ) ;
6+
7+ const SHA = process . env . TRAVIS_COMMIT ;
8+ const LFS_BASE_URL = 'https://media.githubusercontent.com/media/angular/material2' ;
9+
10+ /**
11+ * Generates a screenshot from the current state of the Protractor test and compares it to the
12+ * previous stored screenshot. If the screenshots do not match or if no existing screenshot is
13+ * found, an error will be thrown. In both cases, the new screenshot will be stored so that it can
14+ * be added to git.
15+ */
16+ class Screenshot {
17+ /**
18+ * @param {string } id A unique identifier used for the screenshot
19+ */
20+ constructor ( id ) {
21+ this . id = id ;
22+ this . path = path . resolve ( __dirname , '..' , 'screenshots' , id + '.screenshot.png' ) ;
23+ this . url = `${ LFS_BASE_URL } /${ SHA } /screenshots/${ encodeURIComponent ( id ) } .screenshot.png` ;
24+ browser . takeScreenshot ( ) . then ( png => this . storeScreenshot ( png ) ) ;
25+ }
26+
27+ /**
28+ * Stores a local copy of the screenshot for future comparison
29+ * @param {string } png The base64-encoded screenshot generated from the current browser state
30+ */
31+ storeScreenshot ( png ) {
32+ console . info ( `[STATUS] Generated new screenshot for "${ this . id } "` ) ;
33+ this . png = mapnik . Image . fromBytes ( new Buffer ( png , 'base64' ) ) ;
34+ if ( SHA ) {
35+ this . downloadFromGithub ( ) ;
36+ } else {
37+ this . compareScreenshots ( ) ;
38+ }
39+ }
40+
41+ /**
42+ * Since we are using `git-lfs`, screenshots are not necessarily available within our local
43+ * directory. To get around this, we download the latest screenshot from Github.
44+ */
45+ downloadFromGithub ( ) {
46+ console . info ( `[STATUS] Downloading screenshot from Github: ${ this . url } => ${ this . path } ` ) ;
47+ child_process . execSync ( `curl ${ this . url } > "${ this . path } "` ) ;
48+ this . compareScreenshots ( ) ;
49+ }
50+
51+ /**
52+ * Compares the generated screenshot to the existing screenshot. If it does not match, an error
53+ * will be thrown.
54+ */
55+ compareScreenshots ( ) {
56+ console . info ( `[STATUS] Comparing screenshots` ) ;
57+ try {
58+ let referenceScreenshot = mapnik . Image . open ( this . path ) ;
59+ this . overwriteExistingScreenshot ( ) ;
60+ if ( referenceScreenshot . compare ( this . png ) ) {
61+ throw new Error ( `screenshot "${ this . id } " has changed.` ) ;
62+ } else {
63+ console . info ( '[STATUS] Screenshot has not changed' ) ;
64+ }
65+ } catch ( e ) {
66+ console . info ( `[STATUS] No reference screenshot found` ) ;
67+ this . overwriteExistingScreenshot ( ) ;
68+ throw new Error ( `screenshot "${ this . id } " was not found.` ) ;
69+ }
70+ }
71+
72+ /**
73+ * Replaces the existing screenshot with the newly generated one.
74+ */
75+ overwriteExistingScreenshot ( ) {
76+ console . info ( `[STATUS] Saving new screenshot` ) ;
77+ this . png . save ( this . path ) ;
78+ }
79+ }
80+
81+ module . exports = ( id ) => new Screenshot ( id ) ;
0 commit comments