test: Backend-e2e in CI stabil (eigene Jahre, Sperren, ein Server je App)
Backend E2E / e2e (push) Failing after 7m26s
Backend Image / build-and-push (push) Failing after 4m20s
Frontend Image / build-and-push (push) Successful in 15m44s

- daily-evaluation nutzt die Jahre 2011/2012 statt 2001, damit der Job nicht
  die Daten von autopilot und reminders liest und verändert.
- throttler: app.listen(0) einmal je App statt eines Servers je Anfrage
  (ECONNRESET bei 40 parallelen Anfragen).
- outbox-claims: 120 s Zeitlimit für 2000 sequentielle Anweisungen.
- migration-harness: eine `migrate deploy` zur Zeit über eine eigene
  Advisory-Sperre (P1002 bei parallelen Migrations-Suites).
- authority-notices und authority-notices-herd laufen über
  exclusive-suite nacheinander; Herd-Wiederholung räumt eigene Entwürfe.

Refs #32

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
Nick.RosenloecherandClaude Opus 5.5 committed 2026-10-16 16:55:56 +02:00
1 parent 258e90828f
commit 6edae3efec
7 files changed
+217 -140

No files matched your search

@@ -9,6 +9,7 @@ import { DomainEventRegistry } from '../src/domain-events/domain-event-registry'
import { PrismaService } from '../src/prisma/prisma.service';
import { login } from './utils/api';
import { createTestApp } from './utils/create-test-app';
import { acquireExclusive, EXCLUSIVE_KEYS } from './utils/exclusive-suite';
import { drainDomainEvents } from './utils/domain-events';
interface NoticeBody {
@@ -55,7 +56,11 @@ describe('Authority notices: herd change notification (e2e)', () => {
const nextKey = () =>
`herd-e2e-${suffix}-${(keyCounter += 1).toString().padStart(4, '0')}`;
let releaseExclusive: () => Promise<void>;
beforeAll(async () => {
// Suites that clear or create the global open notice drafts take turns.
releaseExclusive = await acquireExclusive(EXCLUSIVE_KEYS.authorityNotices);
app = await createTestApp();
prisma = app.get(PrismaService);
const passwordHash = await bcrypt.hash(password, 12);
@@ -107,6 +112,11 @@ describe('Authority notices: herd change notification (e2e)', () => {
await prisma.notification.deleteMany({
where: { userId: { in: [...managerIds, staffId] } },
});
// A retried attempt must start without the notices (and the open draft)
// of the failed one.
await prisma.authorityNotice.deleteMany({
where: { id: { in: noticeIds.splice(0) } },
});
}
beforeEach(resetScenarioState);
@@ -168,6 +178,7 @@ describe('Authority notices: herd change notification (e2e)', () => {
});
await prisma.user.deleteMany({ where: { id: { in: userIds } } });
await app.close();
await releaseExclusive();
});
/** A notice sent today is the baseline: the current herd. */
@@ -319,7 +330,7 @@ describe('Authority notices: herd change notification (e2e)', () => {
scenario('an apiary move (LOCATION_CHANGED) counts', async () => {
await sendBaseline();
await patchApiary({ location: `Neuer Standort ${suffix}` });
await patchApiary({ location: `Neuer Standort ${nextKey()}` });
expect(await unreadOf(managerIds)).toHaveLength(managerIds.length);
});
@@ -327,7 +338,7 @@ describe('Authority notices: herd change notification (e2e)', () => {
scenario('a rename does not count', async () => {
await sendBaseline();
await patchApiary({ name: `Herd Stand umbenannt ${suffix}` });
await patchApiary({ name: `Herd Stand umbenannt ${nextKey()}` });
expect(await unreadOf(managerIds)).toHaveLength(0);
});
@@ -344,7 +355,7 @@ describe('Authority notices: herd change notification (e2e)', () => {
await addColony();
expect(await unreadOf(managerIds)).toHaveLength(0);
await patchApiary({ location: `Ort wieder neu ${suffix}` });
await patchApiary({ location: `Ort wieder neu ${nextKey()}` });
expect(await unreadOf(managerIds)).toHaveLength(managerIds.length);
},
);