Skip to content

Commit c165e31

Browse files
authored
Fix MockPlugin clobbering the active mock when a non-active duplicate is removed (#1756)
1 parent df2e758 commit c165e31

2 files changed

Lines changed: 27 additions & 3 deletions

File tree

‎packages/metro-file-map/src/plugins/MockPlugin.js‎

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -147,13 +147,18 @@ export default class MockPlugin
147147
const duplicates = this.#raw.duplicates.get(mockName);
148148
if (duplicates != null) {
149149
const posixRelativePath = normalizePathSeparatorsToPosix(canonicalPath);
150+
const wasActiveMock = this.#raw.mocks.get(mockName) === posixRelativePath;
150151
duplicates.delete(posixRelativePath);
151152
if (duplicates.size === 1) {
152153
this.#raw.duplicates.delete(mockName);
153154
}
154-
// Set the mock to a remaining duplicate. Should never be empty.
155-
const remaining = nullthrows(duplicates.values().next().value);
156-
this.#raw.mocks.set(mockName, remaining);
155+
// Only reassign the active mock if the file we removed *was* the active
156+
// one; otherwise a non-active duplicate's removal would clobber it.
157+
if (wasActiveMock) {
158+
// Set the mock to a remaining duplicate. Should never be empty.
159+
const remaining = nullthrows(duplicates.values().next().value);
160+
this.#raw.mocks.set(mockName, remaining);
161+
}
157162
} else {
158163
this.#raw.mocks.delete(mockName);
159164
}

‎packages/metro-file-map/src/plugins/mocks/__tests__/MockPlugin-test.js‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,25 @@ Duplicate manual mock found for \`foo\`:
107107
});
108108
});
109109

110+
test('removing a non-active duplicate keeps the active mock', () => {
111+
onFileAdded(p('a/__mocks__/foo.js'));
112+
onFileAdded(p('b/__mocks__/foo.js'));
113+
onFileAdded(p('c/__mocks__/foo.js')); // latest wins -> active mock is c
114+
115+
expect(mockMap.getMockModule('foo')).toBe(p('/root/c/__mocks__/foo.js'));
116+
117+
// Remove a NON-active duplicate (b); the active mock (c) must be kept.
118+
mockMap.onChanged({
119+
addedFiles: new Map(),
120+
modifiedFiles: new Map(),
121+
removedFiles: new Map([[p('b/__mocks__/foo.js'), null]]),
122+
addedDirectories: new Set(),
123+
removedDirectories: new Set(),
124+
});
125+
126+
expect(mockMap.getMockModule('foo')).toBe(p('/root/c/__mocks__/foo.js'));
127+
});
128+
110129
test('loads from a snapshot', async () => {
111130
await mockMap.initialize({
112131
files: {

0 commit comments

Comments
 (0)