|
11 | 11 |
|
12 | 12 | import type {Graph, TransformResultDependency} from '../types.flow';
|
13 | 13 |
|
| 14 | +import CountingSet from '../../lib/CountingSet'; |
14 | 15 | import nullthrows from 'nullthrows';
|
15 | 16 |
|
16 | 17 | const {
|
@@ -202,7 +203,7 @@ async function traverseDependencies(paths, graph, options) {
|
202 | 203 | );
|
203 | 204 | const actualInverseDependencies = new Map();
|
204 | 205 | for (const [path, module] of graph.dependencies) {
|
205 |
| - actualInverseDependencies.set(path, module.inverseDependencies); |
| 206 | + actualInverseDependencies.set(path, new Set(module.inverseDependencies)); |
206 | 207 | }
|
207 | 208 | expect(actualInverseDependencies).toEqual(expectedInverseDependencies);
|
208 | 209 |
|
@@ -314,7 +315,7 @@ it('should populate all the inverse dependencies', async () => {
|
314 | 315 |
|
315 | 316 | expect(
|
316 | 317 | nullthrows(graph.dependencies.get('/bar')).inverseDependencies,
|
317 |
| - ).toEqual(new Set(['/foo', '/bundle'])); |
| 318 | + ).toEqual(new CountingSet(['/foo', '/bundle'])); |
318 | 319 | });
|
319 | 320 |
|
320 | 321 | it('should return an empty result when there are no changes', async () => {
|
@@ -501,7 +502,7 @@ describe('edge cases', () => {
|
501 | 502 |
|
502 | 503 | expect(
|
503 | 504 | nullthrows(graph.dependencies.get('/foo')).inverseDependencies,
|
504 |
| - ).toEqual(new Set(['/bundle', '/baz'])); |
| 505 | + ).toEqual(new CountingSet(['/baz', '/bundle'])); |
505 | 506 | });
|
506 | 507 |
|
507 | 508 | it('should handle renames correctly', async () => {
|
@@ -2049,7 +2050,7 @@ describe('reorderGraph', () => {
|
2049 | 2050 | getSource: () => Buffer.from('// source'),
|
2050 | 2051 | // NOTE: inverseDependencies is traversal state/output, not input, so we
|
2051 | 2052 | // don't pre-populate it.
|
2052 |
| - inverseDependencies: new Set(), |
| 2053 | + inverseDependencies: new CountingSet(), |
2053 | 2054 | });
|
2054 | 2055 |
|
2055 | 2056 | const graph = createGraph({
|
@@ -2168,3 +2169,99 @@ describe('optional dependencies', () => {
|
2168 | 2169 | ).rejects.toThrow();
|
2169 | 2170 | });
|
2170 | 2171 | });
|
| 2172 | + |
| 2173 | +describe('parallel edges', () => { |
| 2174 | + it('add twice w/ same key, build and remove once', async () => { |
| 2175 | + // Create a second edge between /foo and /bar. |
| 2176 | + Actions.addDependency('/foo', '/bar', undefined); |
| 2177 | + |
| 2178 | + await initialTraverseDependencies(graph, options); |
| 2179 | + |
| 2180 | + const fooDeps = nullthrows(graph.dependencies.get('/foo')).dependencies; |
| 2181 | + const fooDepsResolved = [...fooDeps.values()].map(dep => dep.absolutePath); |
| 2182 | + // We dedupe the dependencies because they have the same `name`. |
| 2183 | + expect(fooDepsResolved).toEqual(['/bar', '/baz']); |
| 2184 | + |
| 2185 | + // Remove one of the edges between /foo and /bar (arbitrarily) |
| 2186 | + Actions.removeDependency('/foo', '/bar'); |
| 2187 | + |
| 2188 | + expect( |
| 2189 | + getPaths(await traverseDependencies([...files], graph, options)), |
| 2190 | + ).toEqual({ |
| 2191 | + added: new Set(), |
| 2192 | + modified: new Set(['/foo']), |
| 2193 | + deleted: new Set(), |
| 2194 | + }); |
| 2195 | + }); |
| 2196 | + |
| 2197 | + it('add twice w/ same key, build and remove twice', async () => { |
| 2198 | + // Create a second edge between /foo and /bar. |
| 2199 | + Actions.addDependency('/foo', '/bar', undefined); |
| 2200 | + |
| 2201 | + await initialTraverseDependencies(graph, options); |
| 2202 | + |
| 2203 | + const fooDeps = nullthrows(graph.dependencies.get('/foo')).dependencies; |
| 2204 | + const fooDepsResolved = [...fooDeps.values()].map(dep => dep.absolutePath); |
| 2205 | + // We dedupe the dependencies because they have the same `name`. |
| 2206 | + expect(fooDepsResolved).toEqual(['/bar', '/baz']); |
| 2207 | + |
| 2208 | + // Remove both edges between /foo and /bar |
| 2209 | + Actions.removeDependency('/foo', '/bar'); |
| 2210 | + Actions.removeDependency('/foo', '/bar'); |
| 2211 | + |
| 2212 | + expect( |
| 2213 | + getPaths(await traverseDependencies([...files], graph, options)), |
| 2214 | + ).toEqual({ |
| 2215 | + added: new Set(), |
| 2216 | + modified: new Set(['/foo']), |
| 2217 | + deleted: new Set(['/bar']), |
| 2218 | + }); |
| 2219 | + }); |
| 2220 | + |
| 2221 | + it('add twice w/ different keys, build and remove once', async () => { |
| 2222 | + // Create a second edge between /foo and /bar, with a different `name`. |
| 2223 | + Actions.addDependency('/foo', '/bar', undefined, 'bar-second'); |
| 2224 | + |
| 2225 | + await initialTraverseDependencies(graph, options); |
| 2226 | + |
| 2227 | + const fooDeps = nullthrows(graph.dependencies.get('/foo')).dependencies; |
| 2228 | + const fooDepsResolved = [...fooDeps.values()].map(dep => dep.absolutePath); |
| 2229 | + // We don't dedupe the dependencies because they have different `name`s. |
| 2230 | + expect(fooDepsResolved).toEqual(['/bar', '/baz', '/bar']); |
| 2231 | + |
| 2232 | + // Remove one of the edges between /foo and /bar (arbitrarily) |
| 2233 | + Actions.removeDependency('/foo', '/bar'); |
| 2234 | + |
| 2235 | + expect( |
| 2236 | + getPaths(await traverseDependencies([...files], graph, options)), |
| 2237 | + ).toEqual({ |
| 2238 | + added: new Set(), |
| 2239 | + modified: new Set(['/foo']), |
| 2240 | + deleted: new Set(), |
| 2241 | + }); |
| 2242 | + }); |
| 2243 | + |
| 2244 | + it('add twice w/ different keys, build and remove twice', async () => { |
| 2245 | + // Create a second edge between /foo and /bar, with a different `name`. |
| 2246 | + Actions.addDependency('/foo', '/bar', undefined, 'bar-second'); |
| 2247 | + |
| 2248 | + await initialTraverseDependencies(graph, options); |
| 2249 | + |
| 2250 | + const fooDeps = nullthrows(graph.dependencies.get('/foo')).dependencies; |
| 2251 | + const fooDepsResolved = [...fooDeps.values()].map(dep => dep.absolutePath); |
| 2252 | + // We don't dedupe the dependencies because they have different `name`s. |
| 2253 | + expect(fooDepsResolved).toEqual(['/bar', '/baz', '/bar']); |
| 2254 | + |
| 2255 | + // Remove both edges between /foo and /bar |
| 2256 | + Actions.removeDependency('/foo', '/bar'); |
| 2257 | + Actions.removeDependency('/foo', '/bar'); |
| 2258 | + |
| 2259 | + expect( |
| 2260 | + getPaths(await traverseDependencies([...files], graph, options)), |
| 2261 | + ).toEqual({ |
| 2262 | + added: new Set(), |
| 2263 | + modified: new Set(['/foo']), |
| 2264 | + deleted: new Set(['/bar']), |
| 2265 | + }); |
| 2266 | + }); |
| 2267 | +}); |
0 commit comments