@@ -6,6 +6,7 @@ const chai = require("chai");
6
6
const expect = chai . expect ;
7
7
const assert = chai . assert ;
8
8
const fs = require ( "fs" ) ;
9
+ const os = require ( "os" ) ;
9
10
10
11
const Firestore = require ( "@google-cloud/firestore" ) ;
11
12
@@ -32,7 +33,6 @@ const ALL_EMULATORS_STARTED_LOG = "All emulators started, it is now safe to conn
32
33
* parallel emulator subprocesses.
33
34
*/
34
35
const TEST_SETUP_TIMEOUT = 60000 ;
35
- const EMULATORS_STARTUP_DELAY_TIMEOUT = 60000 ;
36
36
const EMULATORS_WRITE_DELAY_MS = 5000 ;
37
37
const EMULATORS_SHUTDOWN_DELAY_MS = 5000 ;
38
38
const EMULATOR_TEST_TIMEOUT = EMULATORS_WRITE_DELAY_MS * 2 ;
@@ -44,6 +44,66 @@ const EMULATOR_TEST_TIMEOUT = EMULATORS_WRITE_DELAY_MS * 2;
44
44
const FIRESTORE_COMPLETION_MARKER = "test/done_from_firestore" ;
45
45
const DATABASE_COMPLETION_MARKER = "test/done_from_database" ;
46
46
47
+ function CLIProcess ( name ) {
48
+ this . name = name ;
49
+ this . process = undefined ;
50
+ }
51
+ CLIProcess . prototype . constructor = CLIProcess ;
52
+
53
+ CLIProcess . prototype . start = function ( cmd , additionalArgs , logDoneFn ) {
54
+ const args = [ PROJECT_ROOT + "/lib/bin/firebase.js" , cmd , "--project" , FIREBASE_PROJECT ] ;
55
+
56
+ if ( additionalArgs ) {
57
+ args . push ( ...additionalArgs ) ;
58
+ }
59
+
60
+ this . process = subprocess . spawn ( "node" , args ) ;
61
+
62
+ this . process . stdout . on ( "data" , ( data ) => {
63
+ process . stdout . write ( `[${ this . name } stdout] ` + data ) ;
64
+ } ) ;
65
+
66
+ this . process . stderr . on ( "data" , ( data ) => {
67
+ console . log ( `[${ this . name } stderr] ` + data ) ;
68
+ } ) ;
69
+
70
+ let started ;
71
+ if ( logDoneFn ) {
72
+ started = new Promise ( ( resolve ) => {
73
+ this . process . stdout . on ( "data" , ( data ) => {
74
+ if ( logDoneFn ( data ) ) {
75
+ resolve ( ) ;
76
+ }
77
+ } ) ;
78
+ } ) ;
79
+ } else {
80
+ started = new Promise ( ( resolve ) => {
81
+ this . process . once ( "close" , ( ) => {
82
+ this . process = undefined ;
83
+ resolve ( ) ;
84
+ } ) ;
85
+ } ) ;
86
+ }
87
+
88
+ return started ;
89
+ } ;
90
+
91
+ CLIProcess . prototype . stop = function ( ) {
92
+ if ( ! this . process ) {
93
+ return Promise . resolve ( ) ;
94
+ }
95
+
96
+ const stopped = new Promise ( ( resolve ) => {
97
+ this . process . once ( "close" , ( /* exitCode, signal */ ) => {
98
+ this . process = undefined ;
99
+ resolve ( ) ;
100
+ } ) ;
101
+ } ) ;
102
+
103
+ this . process . kill ( "SIGINT" ) ;
104
+ return stopped ;
105
+ } ;
106
+
47
107
function TriggerEndToEndTest ( config ) {
48
108
this . rtdb_emulator_host = "localhost" ;
49
109
this . rtdb_emulator_port = config . emulators . database . port ;
@@ -69,7 +129,7 @@ function TriggerEndToEndTest(config) {
69
129
this . rtdb_from_rtdb = false ;
70
130
this . firestore_from_firestore = false ;
71
131
72
- this . emulators_process = null ;
132
+ this . cli_process = null ;
73
133
}
74
134
75
135
/*
@@ -86,50 +146,36 @@ TriggerEndToEndTest.prototype.success = function success() {
86
146
} ;
87
147
88
148
TriggerEndToEndTest . prototype . startEmulators = function startEmulators ( additionalArgs ) {
89
- var self = this ;
90
- const args = [
91
- PROJECT_ROOT + "/lib/bin/firebase.js" ,
92
- "emulators:start" ,
93
- "--project" ,
94
- FIREBASE_PROJECT ,
95
- ] ;
96
-
97
- if ( additionalArgs ) {
98
- args . push ( ...additionalArgs ) ;
99
- }
100
-
101
- self . emulators_process = subprocess . spawn ( "node" , args ) ;
149
+ const cli = new CLIProcess ( "default" ) ;
150
+ const started = cli . start ( "emulators:start" , additionalArgs , ( data ) => {
151
+ return data . indexOf ( ALL_EMULATORS_STARTED_LOG ) > - 1 ;
152
+ } ) ;
102
153
103
- self . emulators_process . stdout . on ( "data" , function ( data ) {
104
- process . stdout . write ( "[emulators stdout] " + data ) ;
154
+ cli . process . stdout . on ( "data" , ( data ) => {
105
155
if ( data . indexOf ( RTDB_FUNCTION_LOG ) > - 1 ) {
106
- self . rtdb_trigger_count ++ ;
156
+ this . rtdb_trigger_count ++ ;
107
157
}
108
158
if ( data . indexOf ( FIRESTORE_FUNCTION_LOG ) > - 1 ) {
109
- self . firestore_trigger_count ++ ;
159
+ this . firestore_trigger_count ++ ;
110
160
}
111
161
if ( data . indexOf ( PUBSUB_FUNCTION_LOG ) > - 1 ) {
112
- self . pubsub_trigger_count ++ ;
113
- }
114
- if ( data . indexOf ( ALL_EMULATORS_STARTED_LOG ) > - 1 ) {
115
- self . all_emulators_started = true ;
162
+ this . pubsub_trigger_count ++ ;
116
163
}
117
164
} ) ;
118
165
119
- self . emulators_process . stderr . on ( "data" , function ( data ) {
120
- console . log ( "[emulators stderr] " + data ) ;
121
- } ) ;
166
+ this . cli_process = cli ;
167
+ return started ;
122
168
} ;
123
169
124
- TriggerEndToEndTest . prototype . stopEmulators = function stopEmulators ( done ) {
125
- this . emulators_process . once ( "close" , function ( /* exitCode, signal */ ) {
126
- done ( ) ;
127
- } ) ;
170
+ TriggerEndToEndTest . prototype . startEmulatorsAndWait = function startEmulatorsAndWait (
171
+ additionalArgs ,
172
+ done
173
+ ) {
174
+ this . startEmulators ( additionalArgs ) . then ( done ) ;
175
+ } ;
128
176
129
- /*
130
- * CLI process only shuts down emulators cleanly on SIGINT.
131
- */
132
- this . emulators_process . kill ( "SIGINT" ) ;
177
+ TriggerEndToEndTest . prototype . stopEmulators = function stopEmulators ( done ) {
178
+ this . cli_process . stop ( ) . then ( done ) ;
133
179
} ;
134
180
135
181
TriggerEndToEndTest . prototype . invokeHttpFunction = function invokeHttpFunction ( name , done ) {
@@ -217,15 +263,7 @@ describe("database and firestore emulator function triggers", function() {
217
263
} ) ;
218
264
} ,
219
265
function ( done ) {
220
- test . startEmulators ( [ "--only" , "functions,database,firestore" ] ) ;
221
- test . waitForCondition (
222
- ( ) => test . all_emulators_started ,
223
- EMULATORS_STARTUP_DELAY_TIMEOUT ,
224
- ( err ) => {
225
- expect ( err ) . to . be . undefined ;
226
- done ( ) ;
227
- }
228
- ) ;
266
+ test . startEmulatorsAndWait ( [ "--only" , "functions,database,firestore" ] , done ) ;
229
267
} ,
230
268
function ( done ) {
231
269
test . firestore_client = new Firestore ( {
@@ -390,15 +428,7 @@ describe("pubsub emulator function triggers", function() {
390
428
} ) ;
391
429
} ,
392
430
function ( done ) {
393
- test . startEmulators ( [ "--only" , "functions,pubsub" ] ) ;
394
- test . waitForCondition (
395
- ( ) => test . all_emulators_started ,
396
- EMULATORS_STARTUP_DELAY_TIMEOUT ,
397
- ( err ) => {
398
- expect ( err ) . to . be . undefined ;
399
- done ( ) ;
400
- }
401
- ) ;
431
+ test . startEmulatorsAndWait ( [ "--only" , "functions,pubsub" ] , done ) ;
402
432
} ,
403
433
] ,
404
434
done
@@ -429,3 +459,33 @@ describe("pubsub emulator function triggers", function() {
429
459
done ( ) ;
430
460
} ) ;
431
461
} ) ;
462
+
463
+ describe ( "import/export end to end" , ( ) => {
464
+ it ( "should be able to import/export firestore data" , async ( ) => {
465
+ // Start up emulator suite
466
+ const emulatorsCLI = new CLIProcess ( "1" ) ;
467
+ await emulatorsCLI . start ( "emulators:start" , [ "--only" , "firestore" ] , ( data ) => {
468
+ return data . indexOf ( ALL_EMULATORS_STARTED_LOG ) > - 1 ;
469
+ } ) ;
470
+
471
+ // Ask for export
472
+ const exportCLI = new CLIProcess ( "2" ) ;
473
+ const exportPath = fs . mkdtempSync ( path . join ( os . tmpdir ( ) , "emulator-data" ) ) ;
474
+ await exportCLI . start ( "emulators:export" , [ exportPath ] ) ;
475
+
476
+ // Stop the suite
477
+ await emulatorsCLI . stop ( ) ;
478
+
479
+ // Attempt to import
480
+ const importCLI = new CLIProcess ( "3" ) ;
481
+ await importCLI . start (
482
+ "emulators:start" ,
483
+ [ "--only" , "firestore" , "--import" , exportPath ] ,
484
+ ( data ) => {
485
+ return data . indexOf ( ALL_EMULATORS_STARTED_LOG ) > - 1 ;
486
+ }
487
+ ) ;
488
+
489
+ await importCLI . stop ( ) ;
490
+ } ) . timeout ( 2 * TEST_SETUP_TIMEOUT ) ;
491
+ } ) ;
0 commit comments