- Implement `test_convert_channels_rewrites_account_action_suffixes` to ensure
that account action suffixes are correctly rewritten to user-scoped channels.
- Add `test_convert_channels_drops_account_actions_for_guest` to verify that
account actions are dropped for guests without a user ID.
- Introduce `test_from_payload_does_not_suffix_account_for_nested_user_events`
to confirm that nested user events do not leak action suffixes onto account channels.
- Changed test method names from camelCase to snake_case for consistency.
- Updated assertions to ensure action channels are correctly emitted and filtered.
- Improved readability and maintainability of the test suite by restructuring test cases.
- Introduced ACTION_ALL and SUPPORTED_ACTIONS constants for better action handling.
- Updated channel subscription logic to support action suffixes.
- Added tests for action channel parsing and filtering in MessagingTest.
testAppwriteMigrationUpsertDropsOrphanColumn: adds a column directly on
destination (simulating post-rename orphan or dest-only drift), runs
Upsert, asserts the orphan is dropped and source-declared column
survives. Covers the per-table orphan cleanup fired inside
createRecord before rows land.
testAppwriteMigrationSkipKeepsOrphanColumn: same setup, Skip mode.
Asserts the orphan survives, proving the cleanup is correctly gated
to Upsert only.
Two new E2E tests exercising the schema-tolerance UpdateInPlace path
added in utopia-php/migration's DestinationAppwrite.
testAppwriteMigrationUpsertUpdatesContainerMetadata (positive):
- Fresh migration copies source database + table + column + row to dest.
- Mutates source database name (PUT /databases/:id) and table
name/permissions/rowSecurity/enabled (PUT /tablesdb/:db/tables/:id).
- One-second sleep before mutation ensures source's $updatedAt is
strictly greater than dest's at second granularity (strtotime
comparison).
- Upsert re-migration asserts:
- 'completed' status.
- dest database name matches source's new name.
- dest table name / enabled / rowSecurity match source's new values.
- child row's 'name' attribute is untouched — UpdateInPlace only
rewrites container metadata, not rows.
testAppwriteMigrationSkipPreservesContainerDrift (negative):
- Fresh migration, then mutate BOTH dest (simulating ops tightening
permissions post-migration) and source (divergence).
- Skip re-migration asserts dest kept its tightened values — Skip's
strict "don't touch" contract protects dev→prod cutover workflows
from accidentally wiping ops-side drift on schema re-sync.
Both tests use performMigrationSync for strict 'completed' assertions.
Runtime ~18s combined. Existing testAppwriteMigrationRowsOnDuplicate
and testAppwriteMigrationReRunIsIdempotent regression-tested locally.
utopia-php/migration's DestinationAppwrite now handles schema tolerance on
re-migration (PR #171 on feat/skip-duplicates): it pre-checks destination
`_metadata` for each database / table / column / index and tolerates in
Skip/Upsert mode. Re-runs no longer produce schema-level errors, so the
E2E tests can drop the status-tolerant workaround and assert strict
'completed' outcomes.
Changes:
- composer.json: pin utopia-php/migration to dev-feat/skip-duplicates (aliased
to 1.9.99 for stability resolution). Will be replaced with a fixed 1.10.0
tag once the migration PR lands.
- testAppwriteMigrationRowsOnDuplicate: replace the tolerant
runMigrationAssertingRowSuccess helper with performMigrationSync on the
Skip and Upsert re-runs. Asserts 'completed' status on every run,
destination row content matches the expected value per mode (Mutated
preserved on Skip, Original restored on Upsert). Helper method removed.
- testAppwriteMigrationReRunIsIdempotent (new): seeds two rows on source,
runs the migration three times back-to-back (fresh, Skip re-run, Upsert
re-run) against unchanged source data, asserts strict 'completed' on every
run and row content is stable across all three. Exercises the
schema-tolerance path end-to-end: every database/table/column on
destination already exists with a matching spec, so DestinationAppwrite's
pre-check returns Tolerate for every resource.