Files
twenty/packages/twenty-server
Félix Malfait 7eafbd91c6 test(server): make timeline integration test self-seed its data (#21896)
## Problem

`timeline-from-object-record.integration-spec.ts` is flaky depending on
Jest shard composition. Its `beforeAll` scans the dev-seeded people for
one with message threads and one with calendar events, and throws when
none is found:

```
Expected the seeded workspace to contain a person with message threads and calendar events
```

This was observed as a deterministic failure of `server-integration-test
(2)` (failed on re-run too), while the other 15 shards were green.

## Root cause

The suite depends on **mutable shared fixture state** under two fragile
assumptions:

1. **That no sibling suite wiped the seeded people.**
`deleteAllRecords('person')` is a common pattern across the REST/GraphQL
suites — `rest-api-core-find-many`, `rest-api-core-find-one`,
`all-people-resolvers`, `search-resolver`, etc. — each hard-deletes
every person (`DELETE FROM "...".person`) and leaves only its own
handful behind, without restoring the seed. Within a shard, Jest runs
files serially (`maxWorkers: 1`) ordered by file size descending (no
timing cache in CI). `rest-api-core-find-many` (~16 KB, runs 2nd)
executes **before** `timeline-from-object-record` (~12 KB, runs 5th), so
by the time the timeline `beforeAll` runs, only 4 company-linked test
people remain — none with threads or events.
2. **That the seeder's `Math.random` participant assignment** happened
to land a thread and an event on a company-linked person within the
first 100 results — itself non-deterministic across DB resets.

It surfaced now because an unrelated PR added a new integration test
file, which changed the total file set and therefore Jest's shard
distribution, moving `timeline-from-object-record` and
`rest-api-core-find-many` into the **same shard** for the first time. It
is a latent test-isolation issue, not a product regression.

### Reproduced locally

Against a DB where `rest-api-core-find-many` had already run (person
count = 4), the timeline suite fails with the exact CI error; on a
freshly seeded DB it passes. So the failure is purely order/seed
dependent.

## Fix

Make the suite self-contained: in `beforeAll` it now provisions its own
graph via the GraphQL API and tears it down in `afterAll`:

```
company → person → messageThread → message → messageParticipant(personId)
                 ↘ calendarEvent → calendarEventParticipant(personId)
```

The timeline resolvers count threads via `messageThread → messages →
messageParticipants.personId` and events via `calendarEvent →
calendarEventParticipants.personId`, so this graph is sufficient and
minimal. The suite no longer reads any ambient seeded data, making it
independent of execution order and seeding randomness.

## Validation

- Self-seeding suite passes against the **polluted** DB (4 people, no
seeded threads/events) — the exact CI failure condition.
- Idempotent across repeated runs and leaves **no residue** (all
fixtures destroyed in `afterAll`).
- Full `--shard=2/16` run green except a pre-existing environmental
failure (`successful-save-imap-smtp-caldav-account`, fails locally with
no mail server, identical before/after this change).

https://claude.ai/code/session_013k36vfekDppwRCgM6Ha7De

---
_Generated by [Claude
Code](https://claude.ai/code/session_013k36vfekDppwRCgM6Ha7De)_

<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/21896?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>
<!-- End of auto-generated description by cubic. -->
2026-06-20 14:29:28 +02:00
..
2026-04-02 11:20:08 +00:00
2026-04-02 11:20:08 +00:00