Skip to content

Commit 1d4fcb6

Browse files
committed
test(contracts): split group policy lanes
1 parent 724dd5c commit 1d4fcb6

3 files changed

Lines changed: 181 additions & 0 deletions

File tree

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
import { describe, it } from "vitest";
2+
import { whatsappAccessControlTesting } from "../../../../extensions/whatsapp/api.js";
3+
import { resolveZaloRuntimeGroupPolicy } from "../../../../extensions/zalo/api.js";
4+
import {
5+
expectResolvedGroupPolicyCase,
6+
installChannelRuntimeGroupPolicyFallbackSuite,
7+
} from "../../../../test/helpers/channels/group-policy-contract-suites.js";
8+
import { resolveOpenProviderRuntimeGroupPolicy } from "../../../config/runtime-group-policy.js";
9+
10+
type ResolvedGroupPolicy = ReturnType<typeof resolveOpenProviderRuntimeGroupPolicy>;
11+
12+
function expectResolvedDiscordGroupPolicyCase(params: {
13+
providerConfigPresent: Parameters<
14+
typeof resolveOpenProviderRuntimeGroupPolicy
15+
>[0]["providerConfigPresent"];
16+
groupPolicy: Parameters<typeof resolveOpenProviderRuntimeGroupPolicy>[0]["groupPolicy"];
17+
expected: Pick<ResolvedGroupPolicy, "groupPolicy" | "providerMissingFallbackApplied">;
18+
}) {
19+
expectResolvedGroupPolicyCase(resolveOpenProviderRuntimeGroupPolicy(params), params.expected);
20+
}
21+
22+
describe("channel runtime group policy fallback contract", () => {
23+
describe("slack", () => {
24+
installChannelRuntimeGroupPolicyFallbackSuite({
25+
resolve: resolveOpenProviderRuntimeGroupPolicy,
26+
configuredLabel: "keeps open default when channels.slack is configured",
27+
defaultGroupPolicyUnderTest: "open",
28+
missingConfigLabel: "fails closed when channels.slack is missing and no defaults are set",
29+
missingDefaultLabel: "ignores explicit global defaults when provider config is missing",
30+
});
31+
});
32+
33+
describe("telegram", () => {
34+
installChannelRuntimeGroupPolicyFallbackSuite({
35+
resolve: resolveOpenProviderRuntimeGroupPolicy,
36+
configuredLabel: "keeps open fallback when channels.telegram is configured",
37+
defaultGroupPolicyUnderTest: "disabled",
38+
missingConfigLabel: "fails closed when channels.telegram is missing and no defaults are set",
39+
missingDefaultLabel: "ignores explicit defaults when provider config is missing",
40+
});
41+
});
42+
43+
describe("whatsapp", () => {
44+
installChannelRuntimeGroupPolicyFallbackSuite({
45+
resolve: whatsappAccessControlTesting.resolveWhatsAppRuntimeGroupPolicy,
46+
configuredLabel: "keeps open fallback when channels.whatsapp is configured",
47+
defaultGroupPolicyUnderTest: "disabled",
48+
missingConfigLabel: "fails closed when channels.whatsapp is missing and no defaults are set",
49+
missingDefaultLabel: "ignores explicit global defaults when provider config is missing",
50+
});
51+
});
52+
53+
describe("imessage", () => {
54+
installChannelRuntimeGroupPolicyFallbackSuite({
55+
resolve: resolveOpenProviderRuntimeGroupPolicy,
56+
configuredLabel: "keeps open fallback when channels.imessage is configured",
57+
defaultGroupPolicyUnderTest: "disabled",
58+
missingConfigLabel: "fails closed when channels.imessage is missing and no defaults are set",
59+
missingDefaultLabel: "ignores explicit global defaults when provider config is missing",
60+
});
61+
});
62+
63+
describe("discord", () => {
64+
installChannelRuntimeGroupPolicyFallbackSuite({
65+
resolve: resolveOpenProviderRuntimeGroupPolicy,
66+
configuredLabel: "keeps open default when channels.discord is configured",
67+
defaultGroupPolicyUnderTest: "open",
68+
missingConfigLabel: "fails closed when channels.discord is missing and no defaults are set",
69+
missingDefaultLabel: "ignores explicit global defaults when provider config is missing",
70+
});
71+
72+
it.each([
73+
{
74+
providerConfigPresent: false,
75+
groupPolicy: "disabled",
76+
expected: {
77+
groupPolicy: "disabled",
78+
providerMissingFallbackApplied: false,
79+
},
80+
},
81+
] as const)("respects explicit provider policy %#", (testCase) => {
82+
expectResolvedDiscordGroupPolicyCase(testCase);
83+
});
84+
});
85+
86+
describe("zalo", () => {
87+
installChannelRuntimeGroupPolicyFallbackSuite({
88+
resolve: resolveZaloRuntimeGroupPolicy,
89+
configuredLabel: "keeps open fallback when channels.zalo is configured",
90+
defaultGroupPolicyUnderTest: "open",
91+
missingConfigLabel: "fails closed when channels.zalo is missing and no defaults are set",
92+
missingDefaultLabel: "ignores explicit global defaults when provider config is missing",
93+
});
94+
});
95+
});
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { describe, expect, it } from "vitest";
2+
import { evaluateZaloGroupAccess } from "../../../../extensions/zalo/api.js";
3+
4+
function expectAllowedZaloGroupAccess(params: Parameters<typeof evaluateZaloGroupAccess>[0]) {
5+
expect(evaluateZaloGroupAccess(params)).toMatchObject({
6+
allowed: true,
7+
groupPolicy: "allowlist",
8+
reason: "allowed",
9+
});
10+
}
11+
12+
function expectAllowedZaloGroupAccessCase(
13+
params: Omit<Parameters<typeof evaluateZaloGroupAccess>[0], "groupAllowFrom"> & {
14+
groupAllowFrom: readonly string[];
15+
},
16+
) {
17+
expectAllowedZaloGroupAccess({
18+
...params,
19+
groupAllowFrom: [...params.groupAllowFrom],
20+
});
21+
}
22+
23+
describe("channel runtime group policy provider-owned contract", () => {
24+
describe("zalo", () => {
25+
it.each([
26+
{
27+
providerConfigPresent: true,
28+
configuredGroupPolicy: "allowlist",
29+
defaultGroupPolicy: "open",
30+
groupAllowFrom: ["zl:12345"],
31+
senderId: "12345",
32+
},
33+
] as const)("keeps provider-owned group access evaluation %#", (testCase) => {
34+
expectAllowedZaloGroupAccessCase(testCase);
35+
});
36+
});
37+
});
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import { expect, it } from "vitest";
2+
import { resolveOpenProviderRuntimeGroupPolicy } from "../../../src/config/runtime-group-policy.js";
3+
4+
type ResolvedGroupPolicy = ReturnType<typeof resolveOpenProviderRuntimeGroupPolicy>;
5+
6+
export type RuntimeGroupPolicyResolver = (
7+
params: Parameters<typeof resolveOpenProviderRuntimeGroupPolicy>[0],
8+
) => ReturnType<typeof resolveOpenProviderRuntimeGroupPolicy>;
9+
10+
export function installChannelRuntimeGroupPolicyFallbackSuite(params: {
11+
configuredLabel: string;
12+
defaultGroupPolicyUnderTest: "allowlist" | "disabled" | "open";
13+
missingConfigLabel: string;
14+
missingDefaultLabel: string;
15+
resolve: RuntimeGroupPolicyResolver;
16+
}) {
17+
it(params.missingConfigLabel, () => {
18+
const resolved = params.resolve({
19+
providerConfigPresent: false,
20+
});
21+
expect(resolved.groupPolicy).toBe("allowlist");
22+
expect(resolved.providerMissingFallbackApplied).toBe(true);
23+
});
24+
25+
it(params.configuredLabel, () => {
26+
const resolved = params.resolve({
27+
providerConfigPresent: true,
28+
});
29+
expect(resolved.groupPolicy).toBe("open");
30+
expect(resolved.providerMissingFallbackApplied).toBe(false);
31+
});
32+
33+
it(params.missingDefaultLabel, () => {
34+
const resolved = params.resolve({
35+
providerConfigPresent: false,
36+
defaultGroupPolicy: params.defaultGroupPolicyUnderTest,
37+
});
38+
expect(resolved.groupPolicy).toBe("allowlist");
39+
expect(resolved.providerMissingFallbackApplied).toBe(true);
40+
});
41+
}
42+
43+
export function expectResolvedGroupPolicyCase(
44+
resolved: Pick<ResolvedGroupPolicy, "groupPolicy" | "providerMissingFallbackApplied">,
45+
expected: Pick<ResolvedGroupPolicy, "groupPolicy" | "providerMissingFallbackApplied">,
46+
) {
47+
expect(resolved.groupPolicy).toBe(expected.groupPolicy);
48+
expect(resolved.providerMissingFallbackApplied).toBe(expected.providerMissingFallbackApplied);
49+
}

0 commit comments

Comments
 (0)