ci: trigga på master + formatfix inför Gitea Actions
CI / Typecheck, test & build (push) Failing after 2s
CI / Typecheck, test & build (push) Failing after 2s
This commit is contained in:
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user