@learncard/network-plugin 3.2.2 → 4.0.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/README.md +18 -123
- package/dist/lcn-plugin.cjs.development.cjs +986 -79
- package/dist/lcn-plugin.cjs.development.cjs.map +3 -3
- package/dist/lcn-plugin.cjs.production.min.cjs +29 -29
- package/dist/lcn-plugin.cjs.production.min.cjs.map +3 -3
- package/dist/lcn-plugin.esm.js +992 -81
- package/dist/lcn-plugin.esm.js.map +3 -3
- package/dist/plugin.d.ts.map +1 -1
- package/dist/test/holder-send.test.d.ts +2 -0
- package/dist/test/holder-send.test.d.ts.map +1 -0
- package/dist/types.d.ts +95 -12
- package/dist/types.d.ts.map +1 -1
- package/package.json +9 -9
- package/src/plugin.ts +604 -38
- package/src/test/campaigns.test.ts +87 -1
- package/src/test/holder-send.test.ts +735 -0
- package/src/test/index.test.ts +71 -0
- package/src/test/refresh-send.test.ts +149 -4
- package/src/types.ts +122 -10
|
@@ -24,6 +24,9 @@ const mockClient = () => ({
|
|
|
24
24
|
},
|
|
25
25
|
campaigns: {
|
|
26
26
|
isAdmin: query(),
|
|
27
|
+
dispatch: mutation(),
|
|
28
|
+
previewDispatch: query(),
|
|
29
|
+
sendTestToMe: mutation(),
|
|
27
30
|
create: mutation(),
|
|
28
31
|
update: mutation(),
|
|
29
32
|
get: query(),
|
|
@@ -34,7 +37,7 @@ const mockClient = () => ({
|
|
|
34
37
|
addAudience: mutation(),
|
|
35
38
|
pageAudience: query(),
|
|
36
39
|
getStats: query(),
|
|
37
|
-
getMyCampaigns: query(),
|
|
40
|
+
getMyCampaigns: { query: vi.fn<() => Promise<unknown>>().mockResolvedValue([]) },
|
|
38
41
|
recordEvent: mutation(),
|
|
39
42
|
enroll: mutation(),
|
|
40
43
|
},
|
|
@@ -43,6 +46,70 @@ const mockClient = () => ({
|
|
|
43
46
|
beforeEach(() => vi.clearAllMocks());
|
|
44
47
|
|
|
45
48
|
describe('campaign network plugin methods', () => {
|
|
49
|
+
it('previews recipients and forwards the reviewed token to dispatch', async () => {
|
|
50
|
+
const client = mockClient();
|
|
51
|
+
vi.mocked(getClient).mockResolvedValue(client as never);
|
|
52
|
+
const { methods } = await getLearnCardNetworkPlugin(wallet, 'https://network.example/trpc');
|
|
53
|
+
await methods.campaignsPreviewDispatch(wallet, 'pilot-clr');
|
|
54
|
+
expect(client.campaigns.previewDispatch.query).toHaveBeenCalledWith({
|
|
55
|
+
campaignId: 'pilot-clr',
|
|
56
|
+
});
|
|
57
|
+
await methods.campaignsDispatch(wallet, 'pilot-clr', {
|
|
58
|
+
expectedPreviewToken: 'a'.repeat(64),
|
|
59
|
+
});
|
|
60
|
+
expect(client.campaigns.dispatch.mutate).toHaveBeenCalledWith({
|
|
61
|
+
campaignId: 'pilot-clr',
|
|
62
|
+
expectedPreviewToken: 'a'.repeat(64),
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it('acknowledges a private test through the existing recordEvent endpoint', async () => {
|
|
67
|
+
const client = mockClient();
|
|
68
|
+
vi.mocked(getClient).mockResolvedValue(client as never);
|
|
69
|
+
const { methods } = await getLearnCardNetworkPlugin(wallet, 'https://network.example/trpc');
|
|
70
|
+
const testId = 'aaaaaaaa-aaaa-4aaa-aaaa-aaaaaaaaaaaa';
|
|
71
|
+
await methods.recordCampaignEvent(wallet, 'pilot-clr', 'shown', testId);
|
|
72
|
+
expect(client.campaigns.recordEvent.mutate).toHaveBeenCalledWith({
|
|
73
|
+
campaignId: 'pilot-clr',
|
|
74
|
+
event: 'shown',
|
|
75
|
+
testId,
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
it('validates campaign messages before returning them to the renderer', async () => {
|
|
79
|
+
const client = mockClient();
|
|
80
|
+
vi.mocked(getClient).mockResolvedValue(client as never);
|
|
81
|
+
const { methods } = await getLearnCardNetworkPlugin(wallet, 'https://network.example/trpc');
|
|
82
|
+
const item = {
|
|
83
|
+
campaign: {
|
|
84
|
+
id: 'pilot-clr',
|
|
85
|
+
message: { id: 'pilot-clr', title: 'Welcome', presentation: 'modal' },
|
|
86
|
+
selfEnroll: false,
|
|
87
|
+
},
|
|
88
|
+
state: { shownCount: 0 },
|
|
89
|
+
};
|
|
90
|
+
client.campaigns.getMyCampaigns.query.mockResolvedValue([item]);
|
|
91
|
+
await expect(methods.getMyCampaigns(wallet)).resolves.toMatchObject([item]);
|
|
92
|
+
for (const invalid of [null, {}, 'invalid']) {
|
|
93
|
+
client.campaigns.getMyCampaigns.query.mockResolvedValue(invalid);
|
|
94
|
+
await expect(methods.getMyCampaigns(wallet)).rejects.toThrow('expected an array');
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
for (const message of [
|
|
98
|
+
null,
|
|
99
|
+
{ ...item.campaign.message, presentation: 'unsupported' },
|
|
100
|
+
{
|
|
101
|
+
...item.campaign.message,
|
|
102
|
+
actions: [{ type: 'navigate', path: 'javascript:alert(1)' }],
|
|
103
|
+
},
|
|
104
|
+
]) {
|
|
105
|
+
client.campaigns.getMyCampaigns.query.mockResolvedValue([
|
|
106
|
+
{ ...item, campaign: { ...item.campaign, message } },
|
|
107
|
+
item,
|
|
108
|
+
]);
|
|
109
|
+
await expect(methods.getMyCampaigns(wallet)).resolves.toMatchObject([item]);
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
|
|
46
113
|
it('forwards every campaign operation to the correct typed procedure', async () => {
|
|
47
114
|
const client = mockClient();
|
|
48
115
|
vi.mocked(getClient).mockResolvedValue(client as never);
|
|
@@ -70,6 +137,8 @@ describe('campaign network plugin methods', () => {
|
|
|
70
137
|
await methods.campaignsAddAudience(wallet, source);
|
|
71
138
|
await methods.campaignsPageAudience(wallet, { campaignId: campaign.id, limit: 20 });
|
|
72
139
|
await methods.campaignsGetStats(wallet, campaign.id);
|
|
140
|
+
await methods.campaignsSendTestToMe(wallet, campaign.id);
|
|
141
|
+
await methods.campaignsDispatch(wallet, campaign.id);
|
|
73
142
|
await methods.getMyCampaigns(wallet);
|
|
74
143
|
await methods.recordCampaignEvent(wallet, campaign.id, 'shown');
|
|
75
144
|
await methods.enrollInCampaign(wallet, campaign.id);
|
|
@@ -91,6 +160,10 @@ describe('campaign network plugin methods', () => {
|
|
|
91
160
|
limit: 20,
|
|
92
161
|
});
|
|
93
162
|
expect(client.campaigns.getStats.query).toHaveBeenCalledWith({ campaignId: campaign.id });
|
|
163
|
+
expect(client.campaigns.sendTestToMe.mutate).toHaveBeenCalledWith({
|
|
164
|
+
campaignId: campaign.id,
|
|
165
|
+
});
|
|
166
|
+
expect(client.campaigns.dispatch.mutate).toHaveBeenCalledWith({ campaignId: campaign.id });
|
|
94
167
|
expect(client.campaigns.getMyCampaigns.query).toHaveBeenCalledWith();
|
|
95
168
|
expect(client.campaigns.recordEvent.mutate).toHaveBeenCalledWith({
|
|
96
169
|
campaignId: campaign.id,
|
|
@@ -115,3 +188,16 @@ describe('campaign network plugin methods', () => {
|
|
|
115
188
|
);
|
|
116
189
|
});
|
|
117
190
|
});
|
|
191
|
+
|
|
192
|
+
describe('announcement preferences', () => {
|
|
193
|
+
it('requires a network profile for private preferences', async () => {
|
|
194
|
+
const client = mockClient();
|
|
195
|
+
client.profile.getProfile.query.mockResolvedValue(undefined);
|
|
196
|
+
vi.mocked(getClient).mockResolvedValue(client as never);
|
|
197
|
+
const { methods } = await getLearnCardNetworkPlugin(wallet, 'https://network.example/trpc');
|
|
198
|
+
await expect(methods.getAnnouncementPreferences(wallet)).rejects.toThrow();
|
|
199
|
+
await expect(
|
|
200
|
+
methods.updateAnnouncementPreferences(wallet, { announcementPushOptOut: true })
|
|
201
|
+
).rejects.toThrow();
|
|
202
|
+
});
|
|
203
|
+
});
|