All files utils.ts

95.45% Statements 21/22
95.65% Branches 22/23
100% Functions 9/9
95.23% Lines 20/21

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 1776x 6x           4901x             1427x             1427x             6218x                 1425x 1224x   201x             1425x 1224x     1224x             4253x               1120x             1628x 2x   1626x 1626x 108x   1518x                                                                                                                                                                                                
const textEncoder = new TextEncoder();
const textDecoder = new TextDecoder();
 
/**
 * Returns true if `val` is a string
 */
export function isString(val: unknown): val is string {
  return typeof val === "string";
}
 
/**
 * Strip BOM (Byte Order Mark) from a string
 */
function stripBom(str: string): string {
  return str.charCodeAt(0) === 0xfeff ? str.slice(1) : str;
}
 
/**
 * Returns true if `val` is a Uint8Array
 */
function isUint8Array(val: unknown): val is Uint8Array {
  return val instanceof Uint8Array;
}
 
/**
 * Returns true if `val` is a plain object (not a Uint8Array or other special object)
 */
export function isObject(val: unknown): val is Record<string, unknown> {
  return (
    typeof val === "object" && val !== null && !Array.isArray(val) && !(val instanceof Uint8Array)
  );
}
 
/**
 * Cast `input` to a Uint8Array
 */
export function toUint8Array(input: string | Uint8Array): Uint8Array {
  if (isString(input)) {
    return textEncoder.encode(input);
  }
  return input;
}
 
/**
 * Cast `input` to a string, stripping BOM
 */
export function toString(input: string | Uint8Array): string {
  if (isUint8Array(input)) return stripBom(textDecoder.decode(input));
  Iif (typeof input !== "string") {
    throw new TypeError("expected input to be a string or Uint8Array");
  }
  return stripBom(input);
}
 
/**
 * Cast `val` to an array
 */
export function arrayify<T>(val: T | T[] | undefined | null): T[] {
  return val ? (Array.isArray(val) ? val : [val]) : [];
}
 
/**
 * Asserts that `val` is a plain object and returns it typed as Record<string, unknown>
 * If `val` is not a plain object, returns an empty object
 */
export function toRecord(val: unknown): Record<string, unknown> {
  return isObject(val) ? val : {};
}
 
/**
 * Get a string property from an object with a default value
 */
export function getStringProp(obj: unknown, key: string, defaultValue = ""): string {
  if (!isObject(obj)) {
    return defaultValue;
  }
  const value = obj[key];
  if (isString(value)) {
    return value;
  }
  return defaultValue;
}
 
if (import.meta.vitest) {
  describe("utils", () => {
    describe("toRecord", () => {
      it("should return object as-is", () => {
        const obj = { a: 1, b: "hello" };
        expect(toRecord(obj)).toBe(obj);
      });
 
      it("should return empty object for non-objects", () => {
        expect(toRecord(null)).toEqual({});
        expect(toRecord(undefined)).toEqual({});
        expect(toRecord("string")).toEqual({});
        expect(toRecord(123)).toEqual({});
        expect(toRecord([])).toEqual({});
      });
    });
 
    describe("getStringProp", () => {
      it("should return string property value", () => {
        expect(getStringProp({ name: "test" }, "name")).toBe("test");
      });
 
      it("should return default for missing property", () => {
        expect(getStringProp({ other: "value" }, "name")).toBe("");
        expect(getStringProp({ other: "value" }, "name", "default")).toBe("default");
      });
 
      it("should return default for non-string property", () => {
        expect(getStringProp({ count: 42 }, "count")).toBe("");
        expect(getStringProp({ flag: true }, "flag")).toBe("");
      });
 
      it("should return default for non-objects", () => {
        expect(getStringProp(null, "name")).toBe("");
        expect(getStringProp("string", "name")).toBe("");
      });
    });
 
    describe("stripBom", () => {
      it("should strip BOM from string", () => {
        expect(stripBom("\uFEFFhello")).toBe("hello");
      });
 
      it("should return string unchanged if no BOM", () => {
        expect(stripBom("hello")).toBe("hello");
      });
    });
 
    describe("isUint8Array", () => {
      it("should return true for Uint8Array", () => {
        expect(isUint8Array(new Uint8Array([1, 2, 3]))).toBe(true);
      });
 
      it("should return false for string", () => {
        expect(isUint8Array("test")).toBe(false);
      });
    });
 
    describe("isObject", () => {
      it("should return true for plain object", () => {
        expect(isObject({})).toBe(true);
        expect(isObject({ a: 1 })).toBe(true);
      });
 
      it("should return false for array", () => {
        expect(isObject([])).toBe(false);
      });
 
      it("should return false for null", () => {
        expect(isObject(null)).toBe(false);
      });
 
      it("should return false for Uint8Array", () => {
        expect(isObject(new Uint8Array([1, 2, 3]))).toBe(false);
      });
    });
 
    describe("arrayify", () => {
      it("should wrap non-array in array", () => {
        expect(arrayify("test")).toEqual(["test"]);
      });
 
      it("should return array unchanged", () => {
        expect(arrayify(["a", "b"])).toEqual(["a", "b"]);
      });
 
      it("should return empty array for null/undefined", () => {
        expect(arrayify(null)).toEqual([]);
        expect(arrayify(undefined)).toEqual([]);
      });
    });
  });
}