@company-semantics/contracts 35.0.0 → 35.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/notifications/README.md +21 -19
- package/src/notifications/__tests__/README.md +42 -47
- package/src/notifications/__tests__/__snapshots__/README.md +15 -8
- package/src/notifications/__tests__/__snapshots__/registry.test.ts.snap +31 -0
- package/src/notifications/__tests__/__snapshots__/render-snapshot.test.ts.snap +2 -2
- package/src/notifications/__tests__/context.test.ts +5 -5
- package/src/notifications/__tests__/definition.test.ts +2 -2
- package/src/notifications/__tests__/fixtures.ts +226 -0
- package/src/notifications/__tests__/kinds.test.ts +2 -3
- package/src/notifications/__tests__/registry.test.ts +27 -27
- package/src/notifications/__tests__/render-snapshot.test.ts +10 -6
- package/src/notifications/kinds/README.md +2 -2
- package/src/notifications/render.ts +6 -6
- package/src/notifications/renderers/email/README.md +10 -6
- package/src/notifications/renderers/email/__tests__/README.md +19 -16
- package/src/notifications/renderers/email/__tests__/render.test.ts +44 -36
- package/src/notifications/renderers/email/chat.ts +3 -2
- package/src/notifications/renderers/email/constants.ts +17 -0
- package/src/notifications/renderers/email/index.ts +4 -4
- package/src/notifications/renderers/email/render.ts +15 -2
- package/src/notifications/renderers/email/shells.ts +3 -2
- package/src/notifications/text.ts +2 -2
- package/src/notifications/__tests__/output-parity.golden.ts +0 -363
- package/src/notifications/__tests__/output-parity.test.ts +0 -122
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The "no output change" proof for the multi-channel notification work
|
|
3
|
-
* (ADR-CONTRACTS-086), now closed.
|
|
4
|
-
*
|
|
5
|
-
* The golden was captured from the old email layer at 32.0.0, before any of this
|
|
6
|
-
* existed. This renders the same fixtures through the entry point that replaced
|
|
7
|
-
* it — `renderToChannel(kind, payload, emailRenderer, ctx)`, the whole
|
|
8
|
-
* `compose → Content → Renderer` pipeline — and asserts the same bytes. That
|
|
9
|
-
* comparison is the point of the golden: it is the only thing standing between a
|
|
10
|
-
* refactor of the code that renders real transactional email and a silently lost
|
|
11
|
-
* blank line. Now that `src/email/` is deleted, it is also the only record of
|
|
12
|
-
* what that layer emitted.
|
|
13
|
-
*
|
|
14
|
-
* `renderers/email/__tests__/render.test.ts` proves the RENDERER reproduces the
|
|
15
|
-
* golden from composed content. This proves the ENTRY POINT does, which is the
|
|
16
|
-
* claim a caller actually depends on.
|
|
17
|
-
*
|
|
18
|
-
* There is no fake timer here any more, and that is the improvement being locked
|
|
19
|
-
* in. The old layer read `new Date().getFullYear()` inside `signature()`, so
|
|
20
|
-
* every parity render had to freeze the clock or fail on New Year's Day for
|
|
21
|
-
* calendar reasons alone. The year is now a value in the `RenderContext`, so the
|
|
22
|
-
* golden's clock is just a number — and this file no longer has an opinion about
|
|
23
|
-
* what day it is.
|
|
24
|
-
*/
|
|
25
|
-
|
|
26
|
-
import { describe, expect, it } from "vitest";
|
|
27
|
-
|
|
28
|
-
import { createRenderContext } from "../context";
|
|
29
|
-
import type { RenderContext } from "../context";
|
|
30
|
-
import type { NotificationKind } from "../kinds";
|
|
31
|
-
import { renderEmail, renderToChannel } from "../render";
|
|
32
|
-
import { NOTIFICATION_DEFINITIONS } from "../registry";
|
|
33
|
-
import { emailRenderer } from "../renderers/email";
|
|
34
|
-
import {
|
|
35
|
-
OUTPUT_PARITY_CLOCK,
|
|
36
|
-
OUTPUT_PARITY_FIXTURES,
|
|
37
|
-
OUTPUT_PARITY_GOLDEN,
|
|
38
|
-
fixtureKey,
|
|
39
|
-
} from "./output-parity.golden";
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* The instant the golden was captured under, stated rather than ticked. Only the
|
|
43
|
-
* year is pinned; the brand name comes from `createRenderContext`'s own default,
|
|
44
|
-
* so the golden keeps asserting the real `COMPANY_NAME` rather than a copy of it
|
|
45
|
-
* written here.
|
|
46
|
-
*/
|
|
47
|
-
const GOLDEN_CONTEXT: RenderContext = createRenderContext({
|
|
48
|
-
brand: { copyrightYear: new Date(OUTPUT_PARITY_CLOCK).getUTCFullYear() },
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
const KINDS = Object.keys(NOTIFICATION_DEFINITIONS) as NotificationKind[];
|
|
52
|
-
|
|
53
|
-
describe("email output parity", () => {
|
|
54
|
-
it("has a fixture for every kind that can be rendered", () => {
|
|
55
|
-
// Sourced from the registry rather than the old `IMPLEMENTED_EMAIL_KINDS`:
|
|
56
|
-
// the registry is what a caller starts from now, and it is total, so "every
|
|
57
|
-
// kind the entry point accepts" and "every kind with a fixture" must agree.
|
|
58
|
-
const covered = new Set(OUTPUT_PARITY_FIXTURES.map((f) => f.kind));
|
|
59
|
-
for (const kind of KINDS) {
|
|
60
|
-
expect(covered.has(kind), `missing fixture for ${kind}`).toBe(true);
|
|
61
|
-
}
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
it("golden covers exactly the fixtures — no missing or orphaned entries", () => {
|
|
65
|
-
const expected = OUTPUT_PARITY_FIXTURES.map((f) =>
|
|
66
|
-
fixtureKey(f.kind, f.name),
|
|
67
|
-
);
|
|
68
|
-
expect(new Set(expected).size, "fixture keys must be unique").toBe(
|
|
69
|
-
expected.length,
|
|
70
|
-
);
|
|
71
|
-
expect(Object.keys(OUTPUT_PARITY_GOLDEN).sort()).toEqual(expected.sort());
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
it("golden was captured under the frozen clock", () => {
|
|
75
|
-
// Guards the context above: if the golden had been captured under a
|
|
76
|
-
// different year, every case below would fail for calendar reasons.
|
|
77
|
-
const year = new Date(OUTPUT_PARITY_CLOCK).getUTCFullYear();
|
|
78
|
-
for (const [key, rendered] of Object.entries(OUTPUT_PARITY_GOLDEN)) {
|
|
79
|
-
expect(rendered.text, `${key} text`).toContain(`ⓒ ${year} •`);
|
|
80
|
-
expect(rendered.html, `${key} html`).toContain(`ⓒ ${year} •`);
|
|
81
|
-
}
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
for (const fixture of OUTPUT_PARITY_FIXTURES) {
|
|
85
|
-
const key = fixtureKey(fixture.kind, fixture.name);
|
|
86
|
-
it(`${key} renders byte-for-byte`, () => {
|
|
87
|
-
// `payload as never`: the fixture call sites are type-checked in the
|
|
88
|
-
// golden module; this only bridges compose's per-kind payload.
|
|
89
|
-
const rendered = renderToChannel(
|
|
90
|
-
fixture.kind,
|
|
91
|
-
fixture.payload as never,
|
|
92
|
-
emailRenderer,
|
|
93
|
-
GOLDEN_CONTEXT,
|
|
94
|
-
);
|
|
95
|
-
expect(rendered).toEqual(OUTPUT_PARITY_GOLDEN[key]);
|
|
96
|
-
});
|
|
97
|
-
}
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
describe("renderEmail", () => {
|
|
101
|
-
it("is renderToChannel through the email renderer, and nothing more", () => {
|
|
102
|
-
const year = new Date(OUTPUT_PARITY_CLOCK).getUTCFullYear();
|
|
103
|
-
for (const fixture of OUTPUT_PARITY_FIXTURES) {
|
|
104
|
-
const key = fixtureKey(fixture.kind, fixture.name);
|
|
105
|
-
expect(
|
|
106
|
-
renderEmail(fixture.kind, fixture.payload as never, {
|
|
107
|
-
brand: { copyrightYear: year },
|
|
108
|
-
}),
|
|
109
|
-
key,
|
|
110
|
-
).toEqual(OUTPUT_PARITY_GOLDEN[key]);
|
|
111
|
-
}
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
it("takes the copyright year from the caller, never from a clock", () => {
|
|
115
|
-
const rendered = renderEmail(
|
|
116
|
-
"auth.otp",
|
|
117
|
-
{ otp: "123456", expiresInMinutes: 10 },
|
|
118
|
-
{ brand: { copyrightYear: 1999 } },
|
|
119
|
-
);
|
|
120
|
-
expect(rendered.text).toContain("ⓒ 1999 •");
|
|
121
|
-
});
|
|
122
|
-
});
|