16
16
*/
17
17
18
18
const { resolve } = require ( 'path' ) ;
19
- const { spawn } = require ( 'child-process-promise' ) ;
19
+ const { spawn, exec } = require ( 'child-process-promise' ) ;
20
20
const chalk = require ( 'chalk' ) ;
21
21
const simpleGit = require ( 'simple-git/promise' ) ;
22
22
@@ -52,35 +52,84 @@ const alwaysRunTestPaths = [
52
52
'integration/webpack'
53
53
] ;
54
54
55
+ /**
56
+ * These files trigger tests in other dirs
57
+ */
58
+ const specialPaths = {
59
+ 'scripts/emulator-testing/emulators/firestore-emulator.ts' : [ 'packages/firestore' ] ,
60
+ 'scripts/emulator-testing/emulators/database-emulator.ts' : [ 'packages/database' ] ,
61
+ 'scripts/emulator-testing/emulators/emulator.ts' : [ 'packages/firestore' , 'packages/database' ] ,
62
+ 'scripts/emulator-testing/firestore-test-runner.ts' : [ 'packages/firestore' ] ,
63
+ 'scripts/emulator-testing/database-test-runner.ts' : [ 'packages/database' ]
64
+ } ;
65
+
55
66
/**
56
67
* Identify modified packages that require tests.
57
68
*/
58
69
async function getChangedPackages ( ) {
70
+ const packageInfo = JSON . parse (
71
+ ( await exec ( 'npx lerna ls --json' , { cwd : root } ) ) . stdout
72
+ ) ;
73
+ const depGraph = JSON . parse (
74
+ ( await exec ( 'npx lerna ls --graph' , { cwd : root } ) ) . stdout
75
+ ) ;
59
76
const diff = await git . diff ( [ '--name-only' , 'origin/master...HEAD' ] ) ;
60
77
const changedFiles = diff . split ( '\n' ) ;
61
78
const changedPackages = { } ;
62
79
for ( const filename of changedFiles ) {
80
+ // Files that trigger full test suite.
63
81
if ( fullTestTriggerFiles . includes ( filename ) ) {
64
82
console . log (
65
83
chalk `{blue Running all tests because ${ filename } was modified.}`
66
84
) ;
67
85
return { testAll : true } ;
68
86
}
87
+ // Files outside a package dir that should trigger its tests.
88
+ if ( specialPaths [ filename ] ) {
89
+ for ( const targetPackage of specialPaths [ filename ] ) {
90
+ changedPackages [ targetPackage ] = 'dependency' ;
91
+ }
92
+ }
93
+ // Check for changed files inside package dirs.
69
94
const match = filename . match ( '^(packages/[a-zA-Z0-9-]+)/.*' ) ;
70
95
if ( match && match [ 1 ] ) {
71
- const pkg = require ( resolve ( root , match [ 1 ] , 'package.json' ) ) ;
72
- if ( pkg && pkg . scripts . test ) {
73
- changedPackages [ match [ 1 ] ] = true ;
96
+ const changedPackage = require ( resolve ( root , match [ 1 ] , 'package.json' ) ) ;
97
+ if ( changedPackage ) {
98
+ if ( changedPackage . scripts . test ) {
99
+ // Add the package itself.
100
+ changedPackages [ match [ 1 ] ] = 'direct' ;
101
+ }
102
+ // Add packages that depend on it.
103
+ for ( const package in depGraph ) {
104
+ if ( depGraph [ package ] . includes ( changedPackage . name ) ) {
105
+ const depData = packageInfo . find ( item => item . name === package ) ;
106
+ if ( depData ) {
107
+ const depPkgJson = require ( resolve (
108
+ depData . location ,
109
+ 'package.json'
110
+ ) ) ;
111
+ if ( depPkgJson && depPkgJson . scripts . test ) {
112
+ const depPath = depData . location . replace ( `${ root } /` , '' ) ;
113
+ if ( ! changedPackages [ depPath ] ) {
114
+ changedPackages [ depPath ] = 'dependency' ;
115
+ }
116
+ }
117
+ }
118
+ }
119
+ }
74
120
}
75
121
}
76
122
}
77
123
if ( Object . keys ( changedPackages ) . length > 0 ) {
78
- return { testAll : false , packageDirs : Object . keys ( changedPackages ) } ;
124
+ return {
125
+ testAll : false ,
126
+ changedPackages
127
+ } ;
79
128
} else {
80
129
console . log (
81
130
chalk `{green No changes detected in any package. Skipping all package-specific tests.}`
82
131
) ;
83
- return { testAll : false , packageDirs : [ ] } ;
132
+ return { testAll : false } ;
84
133
}
85
134
}
86
135
@@ -103,21 +152,28 @@ async function runTests(pathList) {
103
152
104
153
async function main ( ) {
105
154
try {
106
- const { testAll, packageDirs = [ ] } = await getChangedPackages ( ) ;
155
+ const {
156
+ testAll,
157
+ changedPackages = { }
158
+ } = await getChangedPackages ( ) ;
107
159
if ( testAll ) {
108
160
await spawn ( 'yarn' , [ 'test' ] , {
109
161
stdio : 'inherit'
110
162
} ) ;
111
163
} else {
112
164
console . log ( chalk `{blue Running tests in:}` ) ;
113
- for ( const filename of alwaysRunTestPaths ) {
165
+ for ( const filename of alwaysRunTestPaths ) { // array
114
166
console . log ( chalk `{green ${ filename } (always runs)}` ) ;
115
167
}
116
- for ( const filename of packageDirs ) {
117
- console . log ( chalk `{yellow ${ filename } (contains modified files)}` ) ;
168
+ for ( const filename in changedPackages ) { // obj
169
+ if ( changedPackages [ filename ] === 'direct' ) {
170
+ console . log ( chalk `{yellow ${ filename } (contains modified files)}` ) ;
171
+ } else {
172
+ console . log ( chalk `{yellow ${ filename } (depends on modified files)}` ) ;
173
+ }
118
174
}
119
175
await runTests ( alwaysRunTestPaths ) ;
120
- await runTests ( packageDirs ) ;
176
+ await runTests ( Object . keys ( changedPackages ) ) ;
121
177
}
122
178
} catch ( e ) {
123
179
console . error ( e ) ;
0 commit comments