From a2223ee83d288bb415363f433d4d3f4f9dafb4f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ralph=20K=C3=BCpper?= Date: Fri, 31 Jul 2026 02:46:50 +0200 Subject: [PATCH 1/2] fix(node:test): preserve mock state across tracker resets --- .../perry-runtime/src/node_submodules/test.rs | 22 +++++++++++++------ 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/crates/perry-runtime/src/node_submodules/test.rs b/crates/perry-runtime/src/node_submodules/test.rs index 71eab4fef0..fc79cd8aae 100644 --- a/crates/perry-runtime/src/node_submodules/test.rs +++ b/crates/perry-runtime/src/node_submodules/test.rs @@ -432,6 +432,7 @@ enum MockRestoreTarget { struct MockState { id: i64, + tracked: bool, original: f64, implementation: f64, once: Vec, @@ -701,6 +702,7 @@ fn create_mock_function(original: f64, implementation: f64, restore: MockRestore MOCK_STATES.with(|states| { states.borrow_mut().push(MockState { id, + tracked: true, original: original.get_nanbox_f64(), implementation: implementation.get_nanbox_f64(), once: Vec::new(), @@ -720,6 +722,7 @@ fn create_restore_context(restore: MockRestoreTarget) -> f64 { MOCK_STATES.with(|states| { states.borrow_mut().push(MockState { id, + tracked: true, original: undefined_value(), implementation: undefined_value(), once: Vec::new(), @@ -743,9 +746,9 @@ fn restore_mock_state(id: i64) { let Some(state) = states.iter_mut().find(|state| state.id == id) else { return None; }; - state.implementation = state.original; - state.once.clear(); - reset_mock_state_calls(state); + if matches!(state.restore, MockRestoreTarget::None) { + state.implementation = state.original; + } Some(state.restore.clone()) }); match restore { @@ -1161,27 +1164,32 @@ extern "C" fn mock_property_thunk( } extern "C" fn mock_reset_thunk(_closure: *const ClosureHeader) -> f64 { + restore_tracked_mocks(); MOCK_STATES.with(|states| { for state in states.borrow_mut().iter_mut() { - state.implementation = state.original; - state.once.clear(); - reset_mock_state_calls(state); + state.tracked = false; } }); + crate::timer::js_mock_timers_reset(); undefined_value() } -extern "C" fn mock_restore_all_thunk(_closure: *const ClosureHeader) -> f64 { +fn restore_tracked_mocks() { let ids = MOCK_STATES.with(|states| { states .borrow() .iter() + .filter(|state| state.tracked) .map(|state| state.id) .collect::>() }); for id in ids { restore_mock_state(id); } +} + +extern "C" fn mock_restore_all_thunk(_closure: *const ClosureHeader) -> f64 { + restore_tracked_mocks(); undefined_value() } From 9b85911b3168b0d9b712c33e342bb7048e6eadc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ralph=20K=C3=BCpper?= Date: Fri, 31 Jul 2026 02:47:13 +0200 Subject: [PATCH 2/2] docs(changelog): note node test mock reset parity --- changelog.d/7101-node-test-mock-reset.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 changelog.d/7101-node-test-mock-reset.md diff --git a/changelog.d/7101-node-test-mock-reset.md b/changelog.d/7101-node-test-mock-reset.md new file mode 100644 index 0000000000..34abf20062 --- /dev/null +++ b/changelog.d/7101-node-test-mock-reset.md @@ -0,0 +1,2 @@ +Fixed `node:test` mock tracker reset and restore behavior to preserve call +history, disassociate reset mocks, and reset mock timers like Node.js.