/** * Spec-conformance pins for SegmenterFormatter — Zod rejection paths, * Intl.RangeError mapping, OTel emission, and cache reuse semantics. */ import { I18N_CODES, I18nError } from "@suaveplan/i18n-shared"; import { describe, expect, expectTypeOf, it } from "@suaveplan/testing/runner"; import { clearSegmenterCache, SegmenterFormatter, segmentText, } from "./formatter/formatter.js"; import type { SegmenterFormatterOptions, SegmenterGranularity, } from "./formatter.types.js"; import { getSegmenterMetricsState, resetSegmenterMetricsState, } from "./observability/observability.js"; describe("SegmenterFormatter spec-conformance", () => { it("rejects non-object options shape (no path → field='options')", { timeout: 5000, }, () => { try { // @ts-expect-error wrong type for safeParse segmentText("a", "en-GB", "not-an-object"); expect.fail("expected throw"); } catch (err) { expect(err).toBeInstanceOf(I18nError); expect((err as I18nError).code).toBe( I18N_CODES.INVALID_FORMATTER_OPTIONS ); expect((err as I18nError).context).toMatchObject({ field: "options", }); } }); it("rejects unknown granularity with INVALID_FORMATTER_OPTIONS", { timeout: 5000, }, () => { try { new SegmenterFormatter({ granularity: "magic" as never }); expect.fail("expected throw"); } catch (err) { expect(err).toBeInstanceOf(I18nError); expect((err as I18nError).code).toBe( I18N_CODES.INVALID_FORMATTER_OPTIONS ); expect((err as I18nError).context).toMatchObject({ field: "granularity", }); } }); it("maps Intl RangeError to UNSUPPORTED_LOCALE", { timeout: 5000, }, () => { clearSegmenterCache(); try { segmentText("a", "en US"); expect.fail("expected throw"); } catch (err) { expect(err).toBeInstanceOf(I18nError); expect((err as I18nError).code).toBe(I18N_CODES.UNSUPPORTED_LOCALE); } }); it("reuses cached Intl.Segmenter on identical key", { timeout: 5000, }, () => { clearSegmenterCache(); resetSegmenterMetricsState(); segmentText("a", "en-GB"); segmentText("a", "en-GB"); const state = getSegmenterMetricsState(); expect(state.cacheHitSamples).toHaveLength(1); expect(state.cacheHitSamples[0]?.attributes.formatter).toBe( "segmenter" ); }); it("does not reuse cache across distinct granularities", { timeout: 5000, }, () => { clearSegmenterCache(); resetSegmenterMetricsState(); segmentText("a b", "en-GB", { granularity: "grapheme" }); segmentText("a b", "en-GB", { granularity: "word" }); const state = getSegmenterMetricsState(); expect(state.cacheHitSamples).toHaveLength(0); }); it("records a duration_ms sample per call with locale + granularity", { timeout: 5000, }, () => { clearSegmenterCache(); resetSegmenterMetricsState(); segmentText("hello", "en-GB", { granularity: "word" }); const state = getSegmenterMetricsState(); expect(state.durationSamples).toHaveLength(1); expect(state.durationSamples[0]?.attributes).toMatchObject({ locale: "en-GB", granularity: "word", }); }); it("defaults granularity to 'grapheme' when omitted", { timeout: 5000, }, () => { clearSegmenterCache(); resetSegmenterMetricsState(); segmentText("ab", "en-GB"); const state = getSegmenterMetricsState(); expect(state.durationSamples[0]?.attributes.granularity).toBe( "grapheme" ); }); it("granularity field of options matches SegmenterGranularity", { timeout: 5000, }, () => { expectTypeOf().toEqualTypeOf< SegmenterGranularity | undefined >(); }); });