Write the failing tests for direct sign-up to an event
This commit is contained in:
@@ -118,12 +118,14 @@ import { tmpdir } from 'node:os';
|
||||
import { join as joinPath } from 'node:path';
|
||||
import { chromium, type Browser, type Page } from 'playwright';
|
||||
import {
|
||||
appActorUri,
|
||||
attendeesCollectionUri,
|
||||
linkId,
|
||||
MEMBER_URN_PREFIX,
|
||||
memberUrnOf,
|
||||
participationSecretOf,
|
||||
participationsCollectionOf,
|
||||
postOutboxActivity,
|
||||
recordUri,
|
||||
asRecord,
|
||||
type ApodsSession,
|
||||
@@ -1291,6 +1293,49 @@ async function leaveAfterContact(): Promise<void> {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* A direct sign-up to the event itself (FP-001): Alice posts a Join naming E, the way
|
||||
* the app does; her participations collection then lists E, under the same audience as
|
||||
* a meeting point membership — her /contacts group only.
|
||||
*/
|
||||
async function directSignup(): Promise<void> {
|
||||
const G = 'direct sign-up to E (Alice; Bob her contact, Carol not)';
|
||||
const E = (): string => need(S.E, 'E');
|
||||
const listsE = async (): Promise<{ ok: boolean; items: string[] }> => {
|
||||
const alice = need(S.alice, 'Alice');
|
||||
const uri = need(await ownParticipations(alice), 'her participations collection');
|
||||
const r = await refIn(uri, E(), true, alice.token);
|
||||
return { ok: r.ok, items: r.items };
|
||||
};
|
||||
await m.hard('direct.join', G, 'Alice posts a Join naming E, to the app actor alone; her own participations collection lists E', 'items ∋ E within 30 s (her read)', async () => {
|
||||
await postOutboxActivity(need(S.alice, 'Alice'), 'Join', E(), appActorUri(config));
|
||||
const r = await listsE();
|
||||
return { ok: r.ok, actual: `items=${JSON.stringify(r.items)}` };
|
||||
});
|
||||
await m.hard('direct.non-contact-refused', G, "a direct sign-up is not listable by a non-contact: Carol is refused Alice's participations collection although it now lists E (URI handed out of band)", 'refused (403, or the pod\'s 404 while Alice reads it 200)', async () => {
|
||||
const alice = need(S.alice, 'Alice');
|
||||
const listed = await listsE();
|
||||
need(listed.ok, 'the direct sign-up landed (direct.join)');
|
||||
const refusal = await collectionRefusal(need(await ownParticipations(alice), 'her participations collection'), need(S.carol, 'Carol').token, alice, AUTHN);
|
||||
return { ok: refusal.ok, actual: refusal.actual };
|
||||
});
|
||||
await m.hard('direct.contact-lists', G, "a contact lists the direct sign-ups: Bob, her contact, reads Alice's participations collection (linked from her profile) and finds E", '200, items ∋ E', async () => {
|
||||
need(S.contacts, 'the contact pair (contact.accepted)');
|
||||
const profile = need(await profileUriOf(need(S.alice, 'Alice').webId), "the profile Alice's public actor document links");
|
||||
const link = need(participationsCollectionOf(parseJson((await http('GET', profile, { token: need(S.bob, 'Bob').token })).text)), "the participations link on Alice's profile, read by Bob");
|
||||
const r = await poll(() => http('GET', link, { token: need(S.bob, 'Bob').token }), v => v.status === 200 && itemUris(parseJson(v.text)).includes(E()), 30000);
|
||||
const items = itemUris(parseJson(r.text));
|
||||
return { ok: r.status === 200 && items.includes(E()), actual: `HTTP ${r.status} items=${JSON.stringify(items)}` };
|
||||
});
|
||||
await m.hard('direct.leave', G, 'Alice posts a Leave naming E: her participations collection no longer lists it (the group leaves the event as it found it)', 'items ∌ E within 30 s (her read)', async () => {
|
||||
const alice = need(S.alice, 'Alice');
|
||||
await postOutboxActivity(alice, 'Leave', E(), appActorUri(config));
|
||||
const uri = need(await ownParticipations(alice), 'her participations collection');
|
||||
const r = await refIn(uri, E(), false, alice.token);
|
||||
return { ok: r.ok, actual: `HTTP ${r.status} items=${JSON.stringify(r.items)}` };
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Who reads a person's participations is her /contacts WAC group, through ONE
|
||||
@@ -1845,6 +1890,7 @@ async function cleanupAccounts(): Promise<void> {
|
||||
await contactChannel();
|
||||
await afterContact();
|
||||
await leaveAfterContact();
|
||||
await directSignup();
|
||||
await visibility();
|
||||
await forgedContact();
|
||||
await contactChanges();
|
||||
|
||||
Reference in New Issue
Block a user