diff --git a/src/common/utils/get-startable-stoppable.test.ts b/src/common/utils/get-startable-stoppable.test.ts index 24b9e1862d..dc8b24dd43 100644 --- a/src/common/utils/get-startable-stoppable.test.ts +++ b/src/common/utils/get-startable-stoppable.test.ts @@ -2,21 +2,17 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import type { AsyncFnMock } from "@async-fn/jest"; -import asyncFn from "@async-fn/jest"; +import type { StartableStoppable } from "./get-startable-stoppable"; import { getStartableStoppable } from "./get-startable-stoppable"; -import { getPromiseStatus } from "../test-utils/get-promise-status"; -import { flushPromises } from "../test-utils/flush-promises"; describe("getStartableStoppable", () => { - let stopMock: AsyncFnMock<() => Promise>; - let startMock: AsyncFnMock<() => Promise<() => Promise>>; - let actual: { stop: () => Promise; start: () => Promise; started: boolean }; + let stopMock: jest.MockedFunction<() => void>; + let startMock: jest.MockedFunction<() => () => void>; + let actual: StartableStoppable; beforeEach(() => { - stopMock = asyncFn(); - startMock = asyncFn(); - + stopMock = jest.fn(); + startMock = jest.fn().mockImplementation(() => stopMock); actual = getStartableStoppable("some-id", startMock); }); @@ -29,7 +25,7 @@ describe("getStartableStoppable", () => { }); it("when stopping before ever starting, throws", () => { - expect(actual.stop).rejects.toThrow("Tried to stop \"some-id\", but it has not started yet."); + expect(() => actual.stop()).toThrow("Tried to stop \"some-id\", but it is already stopped."); }); it("is not started", () => { @@ -37,199 +33,30 @@ describe("getStartableStoppable", () => { }); describe("when started", () => { - let startPromise: Promise; - beforeEach(() => { - startPromise = actual.start(); + actual.start(); }); - it("starts starting", () => { + it("calls start function", () => { expect(startMock).toHaveBeenCalled(); }); - it("starting does not resolve yet", async () => { - const promiseStatus = await getPromiseStatus(startPromise); - - expect(promiseStatus.fulfilled).toBe(false); + it("is started", () => { + expect(actual.started).toBe(true); }); - it("is not started yet", () => { - expect(actual.started).toBe(false); - }); - - describe("when started again before the start has finished", () => { - let error: Error; - + describe("when stopped", () => { beforeEach(() => { - startMock.mockClear(); - - actual.start().catch((e) => { error = e; }); + actual.stop(); }); - it("does not start starting again", () => { - expect(startMock).not.toHaveBeenCalled(); + it("calls stop function", () => { + expect(stopMock).toBeCalled(); }); - it("throws", () => { - expect(error.message).toBe("Tried to start \"some-id\", but it is already being started."); - }); - }); - - describe("when starting finishes", () => { - beforeEach(async () => { - await startMock.resolve(stopMock); - }); - - it("is started", () => { - expect(actual.started).toBe(true); - }); - - it("starting resolves", async () => { - const promiseStatus = await getPromiseStatus(startPromise); - - expect(promiseStatus.fulfilled).toBe(true); - }); - - it("when started again, throws", () => { - expect(actual.start).rejects.toThrow("Tried to start \"some-id\", but it has already started."); - }); - - it("does not stop yet", () => { - expect(stopMock).not.toHaveBeenCalled(); - }); - - describe("when stopped", () => { - let stopPromise: Promise; - - beforeEach(() => { - stopPromise = actual.stop(); - }); - - it("starts stopping", () => { - expect(stopMock).toHaveBeenCalled(); - }); - - it("stopping does not resolve yet", async () => { - const promiseStatus = await getPromiseStatus(stopPromise); - - expect(promiseStatus.fulfilled).toBe(false); - }); - - it("is not stopped yet", () => { - expect(actual.started).toBe(true); - }); - - describe("when stopping finishes", () => { - beforeEach(async () => { - await stopMock.resolve(); - }); - - it("is not started", () => { - expect(actual.started).toBe(false); - }); - - it("stopping resolves", async () => { - const promiseStatus = await getPromiseStatus(stopPromise); - - expect(promiseStatus.fulfilled).toBe(true); - }); - - it("when stopped again, throws", () => { - expect(actual.stop).rejects.toThrow("Tried to stop \"some-id\", but it has already stopped."); - }); - - describe("when started again", () => { - beforeEach( - () => { - startMock.mockClear(); - - actual.start(); - }); - - it("starts", () => { - expect(startMock).toHaveBeenCalled(); - }); - - it("is not started yet", () => { - expect(actual.started).toBe(false); - }); - - describe("when starting finishes", () => { - beforeEach(async () => { - await startMock.resolve(stopMock); - }); - - it("is started", () => { - expect(actual.started).toBe(true); - }); - - it("when stopped again, starts stopping again", async () => { - stopMock.mockClear(); - - actual.stop(); - - await flushPromises(); - - expect(stopMock).toHaveBeenCalled(); - }); - }); - }); - }); - }); - }); - - describe("when stopped before starting finishes", () => { - let stopPromise: Promise; - - beforeEach(() => { - stopPromise = actual.stop(); - }); - - it("does not resolve yet", async () => { - const promiseStatus = await getPromiseStatus(stopPromise); - - expect(promiseStatus.fulfilled).toBe(false); - }); - - it("is not started yet", () => { + it("is stopped", () => { expect(actual.started).toBe(false); }); - - describe("when starting finishes", () => { - beforeEach(async () => { - await startMock.resolve(stopMock); - }); - - it("starts stopping", () => { - expect(stopMock).toHaveBeenCalled(); - }); - - it("is not stopped yet", () => { - expect(actual.started).toBe(true); - }); - - it("does not resolve yet", async () => { - const promiseStatus = await getPromiseStatus(stopPromise); - - expect(promiseStatus.fulfilled).toBe(false); - }); - - describe("when stopping finishes", () => { - beforeEach(async () => { - await stopMock.resolve(); - }); - - it("is stopped", () => { - expect(actual.started).toBe(false); - }); - - it("resolves", async () => { - const promiseStatus = await getPromiseStatus(stopPromise); - - expect(promiseStatus.fulfilled).toBe(true); - }); - }); - }); }); }); }); diff --git a/src/common/utils/get-startable-stoppable.ts b/src/common/utils/get-startable-stoppable.ts index 5590157ab8..05d8b4d9af 100644 --- a/src/common/utils/get-startable-stoppable.ts +++ b/src/common/utils/get-startable-stoppable.ts @@ -3,58 +3,43 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -type Stopper = () => Promise | void; -type Starter = () => Promise | Stopper; +export type Stopper = () => void; +export type Starter = () => Stopper; -export const getStartableStoppable = ( - id: string, - startAndGetStopCallback: Starter, -) => { +export interface StartableStoppable { + readonly started: boolean; + start: () => void; + stop: () => void; +} + +type StartableStoppableState = "stopped" | "started" | "starting"; + +export function getStartableStoppable(id: string, startAndGetStopper: Starter): StartableStoppable { let stop: Stopper; - let stopped = false; - let started = false; - let starting = false; - let startingPromise: Promise | Stopper; + let state: StartableStoppableState = "stopped"; return { get started() { - return started; + return state === "started"; }, - start: async () => { - if (starting) { - throw new Error(`Tried to start "${id}", but it is already being started.`); + start: () => { + if (state !== "stopped") { + throw new Error(`Tried to start "${id}", but it is already ${state}.`); } - starting = true; - - if (started) { - throw new Error(`Tried to start "${id}", but it has already started.`); - } - - startingPromise = startAndGetStopCallback(); - stop = await startingPromise; - - stopped = false; - started = true; - starting = false; + state = "starting"; + stop = startAndGetStopper(); + state = "started"; }, - stop: async () => { - await startingPromise; - - if (stopped) { - throw new Error(`Tried to stop "${id}", but it has already stopped.`); + stop: () => { + if (state !== "started") { + throw new Error(`Tried to stop "${id}", but it is already ${state}.`); } - if (!started) { - throw new Error(`Tried to stop "${id}", but it has not started yet.`); - } - - await stop(); - - started = false; - stopped = true; + stop(); + state = "stopped"; }, }; -}; +}