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