11import { task } from 'gulp' ;
22import { readdirSync , statSync , existsSync , mkdirSync } from 'fs' ;
3- import { openScreenshotsCloudStorage , openScreenshotsFirebaseDatabase } from '../task_helpers' ;
3+ import { openScreenshotsCloudStorage , openFirebaseScreenshotsDatabase } from '../task_helpers' ;
4+ import * as path from 'path' ;
5+ import * as firebase from 'firebase' ;
46const imageDiff = require ( 'image-diff' ) ;
57
68const SCREENSHOT_DIR = './screenshots' ;
@@ -11,38 +13,48 @@ const FIREBASE_REPORT = 'screenshot/reports';
1113task ( 'screenshots' , ( ) => {
1214 let prNumber = process . env [ 'TRAVIS_PULL_REQUEST' ] ;
1315 if ( prNumber ) {
14- let database = openScreenshotsFirebaseDatabase ( ) ;
15- return getFilenameList ( database )
16- . then ( ( filenames : string [ ] ) => {
17- return downloadReferenceScreenshots ( filenames , database )
18- . then ( ( results : any ) => {
19- return compareScreenshots ( filenames , database , prNumber ) ;
20- } ) ;
21- } )
22- . then ( ( results : boolean ) => {
23- return database . ref ( FIREBASE_REPORT ) . child ( `${ prNumber } /result` ) . set ( results ) ;
24- } )
25- . then ( ( ) => database . ref ( FIREBASE_REPORT ) . child ( `${ prNumber } /commit` ) . set ( process . env [ 'TRAVIS_COMMIT' ] ) )
26- . then ( ( ) => setFilenameList ( database , prNumber ) )
16+ let database = openFirebaseScreenshotsDatabase ( ) ;
17+ return getScreenFilenames ( database )
18+ . then ( ( filenames : string [ ] ) => downloadAllGolds ( filenames , database , prNumber ) )
19+ . then ( ( results : boolean ) => updateResult ( database , prNumber , results ) )
20+ . then ( ( ) => setScreenFilenames ( database , prNumber ) )
2721 . then ( ( ) => uploadScreenshots ( prNumber , 'diff' ) )
2822 . then ( ( ) => uploadScreenshots ( prNumber , 'test' ) )
23+ . then ( ( ) => updateCommit ( database , prNumber ) )
2924 . then ( ( ) => database . goOffline ( ) , ( ) => database . goOffline ( ) ) ;
3025 }
3126} ) ;
3227
28+ function updateFileResult ( database : firebase . database . Database , prNumber : string ,
29+ filenameKey : string , result : boolean ) : firebase . Promise < void > {
30+ return database . ref ( FIREBASE_REPORT ) . child ( `${ prNumber } /results/${ filenameKey } ` ) . set ( result ) ;
31+ }
32+
33+ function updateResult ( database : firebase . database . Database , prNumber : string ,
34+ result : boolean ) : firebase . Promise < void > {
35+ return database . ref ( FIREBASE_REPORT ) . child ( `${ prNumber } /result` ) . set ( result ) ;
36+ }
37+
38+ function updateCommit ( database : firebase . database . Database ,
39+ prNumber : string ) : firebase . Promise < void > {
40+ return database . ref ( FIREBASE_REPORT ) . child ( `${ prNumber } /commit` )
41+ . set ( process . env [ 'TRAVIS_COMMIT' ] ) ;
42+ }
43+
3344/** Get a list of filenames from firebase database. */
34- function getFilenameList ( database : any ) : Promise < string [ ] > {
35- return database . ref ( FIREBASE_FILELIST ) . once ( 'value' ) . then ( function ( snapshots : any ) {
45+ function getScreenFilenames ( database : firebase . database . Database ) : firebase . Promise < string [ ] > {
46+ return database . ref ( FIREBASE_FILELIST ) . once ( 'value' )
47+ . then ( ( snapshots : firebase . database . DataSnapshot ) => {
3648 return snapshots . val ( ) ;
3749 } ) ;
3850}
3951
40- /** Upload a list of filenames to firebase database as reference . */
41- function setFilenameList ( database : any ,
42- reportKey ?: string ) : Promise < any > {
52+ /** Upload a list of filenames to firebase database as gold . */
53+ function setScreenFilenames ( database : firebase . database . Database ,
54+ reportKey ?: string ) : firebase . Promise < void > {
4355 let filenames : string [ ] = [ ] ;
44- readdirSync ( SCREENSHOT_DIR ) . map ( function ( file ) {
45- let fullName = SCREENSHOT_DIR + '/' + file ;
56+ readdirSync ( SCREENSHOT_DIR ) . map ( ( file : string ) => {
57+ let fullName = path . join ( SCREENSHOT_DIR , file ) ;
4658 let key = file . replace ( '.screenshot.png' , '' ) ;
4759 if ( ! statSync ( fullName ) . isDirectory ( ) && key ) {
4860 filenames . push ( file ) ;
@@ -54,23 +66,31 @@ function setFilenameList(database: any,
5466 return filelistDatabase . set ( filenames ) ;
5567}
5668
57- /** Upload screenshots to google cloud storage. */
69+ /**
70+ * Upload screenshots to google cloud storage.
71+ * @param {string } reportKey - The key used in firebase. Here it is the PR number.
72+ * If there's no reportKey, we will upload images to 'golds/' folder
73+ * @param {string } mode - Can be 'test' or 'diff' or null.
74+ * If the images are the test results, mode should be 'test'.
75+ * If the images are the diff images generated, mode should be 'diff'.
76+ * For golds mode should be null.
77+ */
5878function uploadScreenshots ( reportKey ?: string , mode ?: 'test' | 'diff' ) {
5979 let bucket = openScreenshotsCloudStorage ( ) ;
6080
61- let promises : Promise < any > [ ] = [ ] ;
81+ let promises : firebase . Promise < void > [ ] = [ ] ;
6282 let localDir = mode == 'diff' ? `${ SCREENSHOT_DIR } /diff` : SCREENSHOT_DIR ;
63- readdirSync ( localDir ) . map ( function ( file ) {
64- let fileName = localDir + '/' + file ;
83+ readdirSync ( localDir ) . map ( ( file : string ) => {
84+ let fileName = path . join ( localDir , file ) ;
6585 let key = file . replace ( '.screenshot.png' , '' ) ;
6686 let destination = ( mode == null || ! reportKey ) ?
67- `references /${ file } ` : `screenshots/${ reportKey } /${ mode } /${ file } ` ;
87+ `golds /${ file } ` : `screenshots/${ reportKey } /${ mode } /${ file } ` ;
6888
6989 if ( ! statSync ( fileName ) . isDirectory ( ) && key ) {
7090 promises . push ( bucket . upload ( fileName , { destination : destination } ) ) ;
7191 }
7292 } ) ;
73- return Promise . all ( promises ) ;
93+ return firebase . Promise . all ( promises ) ;
7494}
7595
7696/** Check whether the directory exists. If not then create one. */
@@ -80,57 +100,50 @@ function _makeDir(dirName: string) {
80100 }
81101}
82102
83- /** Download references screenshots. */
84- function downloadReferenceScreenshots (
85- filenames : string [ ] , database : any ) : Promise < any > {
86- _makeDir ( `${ SCREENSHOT_DIR } /references` ) ;
103+ /** Download golds screenshots. */
104+ function downloadAllGolds (
105+ filenames : string [ ] , database : firebase . database . Database ,
106+ reportKey : string ) : firebase . Promise < boolean > {
107+ _makeDir ( `${ SCREENSHOT_DIR } /golds` ) ;
87108
88- return Promise . all ( filenames . map ( ( filename : string ) => {
89- return _downloadReferenceScreenshot ( filename ) ;
90- } ) ) ;
109+ return firebase . Promise . all ( filenames . map ( ( filename : string ) => {
110+ return downloadGold ( filename ) . then ( ( ) => diffScreenshot ( filename , database , reportKey ) ) ;
111+ } ) ) . then ( ( results : boolean [ ] ) => results . every ( ( value : boolean ) => value == true ) ) ;
91112}
92113
93- /** Download one reference screenshot */
94- function _downloadReferenceScreenshot ( filename : string ) : Promise < any > {
114+ /** Download one gold screenshot */
115+ function downloadGold ( filename : string ) : Promise < void > {
95116 let bucket = openScreenshotsCloudStorage ( ) ;
96- return bucket . file ( `references /${ filename } ` ) . download ( {
97- destination : `${ SCREENSHOT_DIR } /references /${ filename } `
117+ return bucket . file ( `golds /${ filename } ` ) . download ( {
118+ destination : `${ SCREENSHOT_DIR } /golds /${ filename } `
98119 } ) ;
99120}
100121
101- /** Compare the test result and the reference. */
102- function compareScreenshots ( filenames : string [ ] , database : any , reportKey : string ) : Promise < any > {
103- return Promise . all ( filenames . map ( ( filename ) =>
104- _compareScreenshot ( filename , database , reportKey ) ) )
105- . then ( ( results : any ) => results . every ( ( value : boolean ) => value == true ) ) ;
106- }
107-
108- function _compareScreenshot ( filename : string , database : any ,
109- reportKey : string ) : Promise < any > {
110- let expectedUrl = `${ SCREENSHOT_DIR } /references/${ filename } ` ;
111- let actualUrl = `${ SCREENSHOT_DIR } /${ filename } ` ;
122+ function diffScreenshot ( filename : string , database : firebase . database . Database ,
123+ reportKey : string ) : firebase . Promise < boolean > {
124+ // TODO(tinayuangao): Run the downloads and diffs in parallel.
125+ let goldUrl = `${ SCREENSHOT_DIR } /golds/${ filename } ` ;
126+ let pullRequestUrl = `${ SCREENSHOT_DIR } /${ filename } ` ;
112127 let diffUrl = `${ SCREENSHOT_DIR } /diff/${ filename } ` ;
113128 let filenameKey = filename . replace ( '.screenshot.png' , '' ) ;
114129
115- if ( existsSync ( expectedUrl ) && existsSync ( actualUrl ) ) {
116- return new Promise ( function ( resolve , reject ) {
130+ if ( existsSync ( goldUrl ) && existsSync ( pullRequestUrl ) ) {
131+ return new firebase . Promise ( ( resolve : any , reject : any ) => {
117132 imageDiff ( {
118- actualImage : actualUrl ,
119- expectedImage : expectedUrl ,
133+ actualImage : pullRequestUrl ,
134+ expectedImage : goldUrl ,
120135 diffImage : diffUrl ,
121- } , function ( err : any , imagesAreSame : boolean ) {
136+ } , ( err : any , imagesAreSame : boolean ) => {
122137 if ( err ) {
123138 console . log ( err ) ;
124139 imagesAreSame = false ;
125140 reject ( err ) ;
126141 }
127142 resolve ( imagesAreSame ) ;
128- return database . ref ( FIREBASE_REPORT ) . child ( `${ reportKey } /results/${ filenameKey } ` )
129- . set ( imagesAreSame ) ;
143+ return updateFileResult ( database , reportKey , filenameKey , imagesAreSame ) ;
130144 } ) ;
131145 } ) ;
132146 } else {
133- return database . ref ( FIREBASE_REPORT ) . child ( `${ reportKey } /results/${ filenameKey } ` )
134- . set ( false ) . then ( ( ) => false ) ;
147+ return updateFileResult ( database , reportKey , filenameKey , false ) . then ( ( ) => false ) ;
135148 }
136149}
0 commit comments