fix(test-utils): Duplicated subscribers re insertion (#13798)
* fix * Create pink-boats-type.md
This commit is contained in:
1 parent
a34fcfab35
commit
2d1d51a2af
3 files changed
+131
-3
No files matched your search
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"@medusajs/test-utils": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
fix(test-utils): Event subscribers duplicated durin tests
|
||||||
@@ -307,4 +307,120 @@ describe("waitSubscribersExecution", () => {
|
|||||||
clearTimeoutSpy.mockRestore()
|
clearTimeoutSpy.mockRestore()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe("nested wrapper handling", () => {
|
||||||
|
it("should handle multiple consecutive waitSubscribersExecution calls on the same event", async () => {
|
||||||
|
const originalListener = jest.fn().mockResolvedValue("result")
|
||||||
|
eventBus.eventEmitter_.on(TEST_EVENT, originalListener)
|
||||||
|
|
||||||
|
// First wait
|
||||||
|
const wait1 = waitSubscribersExecution(TEST_EVENT, eventBus as any)
|
||||||
|
eventBus.emit(TEST_EVENT, "data1")
|
||||||
|
await wait1
|
||||||
|
|
||||||
|
expect(originalListener).toHaveBeenCalledWith("data1")
|
||||||
|
expect(originalListener).toHaveBeenCalledTimes(1)
|
||||||
|
|
||||||
|
// Second wait on the same event - should still restore properly
|
||||||
|
const wait2 = waitSubscribersExecution(TEST_EVENT, eventBus as any)
|
||||||
|
eventBus.emit(TEST_EVENT, "data2")
|
||||||
|
await wait2
|
||||||
|
|
||||||
|
expect(originalListener).toHaveBeenCalledWith("data2")
|
||||||
|
expect(originalListener).toHaveBeenCalledTimes(2)
|
||||||
|
|
||||||
|
// Original listener should still be intact and work normally
|
||||||
|
eventBus.emit(TEST_EVENT, "data3")
|
||||||
|
expect(originalListener).toHaveBeenCalledWith("data3")
|
||||||
|
expect(originalListener).toHaveBeenCalledTimes(3)
|
||||||
|
|
||||||
|
// Verify we still have the correct number of listeners
|
||||||
|
const listeners = eventBus.eventEmitter_.listeners(TEST_EVENT)
|
||||||
|
expect(listeners).toHaveLength(1)
|
||||||
|
expect(listeners[0]).toBe(originalListener)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should handle three consecutive waitSubscribersExecution calls", async () => {
|
||||||
|
const originalListener = jest.fn().mockResolvedValue("result")
|
||||||
|
eventBus.eventEmitter_.on(TEST_EVENT, originalListener)
|
||||||
|
|
||||||
|
// First wait
|
||||||
|
const wait1 = waitSubscribersExecution(TEST_EVENT, eventBus as any)
|
||||||
|
eventBus.emit(TEST_EVENT, "data1")
|
||||||
|
await wait1
|
||||||
|
|
||||||
|
// Second wait
|
||||||
|
const wait2 = waitSubscribersExecution(TEST_EVENT, eventBus as any)
|
||||||
|
eventBus.emit(TEST_EVENT, "data2")
|
||||||
|
await wait2
|
||||||
|
|
||||||
|
// Third wait
|
||||||
|
const wait3 = waitSubscribersExecution(TEST_EVENT, eventBus as any)
|
||||||
|
eventBus.emit(TEST_EVENT, "data3")
|
||||||
|
await wait3
|
||||||
|
|
||||||
|
// Verify the original listener is still properly attached
|
||||||
|
const listeners = eventBus.eventEmitter_.listeners(TEST_EVENT)
|
||||||
|
expect(listeners).toHaveLength(1)
|
||||||
|
expect(listeners[0]).toBe(originalListener)
|
||||||
|
|
||||||
|
// Verify it still works
|
||||||
|
eventBus.emit(TEST_EVENT, "data4")
|
||||||
|
expect(originalListener).toHaveBeenCalledWith("data4")
|
||||||
|
expect(originalListener).toHaveBeenCalledTimes(4)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should handle multiple listeners with consecutive waits", async () => {
|
||||||
|
const listener1 = jest.fn().mockResolvedValue("result1")
|
||||||
|
const listener2 = jest.fn().mockResolvedValue("result2")
|
||||||
|
|
||||||
|
eventBus.eventEmitter_.on(TEST_EVENT, listener1)
|
||||||
|
eventBus.eventEmitter_.on(TEST_EVENT, listener2)
|
||||||
|
|
||||||
|
// First wait
|
||||||
|
const wait1 = waitSubscribersExecution(TEST_EVENT, eventBus as any)
|
||||||
|
eventBus.emit(TEST_EVENT, "data1")
|
||||||
|
await wait1
|
||||||
|
|
||||||
|
expect(listener1).toHaveBeenCalledWith("data1")
|
||||||
|
expect(listener2).toHaveBeenCalledWith("data1")
|
||||||
|
|
||||||
|
// Second wait
|
||||||
|
const wait2 = waitSubscribersExecution(TEST_EVENT, eventBus as any)
|
||||||
|
eventBus.emit(TEST_EVENT, "data2")
|
||||||
|
await wait2
|
||||||
|
|
||||||
|
expect(listener1).toHaveBeenCalledWith("data2")
|
||||||
|
expect(listener2).toHaveBeenCalledWith("data2")
|
||||||
|
|
||||||
|
// Verify both original listeners are still properly attached
|
||||||
|
const listeners = eventBus.eventEmitter_.listeners(TEST_EVENT)
|
||||||
|
expect(listeners).toHaveLength(2)
|
||||||
|
expect(listeners[0]).toBe(listener1)
|
||||||
|
expect(listeners[1]).toBe(listener2)
|
||||||
|
|
||||||
|
// Verify they still work normally
|
||||||
|
eventBus.emit(TEST_EVENT, "data3")
|
||||||
|
expect(listener1).toHaveBeenCalledWith("data3")
|
||||||
|
expect(listener2).toHaveBeenCalledWith("data3")
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should not add undefined listener when originalListener chain ends", async () => {
|
||||||
|
// This tests the edge case where listener.originalListener might be undefined
|
||||||
|
const originalListener = jest.fn().mockResolvedValue("result")
|
||||||
|
eventBus.eventEmitter_.on(TEST_EVENT, originalListener)
|
||||||
|
|
||||||
|
const wait1 = waitSubscribersExecution(TEST_EVENT, eventBus as any)
|
||||||
|
eventBus.emit(TEST_EVENT, "data1")
|
||||||
|
await wait1
|
||||||
|
|
||||||
|
// Verify we have exactly one listener (the original)
|
||||||
|
const listeners = eventBus.eventEmitter_.listeners(TEST_EVENT)
|
||||||
|
expect(listeners).toHaveLength(1)
|
||||||
|
|
||||||
|
// Verify it's not undefined
|
||||||
|
expect(listeners[0]).toBeDefined()
|
||||||
|
expect(listeners[0]).toBe(originalListener)
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
@@ -99,6 +99,7 @@ const doWaitSubscribersExecution = (
|
|||||||
})
|
})
|
||||||
subscriberPromises.push(promise)
|
subscriberPromises.push(promise)
|
||||||
let res: any[] = []
|
let res: any[] = []
|
||||||
|
let cleanupDone = false
|
||||||
|
|
||||||
const newListener = async (...args2: any[]) => {
|
const newListener = async (...args2: any[]) => {
|
||||||
try {
|
try {
|
||||||
@@ -121,14 +122,20 @@ const doWaitSubscribersExecution = (
|
|||||||
nok(error)
|
nok(error)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentCount >= triggerCount) {
|
if (currentCount >= triggerCount && !cleanupDone) {
|
||||||
// As soon as the subscriber is executed the required number of times, we restore the original listener
|
// As soon as the subscriber is executed the required number of times, we restore the original listener
|
||||||
|
cleanupDone = true
|
||||||
eventEmitter.removeListener(eventName, newListener)
|
eventEmitter.removeListener(eventName, newListener)
|
||||||
|
|
||||||
|
// Unwrap to find the true original listener
|
||||||
let listenerToAdd = listener
|
let listenerToAdd = listener
|
||||||
while (listenerToAdd.originalListener) {
|
while (listenerToAdd?.originalListener) {
|
||||||
listenerToAdd = listenerToAdd.originalListener
|
listenerToAdd = listenerToAdd.originalListener
|
||||||
}
|
}
|
||||||
eventEmitter.on(eventName, listenerToAdd)
|
|
||||||
|
if (listenerToAdd) {
|
||||||
|
eventEmitter.on(eventName, listenerToAdd)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user