Files
TREK/server/tests/integration/broadcast-parity/user.cases.ts
T
Maurice 72ff9600f4 test(realtime): broadcast parity for every MCP write tool
A suite under tests/integration/broadcast-parity boots the app once per
group, runs a write tool through a real MCP session the way the
assistant attaches the registry, runs its REST twin on a twin scene, and
records every broadcast. Per case it checks the exact events in order and
count, that no MCP broadcast skips a socket (the asking tab hears its own
change), that nothing is sent inside a transaction, that every payload
parses with its registered schema, that REST sends the same sequence to
the same room and recipients, and that MCP's keys cover REST's.

A registry test lists the write tools as an MCP client sees them and
fails on a tool without a row, a stale row, or an exemption without a
reason; exemptions run too and must send nothing, and the tools still
waiting for a case are frozen in a list that may only shrink.

The new events the next changes send are registered now (member:updated,
todo:reordered, trips:changed, settings:updated, tags:changed,
notification:read-all, journey:updated, journey:deleted, atlas:changed);
the client keeps them apart as awaiting a sender, and the journey page
already leaves a journey that journey:deleted says is gone.
2026-10-22 00:03:34 +00:00

141 lines
4.4 KiB
TypeScript

import { holidayCode } from './harness';
import type { CaseGroup, Scene } from './types';
/** A user's own addons: journey, atlas, collections, vacay, dawarich and the school holiday catalog. */
const HOLIDAY_CATALOG = "the admin's school holiday catalog is global: no room, and the registry has no event for it";
const TOKEN_ONLY = 'manages a public link token: nothing on any screen follows it live, so there is nothing to send';
const onJourney = (s: Scene) => ({ journeyId: s.journey.id });
const WINTER = { name: 'Winter', startDate: '2027-02-01', endDate: '2027-02-12' };
export const user: CaseGroup = {
name: 'user',
prefix: 'BCP-USER',
cases: [],
exempt: [
{ tool: 'create_journey_share_link', reason: TOKEN_ONLY, needs: ['journey'], args: onJourney },
{
tool: 'delete_journey_share_link',
reason: TOKEN_ONLY,
needs: ['journey'],
args: onJourney,
first: { tool: 'create_journey_share_link', args: onJourney },
},
{
tool: 'create_manual_school_holiday_country',
reason: HOLIDAY_CATALOG,
actor: 'admin',
args: (s) => ({ code: holidayCode(s.n, 0), name: `Holiday land ${s.n}` }),
},
{
tool: 'create_manual_school_holiday_region',
reason: HOLIDAY_CATALOG,
actor: 'admin',
needs: ['holidayCountry'],
args: (s) => ({ country: s.holidayCountry.code, name: `North ${s.n}`, revision: 0, holidays: [WINTER] }),
},
{
tool: 'update_manual_school_holiday_region',
reason: HOLIDAY_CATALOG,
actor: 'admin',
needs: ['holidayRegion'],
args: (s) => ({
regionId: s.holidayRegion.id,
name: `South ${s.n}`,
revision: s.holidayRegion.revision,
holidays: [WINTER],
}),
},
{
tool: 'delete_manual_school_holiday_region',
reason: HOLIDAY_CATALOG,
actor: 'admin',
needs: ['holidayRegion'],
args: (s) => ({ regionId: s.holidayRegion.id, revision: s.holidayRegion.revision }),
},
{
tool: 'delete_manual_school_holiday_country',
reason: HOLIDAY_CATALOG,
actor: 'admin',
needs: ['holidayCountry'],
args: (s) => ({ code: s.holidayCountry.code }),
},
],
pending: [
'create_bucket_list_item',
'delete_bucket_list_item',
'mark_country_visited',
'unmark_country_visited',
'mark_region_visited',
'unmark_region_visited',
'update_bucket_list_item',
'create_collection',
'update_collection',
'delete_collection',
'reorder_collections',
'save_place_to_collection',
'save_trip_places_to_collection',
'update_collection_place',
'set_collection_place_status',
'set_collection_place_status_from_trip',
'rate_collection_place',
'delete_collection_place',
'create_collection_label',
'update_collection_label',
'delete_collection_label',
'assign_collection_labels',
'invite_to_collection',
'set_collection_member_role',
'remove_collection_member',
'cancel_collection_invite',
'accept_collection_invite',
'decline_collection_invite',
'leave_collection',
'accept_dawarich_suggestion_as_place',
'accept_dawarich_suggestion_as_journal_entry',
'mark_bucket_list_item_visited_from_dawarich',
'dismiss_dawarich_suggestion',
'confirm_bucket_list_visits',
'clear_bucket_list_visit',
'accept_atlas_countries',
'create_journey',
'update_journey',
'restore_journey_suggestions',
'delete_journey',
'add_journey_trip',
'remove_journey_trip',
'create_journey_entry',
'update_journey_entry',
'delete_journey_entry',
'reorder_journey_entries',
'reorder_journey_entry_photos',
'add_journey_contributor',
'update_journey_contributor_role',
'remove_journey_contributor',
'update_journey_preferences',
'add_journey_provider_photos',
'link_trip_journal',
'set_trip_journal_members',
'unlink_trip_journal',
'take_over_journey_day_stays',
'save_journey_recorded_day',
'delete_journey_recorded_day',
'update_vacay_plan',
'set_vacay_color',
'send_vacay_invite',
'accept_vacay_invite',
'decline_vacay_invite',
'cancel_vacay_invite',
'dissolve_vacay_plan',
'add_vacay_year',
'delete_vacay_year',
'toggle_vacay_entry',
'toggle_company_holiday',
'update_vacay_stats',
'add_holiday_calendar',
'update_holiday_calendar',
'delete_holiday_calendar',
'share_vacay_calendar',
'unshare_vacay_calendar',
],
};