| Safe Haskell | None |
|---|---|
| Language | GHC2021 |
Test.Meetings
Synopsis
- meetingLinkPassword :: String
- testMeetingCreate :: HasCallStack => App ()
- testMeetingMLSAddParticipant :: HasCallStack => App ()
- testMeetingMLSRemoveParticipantEmitsMeetingDelete :: HasCallStack => App ()
- getMeetingIdAndDomain :: HasCallStack => Value -> App (String, String)
- assertConversationMatchesLegacy :: HasCallStack => Value -> App ()
- assertMeetingNotif :: (HasCallStack, MakesValue notif, MakesValue qid) => notif -> qid -> App ()
- defaultMeetingJson :: String -> UTCTime -> UTCTime -> [String] -> Value
- defaultMeetingJsonLegacy :: String -> UTCTime -> UTCTime -> [String] -> Value
- createDefaultMeeting :: (HasCallStack, MakesValue user) => user -> App Value
- testMeetingGetNotFound :: HasCallStack => App ()
- testMeetingsConfigDisabledBlocksCreate :: HasCallStack => App ()
- testMeetingsReadsWhenDisabled :: HasCallStack => App ()
- testMeetingCreatePastStartTime :: HasCallStack => App ()
- testMeetingRecurrence :: HasCallStack => App ()
- testMeetingUpdateNotFound :: HasCallStack => App ()
- testMeetingUpdateUnauthorized :: HasCallStack => App ()
- testMeetingUpdateTzid :: HasCallStack => App ()
- testMeetingListEmpty :: HasCallStack => App ()
- testMeetingListNoMeetings :: HasCallStack => App ()
- testMeetingListMultiple :: HasCallStack => App ()
- testMeetingListPagination :: HasCallStack => App ()
- testMeetingAddInvitation :: HasCallStack => App ()
- testMeetingAddInvitationNotFound :: HasCallStack => App ()
- testMeetingRemoveInvitation :: HasCallStack => App ()
- testMeetingRemoveInvitationNotFound :: HasCallStack => App ()
- testMeetingReplaceInvitation :: HasCallStack => App ()
- testMeetingReplaceInvitationEmpty :: HasCallStack => App ()
- testMeetingReplaceInvitationNotFound :: HasCallStack => App ()
- testMeetingReplaceInvitationUnauthorized :: HasCallStack => App ()
- testMeetingDelete :: HasCallStack => App ()
- testMeetingLifecycleEventsDeliveredToMembers :: HasCallStack => App ()
- testMeetingOriginatingConnectionExcluded :: HasCallStack => App ()
- testMeetingDeleteNotFound :: HasCallStack => App ()
- testMeetingDeleteUnauthorized :: HasCallStack => App ()
- testMeetingCleanup :: HasCallStack => App ()
- waitForCleanupJob :: (HasCallStack, MakesValue domain) => domain -> App ()
- testMeetingExpiration :: HasCallStack => App ()
- testMeetingListRecurringNotExpired :: HasCallStack => App ()
- testMeetingInteropNewToLegacy :: HasCallStack => App ()
- testMeetingInteropLegacyToNew :: HasCallStack => App ()
- testMeetingType :: HasCallStack => App ()
- testMeetingLink :: HasCallStack => App ()
- testMeetingLinkMultiIngress :: HasCallStack => App ()
- testMeetingInteropV18ToV19 :: HasCallStack => App ()
- testMeetingLinkRefresh :: HasCallStack => App ()
- withLicensedBackendFlagsR :: HasCallStack => Bool -> Bool -> Bool -> (BackendResource -> String -> App a) -> App a
- withLicensedBackend :: HasCallStack => (String -> App a) -> App a
- withLicensedBackendR :: HasCallStack => (BackendResource -> String -> App a) -> App a
- withLicensedBackendFlags :: HasCallStack => Bool -> Bool -> Bool -> (String -> App a) -> App a
- licensedPayloadFor :: String -> (Bool, Bool, Bool) -> App Text
- linkKeyAndCode :: String -> (String, String)
- testMeetingJoinByLink :: HasCallStack => App ()
- testMeetingLinkJoin :: HasCallStack => App ()
- testMeetingLinkTempGuest :: HasCallStack => App ()
- testMeetingAccessUpdateRejected :: HasCallStack => App ()
- testMeetingCreatePassword :: HasCallStack => App ()
- testMeetingLinkJoinNotFound :: HasCallStack => App ()
- testMeetingJoinByLinkUnlicensed :: HasCallStack => App ()
Documentation
meetingLinkPassword :: String Source #
Password protecting meeting join links in this module's tests.
testMeetingCreate :: HasCallStack => App () Source #
testMeetingMLSAddParticipant :: HasCallStack => App () Source #
testMeetingMLSRemoveParticipantEmitsMeetingDelete :: HasCallStack => App () Source #
Kicking a member from a meeting conversation must emit a
meeting.delete event targeted at the removed member so their clients drop
the meeting view. Remaining members must not receive it.
getMeetingIdAndDomain :: HasCallStack => Value -> App (String, String) Source #
Helper to extract meetingId and domain from a meeting JSON object
assertConversationMatchesLegacy :: HasCallStack => Value -> App () Source #
On create/update responses, the full conversation object is returned
alongside the legacy qualified_conversation field. This asserts that both
refer to the same conversation.
assertMeetingNotif :: (HasCallStack, MakesValue notif, MakesValue qid) => notif -> qid -> App () Source #
Assert a meeting lifecycle notification carries the meeting's qualified id flat at payload.0.qualified_id and has NO "data" wrapper (proves the no-nesting contract).
defaultMeetingJson :: String -> UTCTime -> UTCTime -> [String] -> Value Source #
Helper to create a default new meeting JSON object
defaultMeetingJsonLegacy :: String -> UTCTime -> UTCTime -> [String] -> Value Source #
Legacy (V15/V16) meeting JSON: carries end_time and no tzid (V17 adds
tzid). Used to exercise the legacy endpoints in interop tests.
createDefaultMeeting :: (HasCallStack, MakesValue user) => user -> App Value Source #
Create a meeting with default times relative to now (starts in one hour, one hour long, no invitees, title "Team Standup") and return the 201 body.
testMeetingGetNotFound :: HasCallStack => App () Source #
testMeetingsReadsWhenDisabled :: HasCallStack => App () Source #
Read endpoints (GET meetingslist, GET meetings{domain}/{id}) treat a
team with the meetings feature disabled as "no meetings" (list -> 200 [],
get -> 404 meeting-not-found) instead of 403 invalid-op, while write
endpoints (POST /meetings) keep the hard gate and still return 403
invalid-op. See WPB-27329.
testMeetingCreatePastStartTime :: HasCallStack => App () Source #
testMeetingRecurrence :: HasCallStack => App () Source #
testMeetingUpdateNotFound :: HasCallStack => App () Source #
testMeetingUpdateUnauthorized :: HasCallStack => App () Source #
testMeetingUpdateTzid :: HasCallStack => App () Source #
WPB-28272: PUT meetings{domain}/{id} accepts an optional tzid and
updates the stored time zone; omitting it (as legacy clients do) keeps the
stored value; an invalid tzid is rejected at decode time.
testMeetingListEmpty :: HasCallStack => App () Source #
testMeetingListNoMeetings :: HasCallStack => App () Source #
testMeetingListMultiple :: HasCallStack => App () Source #
testMeetingListPagination :: HasCallStack => App () Source #
testMeetingAddInvitation :: HasCallStack => App () Source #
testMeetingRemoveInvitation :: HasCallStack => App () Source #
testMeetingReplaceInvitation :: HasCallStack => App () Source #
testMeetingDelete :: HasCallStack => App () Source #
testMeetingLifecycleEventsDeliveredToMembers :: HasCallStack => App () Source #
WPB-27907: meeting lifecycle events are delivered to all conversation
members; only the originating client connection is excluded (no redundant
echo), while the initiator's other client connections and all other members
receive them. This test covers the non-initiator member path: a member who
joined the meeting conversation after creation receives 'meeting.update' and
'meeting.delete'. The originating-client-connection exclusion is covered in
testMeetingOriginatingConnectionExcluded; the multi-member recipient set
is covered at the unit level in Wire.MeetingsSubsystem.InterpreterSpec.
testMeetingDeleteNotFound :: HasCallStack => App () Source #
testMeetingDeleteUnauthorized :: HasCallStack => App () Source #
testMeetingCleanup :: HasCallStack => App () Source #
waitForCleanupJob :: (HasCallStack, MakesValue domain) => domain -> App () Source #
testMeetingExpiration :: HasCallStack => App () Source #
testMeetingInteropNewToLegacy :: HasCallStack => App () Source #
A meeting created via the V19 shape (end_time + tzid + type) is visible
to legacy clients (< V17) with an end_time; V19 reads carry end_time too.
testMeetingInteropLegacyToNew :: HasCallStack => App () Source #
A meeting created via the legacy shape (end_time) is visible to V19
clients with end_time and the injected default tzid (Europe/Berlin).
testMeetingType :: HasCallStack => App () Source #
The V19 meeting object exposes a type field
(immediate or scheduled); type is required on create and not updatable.
testMeetingLink :: HasCallStack => App () Source #
WPB-29361: the V19 meeting object always exposes a link join link
carrying the meeting's join code as key/code query parameters. Creating
a meeting in a mode that cannot produce a link (cassandra-only code store,
or no join-link URI configured for the domain) fails with 500
link-unavailable. Legacy endpoint shapes (V16/V18) never carry link.
testMeetingLinkMultiIngress :: HasCallStack => App () Source #
WPB-29361: in multi-ingress mode a meeting created by a user whose domain
has no configured join-link URI cannot get a link, so creation fails closed
with 500 link-unavailable (the old fallback would have fabricated one).
Holds regardless of code-storage mode.
testMeetingInteropV18ToV19 :: HasCallStack => App () Source #
A meeting created via the V18 shape (no type) is readable via V19 and
carries the stored default type scheduled.
testMeetingLinkRefresh :: HasCallStack => App () Source #
WPB-28216: refreshing a meeting's join link recreates the join code
(rotating the code embedded in the link URL), revokes the meeting
conversation's guest link, and enforces creator-only access.
withLicensedBackendFlagsR :: HasCallStack => Bool -> Bool -> Bool -> (BackendResource -> String -> App a) -> App a Source #
Run the dynamic backend with a licence whose meetings flags are the given
triple (invitation_links, emails_sending, calendars_integration): the CLI's
example payload is patched with the requested flags, so tests can exercise
flag combinations independently (e.g. join links licensed while email
sending is off). Also exposes the backend resource (e.g. for
execSql, which needs the backend's Postgres dbname).
withLicensedBackend :: HasCallStack => (String -> App a) -> App a Source #
Licensed backend with all meetings flags enabled.
withLicensedBackendR :: HasCallStack => (BackendResource -> String -> App a) -> App a Source #
As withLicensedBackendFlags, but also exposes the backend resource (e.g.
for execSql, which needs the backend's Postgres dbname).
withLicensedBackendFlags :: HasCallStack => Bool -> Bool -> Bool -> (String -> App a) -> App a Source #
Run the body against a dynamic backend whose galley is licensed with the given meetings flags.
licensedPayloadFor :: String -> (Bool, Bool, Bool) -> App Text Source #
Produce a base64url licence payload from the licensing CLI's example, with the three meetings flags overwritten by the given triple.
linkKeyAndCode :: String -> (String, String) Source #
Extract the (key, code) query parameters from a meeting join link URL
(…meeting-join?key=<key>&code=<code>&domain=…). The URL contains
exactly one ? and the three known parameters; missing parts yield "".
testMeetingJoinByLink :: HasCallStack => App () Source #
WPB-28216: POST meeting{domain}{key}{code}/join joins a meeting
through its join link for any authenticated local user (re-joining is an
idempotent no-op) and enforces the optional password.
The code value is the rotating capability: stale values (superseded by a
refresh) yield 404.
testMeetingLinkJoin :: HasCallStack => App () Source #
WPB-28989: GET meeting{domain}{key}{code}/code-check checks a
meeting join link unauthenticated (metadata only) and
POST meeting{domain}{key}{code}/join joins the meeting's
conversation. No creator or conversation membership is required;
password-protected links require the matching password on both verbs.
testMeetingLinkTempGuest :: HasCallStack => App () Source #
A temporary guest (brig ephemeral account created via the anonymous
POST /register flow, what the webapp's "Join as Temporary Guest" uses)
can resolve a meeting join link and join the meeting conversation without
being a team member. Refreshing the link rotates the code so the stale
value stops working, while an already-joined guest keeps their membership.
testMeetingAccessUpdateRejected :: HasCallStack => App () Source #
Access-role updates on meeting conversations are rejected: the roles are
owned by the meetings subsystem (the stored GuestAccessRole is what lets
temporary guests join, see WPB-27191), and a client rewrite via
PUT /conversations/{cnv}/access would strip that role.
testMeetingCreatePassword :: HasCallStack => App () Source #
POST /meetings accepts an optional password that
password-protects the join link/code at creation time; short passwords are
rejected at decode time.
testMeetingLinkJoinNotFound :: HasCallStack => App () Source #
testMeetingJoinByLinkUnlicensed :: HasCallStack => App () Source #
WPB-29643: on a deployment whose license does not cover invitation links (the default, unlicensed static backend), both join-by-link verbs return 403 id-feature-error before any link resolution. Meeting creation is NOT gated, and unknown keys do not leak a 404.