diff --git a/src/features/application-menu/main/menu-items/get-composite/composite-has-descendant/composite-has-descendant.test.ts b/src/features/application-menu/main/menu-items/get-composite/composite-has-descendant/composite-has-descendant.test.ts new file mode 100644 index 0000000000..b80aa90c4c --- /dev/null +++ b/src/features/application-menu/main/menu-items/get-composite/composite-has-descendant/composite-has-descendant.test.ts @@ -0,0 +1,50 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import type { Composite } from "../get-composite"; +import getComposite from "../get-composite"; +import { compositeHasDescendant } from "./composite-has-descendant"; + +describe("composite-has-descendant, given composite with children and grand children", () => { + let composite: Composite<{ id: string; parentId: string | undefined }>; + + beforeEach(() => { + const items = [ + { id: "some-root-id", parentId: undefined }, + { id: "some-child-item", parentId: "some-root-id" }, + + { + id: "some-grand-child-item", + parentId: "some-child-item", + }, + ]; + + composite = getComposite({ source: items }); + }); + + it("has a child as descendant", () => { + const actual = compositeHasDescendant( + (referenceComposite) => referenceComposite.value.id === "some-child-item", + )(composite); + + expect(actual).toBe(true); + }); + + it("has a grand child as descendant", () => { + const actual = compositeHasDescendant( + (referenceComposite) => referenceComposite.value.id === "some-grand-child-item", + )(composite); + + expect(actual).toBe(true); + }); + + it("does not have an unrelated descendant", () => { + const actual = compositeHasDescendant( + (referenceComposite) => referenceComposite.value.id === "some-unknown-item", + )(composite); + + expect(actual).toBe(false); + }); +}); diff --git a/src/features/application-menu/main/menu-items/get-composite/composite-has-descendant/composite-has-descendant.ts b/src/features/application-menu/main/menu-items/get-composite/composite-has-descendant/composite-has-descendant.ts new file mode 100644 index 0000000000..a622ffaf1a --- /dev/null +++ b/src/features/application-menu/main/menu-items/get-composite/composite-has-descendant/composite-has-descendant.ts @@ -0,0 +1,19 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import type { Composite } from "../get-composite"; + +const compositeHasDescendant = ( + predicate: (referenceComposite: Composite) => boolean, +) => { + const _compositeHasDescendant = (composite: Composite): boolean => + predicate(composite) || + !!composite.children.find((childComposite) => + _compositeHasDescendant(childComposite), + ); + + return _compositeHasDescendant; +}; + +export { compositeHasDescendant };