~james/core

core/web/src/lib/components/profile/vouchRelationship.test.ts -rw-r--r-- 3.0 KiB
452f17b7 — james chore(import): snapshot james.dad.town/core at f70c71c7696a 16 hours ago
                                                                                
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
import { describe, expect, it } from "vitest";
import type { NetworkVouchItem, VouchKind } from "#lib/api/graph.ts";
import {
	denounceStrength,
	directVouch,
	indirectVouches,
	isDirectDenounce,
	isDirectVouch,
	isIndirectDenounce,
	isIndirectVouch,
	isMixed,
	type VouchRelationship,
	vouchBadgeState,
	vouchStrength
} from "#lib/components/profile/vouchRelationship.ts";

const viewer = "did:plc:viewer";
const actor = "did:plc:actor";

const item = (author: string, subject: string, kind: VouchKind): NetworkVouchItem => ({
	actor,
	uri: `at://${author}/org.tangled.graph.vouch/${subject}`,
	value: {
		$type: "org.tangled.graph.vouch",
		kind,
		createdAt: "2026-01-01T00:00:00.000Z"
	}
});

const relationship = (...vouches: NetworkVouchItem[]): VouchRelationship => ({
	viewer,
	actor,
	vouches
});

describe("vouch relationship", () => {
	it("lets a direct vouch beat mixed indirect evidence", () => {
		const value = relationship(
			item(viewer, actor, "vouch"),
			item("did:plc:friend", actor, "vouch"),
			item("did:plc:critic", actor, "denounce")
		);
		expect(isDirectVouch(value)).toBe(true);
		expect(isDirectDenounce(value)).toBe(false);
		expect(isMixed(value)).toBe(false);
		expect(isIndirectVouch(value)).toBe(false);
		expect(isIndirectDenounce(value)).toBe(false);
		expect(vouchBadgeState(value)).toBe("direct-vouch");
	});

	it("derives mixed only from non-viewer incoming vouches", () => {
		const value = relationship(
			item("did:plc:friend", actor, "vouch"),
			item("did:plc:critic", actor, "denounce"),
			item(actor, "did:plc:friend", "vouch")
		);
		expect(indirectVouches(value)).toHaveLength(2);
		expect(isMixed(value)).toBe(true);
		expect(vouchStrength(value)).toBe(1);
		expect(denounceStrength(value)).toBe(1);
		expect(vouchBadgeState(value)).toBe("mixed");
	});

	it.each([
		["direct-denounce", relationship(item(viewer, actor, "denounce"))],
		["indirect-vouch", relationship(item("did:plc:friend", actor, "vouch"))],
		["indirect-denounce", relationship(item("did:plc:critic", actor, "denounce"))]
	] as const)("derives %s", (state, value) => {
		expect(vouchBadgeState(value)).toBe(state);
	});

	it("reads the viewer's own vouch on the actor, with its reason", () => {
		const own: NetworkVouchItem = {
			actor,
			uri: `at://${viewer}/org.tangled.graph.vouch/${actor}`,
			value: {
				$type: "org.tangled.graph.vouch",
				kind: "denounce",
				reason: "reason",
				createdAt: "2026-01-01T00:00:00.000Z"
			}
		};
		expect(directVouch(relationship(own, item("did:plc:friend", actor, "vouch")))).toEqual({
			kind: "denounce",
			reason: "reason"
		});
		expect(directVouch(relationship(item("did:plc:friend", actor, "vouch")))).toBeNull();
		expect(directVouch(relationship(item(actor, viewer, "vouch")))).toBeNull();
	});

	it("ignores outgoing and unrelated vouches", () => {
		const value = relationship(
			item(actor, "did:plc:friend", "vouch"),
			item("did:plc:friend", "did:plc:other", "denounce")
		);
		expect(vouchBadgeState(value)).toBeNull();
		expect(vouchStrength(value)).toBe(0);
		expect(denounceStrength(value)).toBe(0);
	});
});