@@ -39,14 +39,29 @@ function Watcher(logger, api, files, sources) {
3939 this . isTest = makeTestMatcher ( files , api . excludePatterns ) ;
4040 this . run = function ( specificFiles ) {
4141 logger . reset ( ) ;
42- this . busy = api . run ( specificFiles || files ) . then ( function ( ) {
42+
43+ var runOnlyExclusive = false ;
44+ if ( specificFiles ) {
45+ var exclusiveFiles = specificFiles . filter ( function ( file ) {
46+ return this . filesWithExclusiveTests . indexOf ( file ) !== - 1 ;
47+ } , this ) ;
48+
49+ runOnlyExclusive = exclusiveFiles . length !== this . filesWithExclusiveTests . length ;
50+ }
51+
52+ this . busy = api . run ( specificFiles || files , {
53+ runOnlyExclusive : runOnlyExclusive
54+ } ) . then ( function ( ) {
4355 logger . finish ( ) ;
4456 } , rethrowAsync ) ;
4557 } ;
4658
4759 this . testDependencies = [ ] ;
4860 this . trackTestDependencies ( api , sources ) ;
4961
62+ this . filesWithExclusiveTests = [ ] ;
63+ this . trackExclusivity ( api ) ;
64+
5065 this . dirtyStates = { } ;
5166 this . watchFiles ( files , sources ) ;
5267 this . rerunAll ( ) ;
@@ -85,12 +100,6 @@ Watcher.prototype.trackTestDependencies = function (api, sources) {
85100 } ) ;
86101} ;
87102
88- Watcher . prototype . removeUnlinkedTestDependencies = function ( unlinkedTests ) {
89- unlinkedTests . forEach ( function ( testFile ) {
90- this . updateTestDependencies ( testFile , [ ] ) ;
91- } , this ) ;
92- } ;
93-
94103Watcher . prototype . updateTestDependencies = function ( file , sources ) {
95104 if ( sources . length === 0 ) {
96105 this . testDependencies = this . testDependencies . filter ( function ( dep ) {
@@ -113,6 +122,30 @@ Watcher.prototype.updateTestDependencies = function (file, sources) {
113122 }
114123} ;
115124
125+ Watcher . prototype . trackExclusivity = function ( api ) {
126+ var self = this ;
127+ api . on ( 'stats' , function ( stats ) {
128+ self . updateExclusivity ( stats . file , stats . hasExclusive ) ;
129+ } ) ;
130+ } ;
131+
132+ Watcher . prototype . updateExclusivity = function ( file , hasExclusiveTests ) {
133+ var index = this . filesWithExclusiveTests . indexOf ( file ) ;
134+
135+ if ( hasExclusiveTests && index === - 1 ) {
136+ this . filesWithExclusiveTests . push ( file ) ;
137+ } else if ( ! hasExclusiveTests && index !== - 1 ) {
138+ this . filesWithExclusiveTests . splice ( index , 1 ) ;
139+ }
140+ } ;
141+
142+ Watcher . prototype . cleanUnlinkedTests = function ( unlinkedTests ) {
143+ unlinkedTests . forEach ( function ( testFile ) {
144+ this . updateTestDependencies ( testFile , [ ] ) ;
145+ this . updateExclusivity ( testFile , false ) ;
146+ } , this ) ;
147+ } ;
148+
116149Watcher . prototype . observeStdin = function ( stdin ) {
117150 var self = this ;
118151
@@ -153,7 +186,7 @@ Watcher.prototype.runAfterChanges = function () {
153186 } ) ;
154187 var unlinkedTests = diff ( dirtyTests , addedOrChangedTests ) ;
155188
156- this . removeUnlinkedTestDependencies ( unlinkedTests ) ;
189+ this . cleanUnlinkedTests ( unlinkedTests ) ;
157190 // No need to rerun tests if the only change is that tests were deleted.
158191 if ( unlinkedTests . length === dirtyPaths . length ) {
159192 return ;
0 commit comments