ci: trigga på master + formatfix inför Gitea Actions
CI / Typecheck, test & build (push) Failing after 2s

This commit is contained in:
Sven (AAMOS AI)
2026-08-13 17:25:14 +07:00
parent 61d60931ad
commit c32a7e33c7
141 changed files with 40555 additions and 45210 deletions
+89 -21
View File
@@ -28,8 +28,12 @@ describe("DELETE /v1/me — GDPR residual completeness", () => {
await testDb.db.delete(schema.recipeRatings).where(eq(schema.recipeRatings.userId, u.id));
await testDb.db.delete(schema.recipeFavorites).where(eq(schema.recipeFavorites.userId, u.id));
await testDb.db.delete(schema.recipeCooks).where(eq(schema.recipeCooks.userId, u.id));
await testDb.db.delete(schema.creatorFollows).where(eq(schema.creatorFollows.followerUserId, u.id));
await testDb.db.delete(schema.creatorFollows).where(eq(schema.creatorFollows.creatorUserId, u.id));
await testDb.db
.delete(schema.creatorFollows)
.where(eq(schema.creatorFollows.followerUserId, u.id));
await testDb.db
.delete(schema.creatorFollows)
.where(eq(schema.creatorFollows.creatorUserId, u.id));
await testDb.db.delete(schema.creatorStats).where(eq(schema.creatorStats.userId, u.id));
await testDb.db.delete(schema.recipes).where(eq(schema.recipes.creatorUserId, u.id));
await testDb.db.delete(schema.foodMemories).where(eq(schema.foodMemories.userId, u.id));
@@ -37,8 +41,12 @@ describe("DELETE /v1/me — GDPR residual completeness", () => {
await testDb.db.delete(schema.tasteSignals).where(eq(schema.tasteSignals.userId, u.id));
await testDb.db.delete(schema.meals).where(eq(schema.meals.userId, u.id));
await testDb.db.delete(schema.subscriptions).where(eq(schema.subscriptions.userId, u.id));
await testDb.db.delete(schema.subscriptionEvents).where(eq(schema.subscriptionEvents.userId, u.id));
await testDb.db.delete(schema.storeTransactions).where(eq(schema.storeTransactions.userId, u.id));
await testDb.db
.delete(schema.subscriptionEvents)
.where(eq(schema.subscriptionEvents.userId, u.id));
await testDb.db
.delete(schema.storeTransactions)
.where(eq(schema.storeTransactions.userId, u.id));
await testDb.db.delete(schema.trials).where(eq(schema.trials.userId, u.id));
await testDb.db.delete(schema.aiUsageCounters).where(eq(schema.aiUsageCounters.userId, u.id));
await testDb.db.delete(schema.notifications).where(eq(schema.notifications.userId, u.id));
@@ -46,22 +54,34 @@ describe("DELETE /v1/me — GDPR residual completeness", () => {
await testDb.db.delete(schema.idempotencyKeys).where(eq(schema.idempotencyKeys.userId, u.id));
await testDb.db.delete(schema.userConsents).where(eq(schema.userConsents.userId, u.id));
await testDb.db.delete(schema.userPreferences).where(eq(schema.userPreferences.userId, u.id));
await testDb.db.delete(schema.userHealthProfiles).where(eq(schema.userHealthProfiles.userId, u.id));
await testDb.db.delete(schema.userLocalePreferences).where(eq(schema.userLocalePreferences.userId, u.id));
await testDb.db
.delete(schema.userHealthProfiles)
.where(eq(schema.userHealthProfiles.userId, u.id));
await testDb.db
.delete(schema.userLocalePreferences)
.where(eq(schema.userLocalePreferences.userId, u.id));
await testDb.db.delete(schema.userCredentials).where(eq(schema.userCredentials.userId, u.id));
await testDb.db.delete(schema.refreshTokens).where(eq(schema.refreshTokens.userId, u.id));
await testDb.db.delete(schema.emailVerificationTokens).where(eq(schema.emailVerificationTokens.userId, u.id));
await testDb.db.delete(schema.passwordResetTokens).where(eq(schema.passwordResetTokens.userId, u.id));
await testDb.db
.delete(schema.emailVerificationTokens)
.where(eq(schema.emailVerificationTokens.userId, u.id));
await testDb.db
.delete(schema.passwordResetTokens)
.where(eq(schema.passwordResetTokens.userId, u.id));
await testDb.db.delete(schema.adminTotp).where(eq(schema.adminTotp.userId, u.id));
await testDb.db.delete(schema.auditLogs).where(eq(schema.auditLogs.actorUserId, u.id));
await testDb.db.delete(schema.domainEvents).where(eq(schema.domainEvents.userId, u.id));
await testDb.db.delete(schema.productAnalyticsEvents).where(eq(schema.productAnalyticsEvents.userId, u.id));
await testDb.db
.delete(schema.productAnalyticsEvents)
.where(eq(schema.productAnalyticsEvents.userId, u.id));
// Remove memberships and any orphaned single-member households.
const memberships = await testDb.db
.select({ householdId: schema.householdMembers.householdId })
.from(schema.householdMembers)
.where(eq(schema.householdMembers.userId, u.id));
await testDb.db.delete(schema.householdMembers).where(eq(schema.householdMembers.userId, u.id));
await testDb.db
.delete(schema.householdMembers)
.where(eq(schema.householdMembers.userId, u.id));
for (const { householdId } of memberships) {
const remaining = await testDb.db
.select({ count: sql<number>`count(*)::int` })
@@ -124,7 +144,9 @@ describe("DELETE /v1/me — GDPR residual completeness", () => {
{ userId, kind: "personalization", status: "granted" },
{ userId, kind: "image_training", status: "granted" },
]);
await testDb.db.insert(schema.pushTokens).values({ userId, token: "expo-token-1", platform: "ios" });
await testDb.db
.insert(schema.pushTokens)
.values({ userId, token: "expo-token-1", platform: "ios" });
await testDb.db.insert(schema.notifications).values({
userId,
type: "subscription_status",
@@ -201,7 +223,16 @@ describe("DELETE /v1/me — GDPR residual completeness", () => {
source: "manual",
titleSv: "Resttest-lunch",
date: new Date().toISOString().slice(0, 10),
nutrition: { kcal: 0, proteinG: 0, carbsG: 0, fatG: 0, saturatedFatG: 0, fiberG: 0, sugarG: 0, saltG: 0 },
nutrition: {
kcal: 0,
proteinG: 0,
carbsG: 0,
fatG: 0,
saturatedFatG: 0,
fiberG: 0,
sugarG: 0,
saltG: 0,
},
});
const [draftRecipe] = await testDb.db
@@ -215,7 +246,16 @@ describe("DELETE /v1/me — GDPR residual completeness", () => {
creatorUserId: userId,
creatorDisplayName: "Test",
status: "draft",
nutritionPerPortion: { kcal: 0, proteinG: 0, carbsG: 0, fatG: 0, saturatedFatG: 0, fiberG: 0, sugarG: 0, saltG: 0 },
nutritionPerPortion: {
kcal: 0,
proteinG: 0,
carbsG: 0,
fatG: 0,
saturatedFatG: 0,
fiberG: 0,
sugarG: 0,
saltG: 0,
},
dna: {
cuisine: "swedish",
vegetables: [],
@@ -241,7 +281,16 @@ describe("DELETE /v1/me — GDPR residual completeness", () => {
creatorDisplayName: "Test",
status: "published",
verificationStatus: "editorial",
nutritionPerPortion: { kcal: 0, proteinG: 0, carbsG: 0, fatG: 0, saturatedFatG: 0, fiberG: 0, sugarG: 0, saltG: 0 },
nutritionPerPortion: {
kcal: 0,
proteinG: 0,
carbsG: 0,
fatG: 0,
saturatedFatG: 0,
fiberG: 0,
sugarG: 0,
saltG: 0,
},
dna: {
cuisine: "swedish",
vegetables: [],
@@ -255,9 +304,15 @@ describe("DELETE /v1/me — GDPR residual completeness", () => {
})
.returning();
await testDb.db.insert(schema.recipeRatings).values({ recipeId: publishedRecipe!.id, userId, stars: 5 });
await testDb.db.insert(schema.recipeFavorites).values({ recipeId: publishedRecipe!.id, userId });
await testDb.db.insert(schema.recipeCooks).values({ recipeId: publishedRecipe!.id, userId, portionsCooked: 2 });
await testDb.db
.insert(schema.recipeRatings)
.values({ recipeId: publishedRecipe!.id, userId, stars: 5 });
await testDb.db
.insert(schema.recipeFavorites)
.values({ recipeId: publishedRecipe!.id, userId });
await testDb.db
.insert(schema.recipeCooks)
.values({ recipeId: publishedRecipe!.id, userId, portionsCooked: 2 });
await testDb.db.insert(schema.creatorStats).values({ userId });
await testDb.db.insert(schema.subscriptions).values({
@@ -431,7 +486,10 @@ describe("DELETE /v1/me — GDPR residual completeness", () => {
const result = await testDb.db.execute<{ count: number }>(
sql.raw(`SELECT count(*)::int AS count FROM "${table}" WHERE "${column}" = '${userId}'`),
);
expect(Number(result.rows[0]?.count ?? 0), `Residual ${table}.${column} for deleted user`).toBe(0);
expect(
Number(result.rows[0]?.count ?? 0),
`Residual ${table}.${column} for deleted user`,
).toBe(0);
}
// Receipts in surviving households must have image stripped.
@@ -440,12 +498,18 @@ describe("DELETE /v1/me — GDPR residual completeness", () => {
.from(schema.receipts)
.where(eq(schema.receipts.householdId, (await getHouseholdId(userId))!));
for (const r of survivingReceipts) {
expect(r.imageUrl, "Receipt image must be null after deletion in surviving household").toBeNull();
expect(
r.imageUrl,
"Receipt image must be null after deletion in surviving household",
).toBeNull();
}
// Public recipe must be anonymized.
const [publicAfter] = await testDb.db
.select({ creatorUserId: schema.recipes.creatorUserId, creatorDisplayName: schema.recipes.creatorDisplayName })
.select({
creatorUserId: schema.recipes.creatorUserId,
creatorDisplayName: schema.recipes.creatorDisplayName,
})
.from(schema.recipes)
.where(eq(schema.recipes.id, publishedRecipe!.id));
expect(publicAfter?.creatorUserId).toBeNull();
@@ -460,7 +524,11 @@ describe("DELETE /v1/me — GDPR residual completeness", () => {
// User row is soft-deleted and anonymized.
const [userAfter] = await testDb.db
.select({ email: schema.users.email, displayName: schema.users.displayName, deletedAt: schema.users.deletedAt })
.select({
email: schema.users.email,
displayName: schema.users.displayName,
deletedAt: schema.users.deletedAt,
})
.from(schema.users)
.where(eq(schema.users.id, userId));
expect(userAfter?.deletedAt).not.toBeNull();