@rightkit/social-ui 0.0.0-stage → 0.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/CHANGELOG.md +5 -0
- package/LICENSE-APACHE +201 -0
- package/LICENSE-MIT +21 -0
- package/README.md +40 -2
- package/dist/appName.d.ts +2 -0
- package/dist/appName.js +8 -0
- package/dist/components/ScopeSelect.d.ts +7 -0
- package/dist/components/ScopeSelect.js +6 -0
- package/dist/components/Shared.d.ts +34 -0
- package/dist/components/Shared.js +55 -0
- package/dist/data/derive.d.ts +21 -0
- package/dist/data/derive.js +47 -0
- package/dist/data/draftRules.d.ts +10 -0
- package/dist/data/draftRules.js +20 -0
- package/dist/data/engine/engineDataSource.d.ts +194 -0
- package/dist/data/engine/engineDataSource.js +836 -0
- package/dist/data/engine/errors.d.ts +13 -0
- package/dist/data/engine/errors.js +21 -0
- package/dist/data/engine/mapping.d.ts +172 -0
- package/dist/data/engine/mapping.js +1487 -0
- package/dist/data/engine/protocol.d.ts +910 -0
- package/dist/data/engine/protocol.js +67 -0
- package/dist/data/index.d.ts +18 -0
- package/dist/data/index.js +23 -0
- package/dist/data/mock/devSource.d.ts +7 -0
- package/dist/data/mock/devSource.js +10 -0
- package/dist/data/mock/fixtures-analytics.d.ts +7 -0
- package/dist/data/mock/fixtures-analytics.js +123 -0
- package/dist/data/mock/fixtures-briefs.d.ts +4 -0
- package/dist/data/mock/fixtures-briefs.js +230 -0
- package/dist/data/mock/fixtures-content.d.ts +4 -0
- package/dist/data/mock/fixtures-content.js +89 -0
- package/dist/data/mock/fixtures-digests.d.ts +3 -0
- package/dist/data/mock/fixtures-digests.js +40 -0
- package/dist/data/mock/fixtures-drafts.d.ts +2 -0
- package/dist/data/mock/fixtures-drafts.js +74 -0
- package/dist/data/mock/fixtures-gate.d.ts +3 -0
- package/dist/data/mock/fixtures-gate.js +49 -0
- package/dist/data/mock/fixtures-hooks.d.ts +2 -0
- package/dist/data/mock/fixtures-hooks.js +103 -0
- package/dist/data/mock/fixtures-inbox.d.ts +11 -0
- package/dist/data/mock/fixtures-inbox.js +213 -0
- package/dist/data/mock/fixtures-links.d.ts +5 -0
- package/dist/data/mock/fixtures-links.js +89 -0
- package/dist/data/mock/fixtures-memory.d.ts +3 -0
- package/dist/data/mock/fixtures-memory.js +148 -0
- package/dist/data/mock/fixtures-ops.d.ts +15 -0
- package/dist/data/mock/fixtures-ops.js +403 -0
- package/dist/data/mock/fixtures-optimise.d.ts +18 -0
- package/dist/data/mock/fixtures-optimise.js +221 -0
- package/dist/data/mock/fixtures-pacing.d.ts +5 -0
- package/dist/data/mock/fixtures-pacing.js +285 -0
- package/dist/data/mock/fixtures-publish.d.ts +2 -0
- package/dist/data/mock/fixtures-publish.js +129 -0
- package/dist/data/mock/fixtures-store.d.ts +10 -0
- package/dist/data/mock/fixtures-store.js +13 -0
- package/dist/data/mock/fixtures-variants.d.ts +5 -0
- package/dist/data/mock/fixtures-variants.js +138 -0
- package/dist/data/mock/fixtures.d.ts +6 -0
- package/dist/data/mock/fixtures.js +420 -0
- package/dist/data/mock/mockDataSource.d.ts +98 -0
- package/dist/data/mock/mockDataSource.js +903 -0
- package/dist/data/money.d.ts +14 -0
- package/dist/data/money.js +36 -0
- package/dist/data/platforms.d.ts +12 -0
- package/dist/data/platforms.js +26 -0
- package/dist/data/source.d.ts +196 -0
- package/dist/data/source.js +1 -0
- package/dist/data/time.d.ts +23 -0
- package/dist/data/time.js +86 -0
- package/dist/data/types.d.ts +1092 -0
- package/dist/data/types.js +3 -0
- package/dist/env.d.ts +59 -0
- package/dist/hooks/useAsync.d.ts +19 -0
- package/dist/hooks/useAsync.js +25 -0
- package/dist/index.d.ts +56 -0
- package/dist/index.js +58 -0
- package/dist/lib/host.d.ts +21 -0
- package/dist/lib/host.js +32 -0
- package/dist/lib/shell.d.ts +156 -0
- package/dist/lib/shell.js +16 -0
- package/dist/screens/AccountsScreen.d.ts +8 -0
- package/dist/screens/AccountsScreen.js +100 -0
- package/dist/screens/AnalyticsScreen.d.ts +7 -0
- package/dist/screens/AnalyticsScreen.js +64 -0
- package/dist/screens/ApprovalsScreen.d.ts +10 -0
- package/dist/screens/ApprovalsScreen.js +144 -0
- package/dist/screens/BriefsScreen.d.ts +7 -0
- package/dist/screens/BriefsScreen.js +83 -0
- package/dist/screens/CalendarScreen.d.ts +10 -0
- package/dist/screens/CalendarScreen.js +143 -0
- package/dist/screens/CampaignsScreen.d.ts +7 -0
- package/dist/screens/CampaignsScreen.js +52 -0
- package/dist/screens/ChannelMemoryScreen.d.ts +7 -0
- package/dist/screens/ChannelMemoryScreen.js +109 -0
- package/dist/screens/ContentScreen.d.ts +7 -0
- package/dist/screens/ContentScreen.js +64 -0
- package/dist/screens/DigestsScreen.d.ts +7 -0
- package/dist/screens/DigestsScreen.js +53 -0
- package/dist/screens/DraftsScreen.d.ts +10 -0
- package/dist/screens/DraftsScreen.js +108 -0
- package/dist/screens/FailuresScreen.d.ts +8 -0
- package/dist/screens/FailuresScreen.js +111 -0
- package/dist/screens/HookTestsScreen.d.ts +7 -0
- package/dist/screens/HookTestsScreen.js +54 -0
- package/dist/screens/InboxScreen.d.ts +12 -0
- package/dist/screens/InboxScreen.js +76 -0
- package/dist/screens/LinksScreen.d.ts +7 -0
- package/dist/screens/LinksScreen.js +52 -0
- package/dist/screens/PacingScreen.d.ts +7 -0
- package/dist/screens/PacingScreen.js +88 -0
- package/dist/screens/PublishJobsScreen.d.ts +7 -0
- package/dist/screens/PublishJobsScreen.js +66 -0
- package/dist/screens/SuggestionsScreen.d.ts +8 -0
- package/dist/screens/SuggestionsScreen.js +94 -0
- package/dist/screens/TextGateScreen.d.ts +7 -0
- package/dist/screens/TextGateScreen.js +111 -0
- package/dist/screens/ThreadsScreen.d.ts +8 -0
- package/dist/screens/ThreadsScreen.js +113 -0
- package/dist/screens/TypedBriefsScreen.d.ts +7 -0
- package/dist/screens/TypedBriefsScreen.js +75 -0
- package/dist/screens/labels.d.ts +121 -0
- package/dist/screens/labels.js +272 -0
- package/package.json +56 -3
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
export const FIXTURE_DRAFTS = [
|
|
2
|
+
{
|
|
3
|
+
id: "mock-draft-reddit-comment-001",
|
|
4
|
+
channelLabel: "fixture-beta / beta-studio / beta-main",
|
|
5
|
+
platform: "reddit",
|
|
6
|
+
kind: "comment",
|
|
7
|
+
target: "https://www.reddit.com/r/example/comments/mock0001/",
|
|
8
|
+
title: null,
|
|
9
|
+
body: "Disclosure: I run App, so take this with that in mind. The setup in the thread is simple: start with one channel and one account.",
|
|
10
|
+
bodyChars: 0,
|
|
11
|
+
disclosureRequired: true,
|
|
12
|
+
state: "drafted",
|
|
13
|
+
revision: 1,
|
|
14
|
+
postedUrl: null,
|
|
15
|
+
postedAtUtc: null,
|
|
16
|
+
skipReason: null,
|
|
17
|
+
sourceNote: "Invented: a thread asked how the queue works.",
|
|
18
|
+
updatedAtUtc: "2026-10-12T16:05:00Z",
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
id: "mock-draft-x-reply-002",
|
|
22
|
+
channelLabel: "fixture-alpha / alpha-shorts / alpha-main",
|
|
23
|
+
platform: "x",
|
|
24
|
+
kind: "reply",
|
|
25
|
+
target: "https://x.com/example/status/mock0002",
|
|
26
|
+
title: null,
|
|
27
|
+
body: "Thanks for the question. The queue waits for your approval before anything is scheduled.",
|
|
28
|
+
bodyChars: 0,
|
|
29
|
+
disclosureRequired: false,
|
|
30
|
+
state: "approved",
|
|
31
|
+
revision: 2,
|
|
32
|
+
postedUrl: null,
|
|
33
|
+
postedAtUtc: null,
|
|
34
|
+
skipReason: null,
|
|
35
|
+
sourceNote: "Invented: a reply to a question about approvals.",
|
|
36
|
+
updatedAtUtc: "2026-10-12T15:40:00Z",
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
id: "mock-draft-reddit-post-003",
|
|
40
|
+
channelLabel: "fixture-beta / beta-studio / beta-main",
|
|
41
|
+
platform: "reddit",
|
|
42
|
+
kind: "post",
|
|
43
|
+
target: null,
|
|
44
|
+
title: "How we keep a posting queue honest",
|
|
45
|
+
body: "We wrote down the rules for our queue: nothing posts without an approval, and every failure has one next action.",
|
|
46
|
+
bodyChars: 0,
|
|
47
|
+
disclosureRequired: false,
|
|
48
|
+
state: "posted_by_operator",
|
|
49
|
+
revision: 3,
|
|
50
|
+
postedUrl: "https://www.reddit.com/r/example/comments/mock0003/",
|
|
51
|
+
postedAtUtc: "2026-10-12T12:10:00Z",
|
|
52
|
+
skipReason: null,
|
|
53
|
+
sourceNote: "Invented: a post about queue rules.",
|
|
54
|
+
updatedAtUtc: "2026-10-12T12:10:00Z",
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
id: "mock-draft-threads-post-004",
|
|
58
|
+
channelLabel: "fixture-alpha / alpha-shorts / alpha-main",
|
|
59
|
+
platform: "threads",
|
|
60
|
+
kind: "post",
|
|
61
|
+
target: null,
|
|
62
|
+
title: null,
|
|
63
|
+
body: "A short note about why the calendar shows times in each account's own zone.",
|
|
64
|
+
bodyChars: 0,
|
|
65
|
+
disclosureRequired: false,
|
|
66
|
+
state: "skipped",
|
|
67
|
+
revision: 2,
|
|
68
|
+
postedUrl: null,
|
|
69
|
+
postedAtUtc: null,
|
|
70
|
+
skipReason: "Not this week: the note repeats the last post.",
|
|
71
|
+
sourceNote: "Invented: a note about time zones.",
|
|
72
|
+
updatedAtUtc: "2026-10-12T10:20:00Z",
|
|
73
|
+
},
|
|
74
|
+
];
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { SCOPE_ALPHA } from "./fixtures-optimise.js";
|
|
2
|
+
export const FIXTURE_GATE_POLICIES = [
|
|
3
|
+
{
|
|
4
|
+
// The first channel has a policy at revision 3. The second and third channels have none, so the screen
|
|
5
|
+
// shows that nothing can pass there.
|
|
6
|
+
scopeId: SCOPE_ALPHA,
|
|
7
|
+
revision: 3,
|
|
8
|
+
createdAtUtc: "2026-09-15T08:00:00Z",
|
|
9
|
+
bannedPhrases: ["guarantee"],
|
|
10
|
+
stockOpeners: ["Here's", "In this"],
|
|
11
|
+
minWords: 40,
|
|
12
|
+
dashMaxPer100WordsMilli: 1500,
|
|
13
|
+
semicolonMaxPer100WordsMilli: 500,
|
|
14
|
+
varianceMinMilli: 4000,
|
|
15
|
+
varianceMinSentences: 5,
|
|
16
|
+
tricolonMaxPer100SentencesMilli: 20000,
|
|
17
|
+
tricolonMinSentences: 4,
|
|
18
|
+
required: {
|
|
19
|
+
bannedPhrase: true,
|
|
20
|
+
dashDensity: true,
|
|
21
|
+
semicolonDensity: true,
|
|
22
|
+
sentenceLengthVariance: true,
|
|
23
|
+
tricolonFrequency: true,
|
|
24
|
+
stockOpener: true,
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
];
|
|
28
|
+
export const FIXTURE_GATE_RECORDS = [
|
|
29
|
+
{
|
|
30
|
+
// An earlier check, under revision 2: blocked. The record stays as it was written.
|
|
31
|
+
scopeId: SCOPE_ALPHA,
|
|
32
|
+
recordSeq: 1,
|
|
33
|
+
subjectId: "fixture-script-hook-01",
|
|
34
|
+
textHash: "fnv1a128:9f1c0a7e4b2d3c5f8a6e1b0d4c2f7a93",
|
|
35
|
+
policyRevision: 2,
|
|
36
|
+
disposition: "block",
|
|
37
|
+
checkedAtUtc: "2026-10-06T09:00:00Z",
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
// A later recorded check, under revision 3: passed.
|
|
41
|
+
scopeId: SCOPE_ALPHA,
|
|
42
|
+
recordSeq: 2,
|
|
43
|
+
subjectId: "fixture-script-hook-01",
|
|
44
|
+
textHash: "fnv1a128:2b7d4e9f0a1c6b3d8e5f2a7c9b0d4e61",
|
|
45
|
+
policyRevision: 3,
|
|
46
|
+
disposition: "pass",
|
|
47
|
+
checkedAtUtc: "2026-10-07T09:30:00Z",
|
|
48
|
+
},
|
|
49
|
+
];
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { SCOPE_ALPHA, SCOPE_BETA } from "./fixtures-optimise.js";
|
|
2
|
+
export const FIXTURE_HOOK_TESTS = [
|
|
3
|
+
{
|
|
4
|
+
// Decided: opening 2 is promoted, openings 1 and 3 are archived. Each keeps its value and lineage.
|
|
5
|
+
id: "hook-fixture-decided-01",
|
|
6
|
+
scopeId: SCOPE_ALPHA,
|
|
7
|
+
briefRef: "Fixture brief hook-01",
|
|
8
|
+
body: "Fixture body. The first line of each opening is the only thing that changes between trial reels.",
|
|
9
|
+
metric: "views",
|
|
10
|
+
window: "lifetime",
|
|
11
|
+
state: "decided",
|
|
12
|
+
revision: 5,
|
|
13
|
+
winnerIndex: 2,
|
|
14
|
+
decidedAtUtc: "2026-10-07T12:00:00Z",
|
|
15
|
+
createdAtUtc: "2026-10-06T08:00:00Z",
|
|
16
|
+
updatedAtUtc: "2026-10-07T12:00:00Z",
|
|
17
|
+
openings: [
|
|
18
|
+
{
|
|
19
|
+
index: 1,
|
|
20
|
+
text: "Fixture opening one.",
|
|
21
|
+
jobId: "fixture-job-0201",
|
|
22
|
+
boundAtUtc: "2026-10-06T08:45:00Z",
|
|
23
|
+
role: "archived",
|
|
24
|
+
value: "18300",
|
|
25
|
+
observedAtUtc: "2026-10-07T09:10:00Z",
|
|
26
|
+
pullId: "pull-fixture-0301",
|
|
27
|
+
publishedAtUtc: "2026-10-06T08:30:00Z",
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
index: 2,
|
|
31
|
+
text: "Fixture opening two.",
|
|
32
|
+
jobId: "fixture-job-0202",
|
|
33
|
+
boundAtUtc: "2026-10-06T08:35:00Z",
|
|
34
|
+
role: "promoted",
|
|
35
|
+
value: "41250",
|
|
36
|
+
observedAtUtc: "2026-10-07T08:40:00Z",
|
|
37
|
+
pullId: "pull-fixture-0302",
|
|
38
|
+
publishedAtUtc: "2026-10-06T08:20:00Z",
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
index: 3,
|
|
42
|
+
text: "Fixture opening three.",
|
|
43
|
+
jobId: "fixture-job-0203",
|
|
44
|
+
boundAtUtc: "2026-10-06T11:10:00Z",
|
|
45
|
+
role: "archived",
|
|
46
|
+
value: "12940",
|
|
47
|
+
observedAtUtc: "2026-10-07T11:20:00Z",
|
|
48
|
+
pullId: "pull-fixture-0303",
|
|
49
|
+
publishedAtUtc: "2026-10-06T11:00:00Z",
|
|
50
|
+
},
|
|
51
|
+
],
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
// Open: two openings are bound and one is not yet. Nothing has been read or decided.
|
|
55
|
+
id: "hook-fixture-open-01",
|
|
56
|
+
scopeId: SCOPE_BETA,
|
|
57
|
+
briefRef: "Fixture brief hook-02",
|
|
58
|
+
body: "Fixture body for an open test. Three openings, two of them published so far.",
|
|
59
|
+
metric: "views",
|
|
60
|
+
window: "lifetime",
|
|
61
|
+
state: "open",
|
|
62
|
+
revision: 3,
|
|
63
|
+
winnerIndex: null,
|
|
64
|
+
decidedAtUtc: null,
|
|
65
|
+
createdAtUtc: "2026-10-10T07:00:00Z",
|
|
66
|
+
updatedAtUtc: "2026-10-11T09:30:00Z",
|
|
67
|
+
openings: [
|
|
68
|
+
{
|
|
69
|
+
index: 1,
|
|
70
|
+
text: "Fixture open opening one.",
|
|
71
|
+
jobId: "fixture-job-0301",
|
|
72
|
+
boundAtUtc: "2026-10-10T07:30:00Z",
|
|
73
|
+
role: null,
|
|
74
|
+
value: null,
|
|
75
|
+
observedAtUtc: null,
|
|
76
|
+
pullId: null,
|
|
77
|
+
publishedAtUtc: null,
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
index: 2,
|
|
81
|
+
text: "Fixture open opening two.",
|
|
82
|
+
jobId: "fixture-job-0302",
|
|
83
|
+
boundAtUtc: "2026-10-11T09:30:00Z",
|
|
84
|
+
role: null,
|
|
85
|
+
value: null,
|
|
86
|
+
observedAtUtc: null,
|
|
87
|
+
pullId: null,
|
|
88
|
+
publishedAtUtc: null,
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
index: 3,
|
|
92
|
+
text: "Fixture open opening three.",
|
|
93
|
+
jobId: null,
|
|
94
|
+
boundAtUtc: null,
|
|
95
|
+
role: null,
|
|
96
|
+
value: null,
|
|
97
|
+
observedAtUtc: null,
|
|
98
|
+
pullId: null,
|
|
99
|
+
publishedAtUtc: null,
|
|
100
|
+
},
|
|
101
|
+
],
|
|
102
|
+
},
|
|
103
|
+
];
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { InboxEvent, InboxStats, UnreadableRow } from "../types.js";
|
|
2
|
+
export interface FixtureInboxRow {
|
|
3
|
+
event: InboxEvent;
|
|
4
|
+
/** The raw item JSON, as the daemon would keep it. */
|
|
5
|
+
rawJson: string;
|
|
6
|
+
}
|
|
7
|
+
export declare const FIXTURE_INBOX: FixtureInboxRow[];
|
|
8
|
+
/** A row the desktop cannot read: a kind it does not show yet. It stays in the unmatched list, with its raw JSON. */
|
|
9
|
+
export declare const FIXTURE_UNMATCHED_UNREADABLE: UnreadableRow[];
|
|
10
|
+
/** The counts that match the rows above. The whole-store totals include the unreadable row. */
|
|
11
|
+
export declare const FIXTURE_INBOX_STATS: InboxStats;
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import { SCOPE_ALPHA, SCOPE_GAMMA } from "./fixtures-optimise.js";
|
|
2
|
+
function itemJson(item) {
|
|
3
|
+
return JSON.stringify(item, null, 2);
|
|
4
|
+
}
|
|
5
|
+
export const FIXTURE_INBOX = [
|
|
6
|
+
{
|
|
7
|
+
// Newest. Its text is markup, shown as text only.
|
|
8
|
+
event: {
|
|
9
|
+
readable: true,
|
|
10
|
+
eventId: "inbox-fixture-0004",
|
|
11
|
+
scopeId: SCOPE_ALPHA,
|
|
12
|
+
unmatched: false,
|
|
13
|
+
unmatchedReason: null,
|
|
14
|
+
platform: "instagram",
|
|
15
|
+
kind: "comment",
|
|
16
|
+
recipientId: "fixture-ig-alpha",
|
|
17
|
+
platformEventId: "fixture-comment-0004",
|
|
18
|
+
senderId: "fixture-sender-0004",
|
|
19
|
+
text: "<img src=x onerror=alert(1)>",
|
|
20
|
+
eventTimeAsGiven: "2026-10-12T17:55:00+0000",
|
|
21
|
+
oversize: false,
|
|
22
|
+
receivedAtUtc: "2026-10-12T17:56:10Z",
|
|
23
|
+
state: "open",
|
|
24
|
+
stateBy: null,
|
|
25
|
+
stateAtUtc: null,
|
|
26
|
+
stateNote: "",
|
|
27
|
+
},
|
|
28
|
+
rawJson: itemJson({
|
|
29
|
+
id: "fixture-comment-0004",
|
|
30
|
+
from: { id: "fixture-sender-0004" },
|
|
31
|
+
text: "<img src=x onerror=alert(1)>",
|
|
32
|
+
created_time: "2026-10-12T17:55:00+0000",
|
|
33
|
+
}),
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
// A message whose text is a javascript: address, shown as plain text. A person handled it by hand.
|
|
37
|
+
event: {
|
|
38
|
+
readable: true,
|
|
39
|
+
eventId: "inbox-fixture-0003",
|
|
40
|
+
scopeId: SCOPE_ALPHA,
|
|
41
|
+
unmatched: false,
|
|
42
|
+
unmatchedReason: null,
|
|
43
|
+
platform: "instagram",
|
|
44
|
+
kind: "message",
|
|
45
|
+
recipientId: "fixture-ig-alpha",
|
|
46
|
+
platformEventId: "fixture-message-0003",
|
|
47
|
+
senderId: "fixture-sender-0003",
|
|
48
|
+
text: "Where is the link? javascript:void(0)",
|
|
49
|
+
eventTimeAsGiven: "2026-10-12T09:12:00Z",
|
|
50
|
+
oversize: false,
|
|
51
|
+
receivedAtUtc: "2026-10-12T09:12:30Z",
|
|
52
|
+
state: "handled",
|
|
53
|
+
stateBy: "adrian",
|
|
54
|
+
stateAtUtc: "2026-10-12T09:40:00Z",
|
|
55
|
+
stateNote: "Answered by hand on the platform.",
|
|
56
|
+
},
|
|
57
|
+
rawJson: itemJson({
|
|
58
|
+
sender: { id: "fixture-sender-0003" },
|
|
59
|
+
message: { mid: "fixture-message-0003", text: "Where is the link? javascript:void(0)" },
|
|
60
|
+
timestamp: 1791797520000,
|
|
61
|
+
}),
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
// A mention cut to its bound. The raw JSON keeps the whole item.
|
|
65
|
+
event: {
|
|
66
|
+
readable: true,
|
|
67
|
+
eventId: "inbox-fixture-0002",
|
|
68
|
+
scopeId: SCOPE_ALPHA,
|
|
69
|
+
unmatched: false,
|
|
70
|
+
unmatchedReason: null,
|
|
71
|
+
platform: "instagram",
|
|
72
|
+
kind: "mention",
|
|
73
|
+
recipientId: "fixture-ig-alpha",
|
|
74
|
+
platformEventId: "fixture-mention-0002",
|
|
75
|
+
senderId: "fixture-sender-0002",
|
|
76
|
+
text: "Fixture mention of the channel. The daemon cut this text to its bound",
|
|
77
|
+
eventTimeAsGiven: "2026-10-11T18:40:00Z",
|
|
78
|
+
oversize: true,
|
|
79
|
+
receivedAtUtc: "2026-10-11T18:41:05Z",
|
|
80
|
+
state: "ignored",
|
|
81
|
+
stateBy: "adrian",
|
|
82
|
+
stateAtUtc: "2026-10-11T19:00:00Z",
|
|
83
|
+
stateNote: "Not a question. No reply needed.",
|
|
84
|
+
},
|
|
85
|
+
rawJson: itemJson({
|
|
86
|
+
id: "fixture-mention-0002",
|
|
87
|
+
from: { id: "fixture-sender-0002" },
|
|
88
|
+
text: "Fixture mention of the channel. The daemon cut this text to its bound, and this copy keeps the whole item.",
|
|
89
|
+
}),
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
// An event with no text, sender or time: the empty fields are said so on the screen.
|
|
93
|
+
event: {
|
|
94
|
+
readable: true,
|
|
95
|
+
eventId: "inbox-fixture-0001",
|
|
96
|
+
scopeId: SCOPE_ALPHA,
|
|
97
|
+
unmatched: false,
|
|
98
|
+
unmatchedReason: null,
|
|
99
|
+
platform: "instagram",
|
|
100
|
+
kind: "other",
|
|
101
|
+
recipientId: "fixture-ig-alpha",
|
|
102
|
+
platformEventId: null,
|
|
103
|
+
senderId: null,
|
|
104
|
+
text: null,
|
|
105
|
+
eventTimeAsGiven: null,
|
|
106
|
+
oversize: false,
|
|
107
|
+
receivedAtUtc: "2026-10-10T07:00:00Z",
|
|
108
|
+
state: "open",
|
|
109
|
+
stateBy: null,
|
|
110
|
+
stateAtUtc: null,
|
|
111
|
+
stateNote: "",
|
|
112
|
+
},
|
|
113
|
+
rawJson: itemJson({ id: "fixture-other-0001", field: "read" }),
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
// Unmatched: no stored account has this recipient id.
|
|
117
|
+
event: {
|
|
118
|
+
readable: true,
|
|
119
|
+
eventId: "inbox-fixture-0005",
|
|
120
|
+
scopeId: null,
|
|
121
|
+
unmatched: true,
|
|
122
|
+
unmatchedReason: "no_account",
|
|
123
|
+
platform: "facebook",
|
|
124
|
+
kind: "comment",
|
|
125
|
+
recipientId: "fixture-fb-unknown",
|
|
126
|
+
platformEventId: "fixture-comment-0005",
|
|
127
|
+
senderId: "fixture-sender-0005",
|
|
128
|
+
text: "Fixture comment on a page App does not hold",
|
|
129
|
+
eventTimeAsGiven: "2026-10-12T12:00:00Z",
|
|
130
|
+
oversize: false,
|
|
131
|
+
receivedAtUtc: "2026-10-12T12:00:20Z",
|
|
132
|
+
state: "open",
|
|
133
|
+
stateBy: null,
|
|
134
|
+
stateAtUtc: null,
|
|
135
|
+
stateNote: "",
|
|
136
|
+
},
|
|
137
|
+
rawJson: itemJson({ id: "fixture-comment-0005", from: { id: "fixture-sender-0005" } }),
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
// Unmatched: two stored accounts share this handle, so the daemon refuses to guess.
|
|
141
|
+
event: {
|
|
142
|
+
readable: true,
|
|
143
|
+
eventId: "inbox-fixture-0007",
|
|
144
|
+
scopeId: null,
|
|
145
|
+
unmatched: true,
|
|
146
|
+
unmatchedReason: "ambiguous_account",
|
|
147
|
+
platform: "instagram",
|
|
148
|
+
kind: "mention",
|
|
149
|
+
recipientId: "fixture-ig-shared",
|
|
150
|
+
platformEventId: "fixture-mention-0007",
|
|
151
|
+
senderId: "fixture-sender-0007",
|
|
152
|
+
text: "Fixture mention of a handle that two channels hold",
|
|
153
|
+
eventTimeAsGiven: "2026-10-11T08:00:00Z",
|
|
154
|
+
oversize: false,
|
|
155
|
+
receivedAtUtc: "2026-10-11T08:00:09Z",
|
|
156
|
+
state: "open",
|
|
157
|
+
stateBy: null,
|
|
158
|
+
stateAtUtc: null,
|
|
159
|
+
stateNote: "",
|
|
160
|
+
},
|
|
161
|
+
rawJson: itemJson({ id: "fixture-mention-0007", from: { id: "fixture-sender-0007" } }),
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
// Channel GAMMA: one open mention.
|
|
165
|
+
event: {
|
|
166
|
+
readable: true,
|
|
167
|
+
eventId: "inbox-fixture-0006",
|
|
168
|
+
scopeId: SCOPE_GAMMA,
|
|
169
|
+
unmatched: false,
|
|
170
|
+
unmatchedReason: null,
|
|
171
|
+
platform: "threads",
|
|
172
|
+
kind: "mention",
|
|
173
|
+
recipientId: "fixture-th-gamma",
|
|
174
|
+
platformEventId: "fixture-mention-0006",
|
|
175
|
+
senderId: "fixture-sender-0006",
|
|
176
|
+
text: "Fixture gamma mention",
|
|
177
|
+
eventTimeAsGiven: "2026-10-11T08:00:00Z",
|
|
178
|
+
oversize: false,
|
|
179
|
+
receivedAtUtc: "2026-10-11T08:00:05Z",
|
|
180
|
+
state: "open",
|
|
181
|
+
stateBy: null,
|
|
182
|
+
stateAtUtc: null,
|
|
183
|
+
stateNote: "",
|
|
184
|
+
},
|
|
185
|
+
rawJson: itemJson({ id: "fixture-mention-0006", from: { id: "fixture-sender-0006" } }),
|
|
186
|
+
},
|
|
187
|
+
];
|
|
188
|
+
/** A row the desktop cannot read: a kind it does not show yet. It stays in the unmatched list, with its raw JSON. */
|
|
189
|
+
export const FIXTURE_UNMATCHED_UNREADABLE = [
|
|
190
|
+
{
|
|
191
|
+
readable: false,
|
|
192
|
+
reason: 'inbox kind "story_reply" is not shown by the desktop yet',
|
|
193
|
+
rawJson: itemJson({ event_id: "inbox-fixture-0008", kind: "story_reply", recipient_id: "fixture-ig-unknown" }),
|
|
194
|
+
},
|
|
195
|
+
];
|
|
196
|
+
/** The counts that match the rows above. The whole-store totals include the unreadable row. */
|
|
197
|
+
export const FIXTURE_INBOX_STATS = {
|
|
198
|
+
totalEvents: 8,
|
|
199
|
+
unmatchedEvents: 3,
|
|
200
|
+
deliveriesParsed: 6,
|
|
201
|
+
deliveriesUnparseable: 1,
|
|
202
|
+
refusedTotal: 2,
|
|
203
|
+
groups: [
|
|
204
|
+
{ scopeId: SCOPE_ALPHA, kind: "comment", state: "open", count: 1 },
|
|
205
|
+
{ scopeId: SCOPE_ALPHA, kind: "message", state: "handled", count: 1 },
|
|
206
|
+
{ scopeId: SCOPE_ALPHA, kind: "mention", state: "ignored", count: 1 },
|
|
207
|
+
{ scopeId: SCOPE_ALPHA, kind: "other", state: "open", count: 1 },
|
|
208
|
+
{ scopeId: SCOPE_GAMMA, kind: "mention", state: "open", count: 1 },
|
|
209
|
+
{ scopeId: null, kind: "comment", state: "open", count: 1 },
|
|
210
|
+
{ scopeId: null, kind: "mention", state: "open", count: 1 },
|
|
211
|
+
{ scopeId: null, kind: "story_reply", state: "open", count: 1 },
|
|
212
|
+
],
|
|
213
|
+
};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { Campaign, TrackedLink } from "../types.js";
|
|
2
|
+
export declare const FIXTURE_CAMPAIGNS: Campaign[];
|
|
3
|
+
export declare const FIXTURE_LINKS: TrackedLink[];
|
|
4
|
+
/** Visits recorded per link id. A link missing here has no visits, which is a count of zero. */
|
|
5
|
+
export declare const FIXTURE_LINK_VISITS: Record<string, number>;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { SCOPE_ALPHA, SCOPE_BETA } from "./fixtures-optimise.js";
|
|
2
|
+
export const FIXTURE_CAMPAIGNS = [
|
|
3
|
+
{
|
|
4
|
+
// Two links, both with visits.
|
|
5
|
+
id: "fixture-spring-launch",
|
|
6
|
+
scopeId: SCOPE_ALPHA,
|
|
7
|
+
name: "Fixture spring launch",
|
|
8
|
+
utmCampaign: "fixture-spring-launch",
|
|
9
|
+
revision: 3,
|
|
10
|
+
createdAtUtc: "2026-10-01T09:00:00Z",
|
|
11
|
+
updatedAtUtc: "2026-10-09T10:00:00Z",
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
// One link, with zero visits: a normal state.
|
|
15
|
+
id: "fixture-autumn-recap",
|
|
16
|
+
scopeId: SCOPE_ALPHA,
|
|
17
|
+
name: "Fixture autumn recap",
|
|
18
|
+
utmCampaign: "fixture-autumn-recap",
|
|
19
|
+
revision: 1,
|
|
20
|
+
createdAtUtc: "2026-10-02T09:00:00Z",
|
|
21
|
+
updatedAtUtc: "2026-10-02T09:00:00Z",
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
// No links and no visits: the empty state of a campaign.
|
|
25
|
+
id: "fixture-beta-empty",
|
|
26
|
+
scopeId: SCOPE_BETA,
|
|
27
|
+
name: "Fixture beta empty",
|
|
28
|
+
utmCampaign: "fixture-beta-empty",
|
|
29
|
+
revision: 1,
|
|
30
|
+
createdAtUtc: "2026-10-10T09:00:00Z",
|
|
31
|
+
updatedAtUtc: "2026-10-10T09:00:00Z",
|
|
32
|
+
},
|
|
33
|
+
];
|
|
34
|
+
export const FIXTURE_LINKS = [
|
|
35
|
+
{
|
|
36
|
+
id: "lnk_1f2e3d4c5b6a79881a2b3c4d5e6f7081",
|
|
37
|
+
scopeId: SCOPE_ALPHA,
|
|
38
|
+
campaignId: "fixture-spring-launch",
|
|
39
|
+
variantId: "v-a",
|
|
40
|
+
platform: "instagram",
|
|
41
|
+
destination: "https://www.example.com/fixture-landing",
|
|
42
|
+
calendarEntryId: "fixture-entry-0141",
|
|
43
|
+
utmSource: "instagram",
|
|
44
|
+
utmMedium: "social",
|
|
45
|
+
utmCampaign: "fixture-spring-launch",
|
|
46
|
+
utmContent: "v-a",
|
|
47
|
+
finalUrl: "https://www.example.com/fixture-landing?utm_source=instagram&utm_medium=social&utm_campaign=fixture-spring-launch&utm_content=v-a",
|
|
48
|
+
createdAtUtc: "2026-10-02T08:00:00Z",
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
id: "lnk_9a8b7c6d5e4f30211a0b9c8d7e6f5041",
|
|
52
|
+
scopeId: SCOPE_ALPHA,
|
|
53
|
+
campaignId: "fixture-spring-launch",
|
|
54
|
+
variantId: "v-b",
|
|
55
|
+
platform: "instagram",
|
|
56
|
+
destination: "https://www.example.com/fixture-landing",
|
|
57
|
+
calendarEntryId: null,
|
|
58
|
+
utmSource: "instagram",
|
|
59
|
+
utmMedium: "social",
|
|
60
|
+
utmCampaign: "fixture-spring-launch",
|
|
61
|
+
utmContent: "v-b",
|
|
62
|
+
finalUrl: "https://www.example.com/fixture-landing?utm_source=instagram&utm_medium=social&utm_campaign=fixture-spring-launch&utm_content=v-b",
|
|
63
|
+
createdAtUtc: "2026-10-02T08:05:00Z",
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
// A destination with a query and a fragment: the UTM parts join the query and the fragment stays last.
|
|
67
|
+
// It sits in the second campaign, so the channel has three links across two campaigns.
|
|
68
|
+
id: "lnk_0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f",
|
|
69
|
+
scopeId: SCOPE_ALPHA,
|
|
70
|
+
campaignId: "fixture-autumn-recap",
|
|
71
|
+
variantId: "v-a",
|
|
72
|
+
platform: "youtube",
|
|
73
|
+
destination: "https://www.example.com/fixture-landing?ref=fixture#top",
|
|
74
|
+
calendarEntryId: "fixture-entry-0127",
|
|
75
|
+
utmSource: "youtube",
|
|
76
|
+
utmMedium: "social",
|
|
77
|
+
utmCampaign: "fixture-autumn-recap",
|
|
78
|
+
utmContent: "v-a",
|
|
79
|
+
finalUrl: "https://www.example.com/fixture-landing?ref=fixture&utm_source=youtube&utm_medium=social&utm_campaign=fixture-autumn-recap&utm_content=v-a#top",
|
|
80
|
+
createdAtUtc: "2026-10-03T08:00:00Z",
|
|
81
|
+
},
|
|
82
|
+
];
|
|
83
|
+
/** Visits recorded per link id. A link missing here has no visits, which is a count of zero. */
|
|
84
|
+
export const FIXTURE_LINK_VISITS = {
|
|
85
|
+
"lnk_1f2e3d4c5b6a79881a2b3c4d5e6f7081": 412,
|
|
86
|
+
"lnk_9a8b7c6d5e4f30211a0b9c8d7e6f5041": 97,
|
|
87
|
+
// Zero visits: a normal state, shown as 0.
|
|
88
|
+
"lnk_0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f": 0,
|
|
89
|
+
};
|