This is an automated email from the ASF dual-hosted git repository. github-merge-queue[bot] pushed a commit to branch gh-readonly-queue/main/pr-6633-4a3f06d9ae65730020702309a3ed4d7aa3719044 in repository https://gitbox.apache.org/repos/asf/texera.git
commit 13609a6c8a887666112cf9031b40bdee144a9030 Author: Matthew B. <[email protected]> AuthorDate: Mon Jul 20 15:06:51 2026 -0700 test(frontend): add unit tests for assertion utilities (#6633) ### What changes were proposed in this PR? - Add `frontend/src/app/common/util/assert.spec.ts`, a new Vitest spec for `assert.ts`, which previously had no dedicated unit tests. - Cover all seven exports: assertType, assert, isType, asType, isNull, isNotNull, and nonNull. - Cover throw-vs-pass paths for the guards and assertions, plus falsy-but-defined values. - Cover primitive vs constructor type checks and the isNull/isNotNull inverse equivalence. ### Any related issues, documentation, discussions? Closes: #6632 ### How was this PR tested? - Run: `cd frontend && node --max-old-space-size=8192 ./node_modules/nx/dist/bin/nx.js test gui --watch=false --include=src/app/common/util/assert.spec.ts`, expect all 22 tests passing. - Test-only change; no production code is modified. ### Was this PR authored or co-authored using generative AI tooling? Co-authored with Claude Opus 4.8 in compliance with ASF --------- Signed-off-by: Xinyuan Lin <[email protected]> Co-authored-by: Xinyuan Lin <[email protected]> Co-authored-by: Copilot Autofix powered by AI <[email protected]> --- frontend/src/app/common/util/assert.spec.ts | 153 ++++++++++++++++++++++++++++ 1 file changed, 153 insertions(+) diff --git a/frontend/src/app/common/util/assert.spec.ts b/frontend/src/app/common/util/assert.spec.ts new file mode 100644 index 0000000000..a151d79b7d --- /dev/null +++ b/frontend/src/app/common/util/assert.spec.ts @@ -0,0 +1,153 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { assert, assertType, asType, isNotNull, isNull, isType, nonNull } from "./assert"; + +describe("assertType", () => { + it("does not throw for defined values, including falsy ones", () => { + expect(() => assertType<number>(0)).not.toThrow(); + expect(() => assertType<string>("")).not.toThrow(); + expect(() => assertType<boolean>(false)).not.toThrow(); + expect(() => assertType<object>({})).not.toThrow(); + }); + + it("throws a TypeError for null", () => { + expect(() => assertType<number>(null)).toThrow(TypeError); + }); + + it("throws a TypeError for undefined", () => { + expect(() => assertType<number>(undefined)).toThrow(TypeError); + }); + + it("reports the received value in the error message", () => { + expect(() => assertType<number>(null)).toThrow("received null"); + expect(() => assertType<number>(undefined)).toThrow("received undefined"); + }); +}); + +describe("assert", () => { + it("does not throw when the condition is true", () => { + expect(() => assert(true)).not.toThrow(); + }); + + it("throws an Error when the condition is false", () => { + expect(() => assert(false)).toThrow(Error); + }); + + it("uses the supplied message on failure", () => { + expect(() => assert(false, "boom")).toThrow("boom"); + }); + + it("throws with an empty message when none is provided", () => { + let err: unknown; + try { + assert(false); + } catch (e) { + err = e; + } + expect(err).toBeInstanceOf(Error); + expect((err as Error).message).toBe(""); + }); +}); + +describe("isType", () => { + it("matches primitive types by typeof", () => { + expect(isType(1, "number")).toBe(true); + expect(isType("x", "string")).toBe(true); + expect(isType(true, "boolean")).toBe(true); + }); + + it("returns false when the primitive type does not match", () => { + expect(isType("1", "number")).toBe(false); + expect(isType(1, "string")).toBe(false); + expect(isType(0, "boolean")).toBe(false); + }); + + it("matches instances via instanceof for constructor types", () => { + expect(isType(new Date(), Date)).toBe(true); + expect(isType([], Array)).toBe(true); + }); + + it("returns false for instances of an unrelated constructor", () => { + expect(isType({}, Date)).toBe(false); + expect(isType(new Date(), Array)).toBe(false); + }); +}); + +describe("asType", () => { + it("returns the value unchanged when the type matches", () => { + expect(asType(5, "number")).toBe(5); + const date = new Date(); + expect(asType(date, Date)).toBe(date); + }); + + it("throws a TypeError when the type does not match", () => { + expect(() => asType("nope", "number")).toThrow(TypeError); + expect(() => asType({}, Date)).toThrow(TypeError); + }); +}); + +describe("isNull", () => { + it("returns true for null and undefined", () => { + expect(isNull(null)).toBe(true); + expect(isNull(undefined)).toBe(true); + }); + + it("returns false for defined values, including falsy ones", () => { + expect(isNull(0)).toBe(false); + expect(isNull("")).toBe(false); + expect(isNull(false)).toBe(false); + }); +}); + +describe("isNotNull", () => { + it("returns false for null and undefined", () => { + expect(isNotNull(null)).toBe(false); + expect(isNotNull(undefined)).toBe(false); + }); + + it("returns true for defined values, including falsy ones", () => { + expect(isNotNull(0)).toBe(true); + expect(isNotNull("")).toBe(true); + expect(isNotNull(false)).toBe(true); + }); + + it("is the logical inverse of isNull", () => { + for (const value of [null, undefined, 0, "", false, {}, []]) { + expect(isNotNull(value)).toBe(!isNull(value)); + } + }); +}); + +describe("nonNull", () => { + it("returns the value unchanged for defined values", () => { + expect(nonNull(0)).toBe(0); + expect(nonNull("")).toBe(""); + const obj = { a: 1 }; + expect(nonNull(obj)).toBe(obj); + }); + + it("throws a TypeError for null", () => { + expect(() => nonNull(null)).toThrow(TypeError); + }); + + it("throws a TypeError for undefined", () => { + expect(() => nonNull(undefined)).toThrow(TypeError); + }); +});
