import { expect, test } from "vitest" import { ABORT_MANAGER_MODE, AbortManager, all, any, fromAbortFriendlyOptions, fromAbortable, fromWithAbortSignal, getAbortSignal, isAborted, } from "#Source/abort/index.ts" test("getAbortSignal resolves AbortSignal from supported abortables", () => { const abortController = new AbortController() const abortManager = new AbortManager({}) expect(getAbortSignal(abortController.signal)).toBe(abortController.signal) expect(getAbortSignal(abortController)).toBe(abortController.signal) expect(getAbortSignal(abortManager)).toBe(abortManager.abortSignal) }) test("isAborted reflects abort state from abortables", () => { const abortController = new AbortController() expect(isAborted(abortController.signal)).toBe(false) expect(isAborted(abortController)).toBe(false) abortController.abort("stop") expect(isAborted(abortController.signal)).toBe(true) expect(isAborted(abortController)).toBe(true) }) test("AbortManager constructor links upstream abortManager from options", () => { const upstream = new AbortManager({}) const abortManager = new AbortManager({ abortManager: upstream }) expect(abortManager.isAborted()).toBe(false) upstream.abort("upstream") expect(abortManager.isAborted()).toBe(true) }) test("AbortManager.isAborted mirrors internal abortSignal", () => { const abortManager = new AbortManager({}) expect(abortManager.isAborted()).toBe(false) abortManager.abort("done") expect(abortManager.isAborted()).toBe(true) }) test("AbortManager.setMode sets mode and supports chaining", () => { const abortManager = new AbortManager({}) const upstream1 = new AbortController() const upstream2 = new AbortController() const returned = abortManager .setMode(ABORT_MANAGER_MODE.ANY) .addUpstreams([upstream1.signal, upstream2.signal]) expect(returned).toBe(abortManager) upstream1.abort("one") expect(abortManager.isAborted()).toBe(true) }) test("AbortManager.addUpstreams makes manager abort when upstream condition is met", () => { const abortManager = new AbortManager({}) const upstream = new AbortController() abortManager.addUpstreams([upstream.signal]) expect(abortManager.isAborted()).toBe(false) upstream.abort("upstream") expect(abortManager.isAborted()).toBe(true) }) test("AbortManager.removeUpstreams detaches selected upstreams", () => { const abortManager = new AbortManager({}) const upstream1 = new AbortController() const upstream2 = new AbortController() abortManager .setMode(ABORT_MANAGER_MODE.ANY) .addUpstreams([upstream1.signal, upstream2.signal]) .removeUpstreams([upstream1.signal]) upstream1.abort("ignored") expect(abortManager.isAborted()).toBe(false) upstream2.abort("active") expect(abortManager.isAborted()).toBe(true) }) test("AbortManager.removeAllUpstreams detaches all upstreams", () => { const abortManager = new AbortManager({}) const upstream1 = new AbortController() const upstream2 = new AbortController() abortManager .setMode(ABORT_MANAGER_MODE.ANY) .addUpstreams([upstream1.signal, upstream2.signal]) .removeAllUpstreams() upstream1.abort("ignored") upstream2.abort("ignored") expect(abortManager.isAborted()).toBe(false) }) test("AbortManager.tryToAbort evaluates mode conditions", () => { const abortManager = new AbortManager({}) const upstream1 = new AbortController() const upstream2 = new AbortController() abortManager.setMode(ABORT_MANAGER_MODE.ALL).addUpstreams([upstream1.signal, upstream2.signal]) upstream1.abort("first") abortManager.tryToAbort() expect(abortManager.isAborted()).toBe(false) upstream2.abort("second") abortManager.tryToAbort() expect(abortManager.isAborted()).toBe(true) }) test("AbortManager.abort aborts and applies auto-remove policy", () => { class TestAbortManager extends AbortManager { removeAllUpstreamsCalled = 0 override removeAllUpstreams(): this { this.removeAllUpstreamsCalled = this.removeAllUpstreamsCalled + 1 return super.removeAllUpstreams() } } const enabled = new TestAbortManager({ autoRemoveUpstreamsAfterAbort: true }) enabled.addUpstreams([new AbortController().signal]) enabled.abort("enabled") const disabled = new TestAbortManager({ autoRemoveUpstreamsAfterAbort: false }) disabled.addUpstreams([new AbortController().signal]) disabled.abort("disabled") expect(enabled.isAborted()).toBe(true) expect(enabled.removeAllUpstreamsCalled).toBe(1) expect(disabled.isAborted()).toBe(true) expect(disabled.removeAllUpstreamsCalled).toBe(0) }) test("fromAbortable creates manager from a single upstream abortable", () => { const upstream = new AbortController() const abortManager = fromAbortable(upstream) expect(abortManager.isAborted()).toBe(false) upstream.abort("stop") expect(abortManager.isAborted()).toBe(true) }) test("any creates manager that aborts when any upstream aborts", () => { const upstream1 = new AbortController() const upstream2 = new AbortController() const abortManager = any([upstream1.signal, null, undefined, upstream2.signal]) expect(abortManager.isAborted()).toBe(false) upstream1.abort("first") expect(abortManager.isAborted()).toBe(true) }) test("all creates manager that aborts only when all upstreams abort", () => { const upstream1 = new AbortController() const upstream2 = new AbortController() const abortManager = all([upstream1.signal, null, undefined, upstream2.signal]) upstream1.abort("first") expect(abortManager.isAborted()).toBe(false) upstream2.abort("second") expect(abortManager.isAborted()).toBe(true) }) test("fromWithAbortSignal creates manager from options.abortSignal", () => { const upstream = new AbortController() const withSignal = fromWithAbortSignal({ abortSignal: upstream.signal }) const withoutSignal = fromWithAbortSignal({}) expect(withSignal.isAborted()).toBe(false) expect(withoutSignal.isAborted()).toBe(false) upstream.abort("stop") expect(withSignal.isAborted()).toBe(true) expect(withoutSignal.isAborted()).toBe(false) }) test("fromAbortFriendlyOptions creates manager using abort-friendly options", () => { const upstream = new AbortManager({}) const abortManager = fromAbortFriendlyOptions({ abortManager: upstream }) expect(abortManager.isAborted()).toBe(false) upstream.abort("stop") expect(abortManager.isAborted()).toBe(true) })