Skip to content

Validate affiliate offer edit text fields - #148

Closed
absalonCRC wants to merge 1 commit into
profullstack:masterfrom
absalonCRC:fix-affiliate-offer-edit-text-validation
Closed

Validate affiliate offer edit text fields#148
absalonCRC wants to merge 1 commit into
profullstack:masterfrom
absalonCRC:fix-affiliate-offer-edit-text-validation

Conversation

@absalonCRC

@absalonCRC absalonCRC commented May 21, 2026

Copy link
Copy Markdown
Contributor

Summary

  • return 400 when affiliate offer PATCH title is present but not a string
  • return 400 when affiliate offer PATCH description is present but not a string
  • add route coverage for both malformed edit payloads

Closes #147.

This is for the active uGig affiliate/invite testing task: 4741218f-a723-46bb-82cb-6516120331ae.

Payment address for the uGig SOL bounty, if accepted: 27sdMYXofqoM9qR13bZhccRNYeEgYn5EoHXTSJn4QWKP

Validation

  • pnpm test:run 'src/app/api/affiliates/offers/[id]/route.test.ts'\n- pnpm exec eslint 'src/app/api/affiliates/offers/[id]/route.ts' 'src/app/api/affiliates/offers/[id]/route.test.ts'\n- pnpm type-check\n- git diff --check -- 'src/app/api/affiliates/offers/[id]/route.ts' 'src/app/api/affiliates/offers/[id]/route.test.ts'

Payment fallback: PayPal cultofrozen@gmail.com

@greptile-apps

greptile-apps Bot commented May 23, 2026

Copy link
Copy Markdown

Greptile Summary

This PR adds type validation for title and description in the affiliate offer PATCH handler, returning 400 when either field is present but not a string. Two new tests cover the rejection cases.

  • route.ts: wraps the existing .trim() calls with typeof !== \"string\" guards, closing a gap where non-string values would previously cause a runtime error (or silently corrupt data).
  • route.test.ts: adds a PATCH describe block with helpers and two tests for the new 400 responses; success-path coverage is absent.
  • The eslint-disable-next-line comment for type AnySupabase = any was removed as a side change.

Confidence Score: 4/5

The validation logic is correct and the new tests confirm the 400 paths work as intended; the change is safe to merge.

The core fix is straightforward and well-scoped. The main gap is that no success-path test was added alongside the error-path tests, so a regression in the happy path would go undetected. The removed ESLint suppression comment is a minor side change that does not affect runtime behaviour.

route.test.ts would benefit from at least one test verifying a valid string update reaches the DB and returns 200.

Important Files Changed

Filename Overview
src/app/api/affiliates/offers/[id]/route.ts Adds typeof guards for title and description in the PATCH handler, returning 400 for non-string values; also removes an eslint-disable comment without removing the underlying any alias it suppressed.
src/app/api/affiliates/offers/[id]/route.test.ts Adds a PATCH describe block with two tests covering the new 400 error cases; no success-path test is included, leaving the happy path untested.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[PATCH /api/affiliates/offers/:id] --> B{Auth check}
    B -->|no auth| C[401 Unauthorized]
    B -->|authenticated| D{Offer exists and seller owns it?}
    D -->|no| E[404 Not found or not authorized]
    D -->|yes| F[Parse request body]
    F --> G{title present?}
    G -->|yes| H{typeof title === string?}
    H -->|no| I[400 title must be a string]
    H -->|yes| J[Add trimmed title to updateData]
    G -->|no| K{description present?}
    J --> K
    K -->|yes| L{typeof description === string?}
    L -->|no| M[400 description must be a string]
    L -->|yes| N[Add trimmed description to updateData]
    K -->|no| O[Assign remaining fields]
    N --> O
    O --> P[DB update]
    P -->|error| Q[400 DB error]
    P -->|success| R[200 offer]
Loading

Reviews (1): Last reviewed commit: "Validate affiliate offer edit text field..." | Re-trigger Greptile

Comment on lines +125 to +156
describe("PATCH /api/affiliates/offers/[id]", () => {
beforeEach(() => {
vi.clearAllMocks();
mockGetAuthContext.mockResolvedValue({ user: { id: "seller1" } });
});

it("rejects non-string title updates", async () => {
mockFrom.mockReturnValue(chainable({ id: "offer1", seller_id: "seller1" }));

const res = await PATCH(
makePatchRequest("offer1", { title: 123 }),
makeParams("offer1")
);
const body = await res.json();

expect(res.status).toBe(400);
expect(body.error).toBe("title must be a string");
});

it("rejects non-string description updates", async () => {
mockFrom.mockReturnValue(chainable({ id: "offer1", seller_id: "seller1" }));

const res = await PATCH(
makePatchRequest("offer1", { description: { text: "not a string" } }),
makeParams("offer1")
);
const body = await res.json();

expect(res.status).toBe(400);
expect(body.error).toBe("description must be a string");
});
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 No success-path test for PATCH

The two new tests only exercise rejection (400) scenarios. There is no test that verifies a valid string title or description actually flows through to a DB update and returns 200. If the update logic were accidentally broken (e.g., updateData construction or the .update() call), both existing tests would still pass, leaving the regression undetected.

import { createServiceClient } from "@/lib/supabase/service";

// eslint-disable-next-line @typescript-eslint/no-explicit-any
type AnySupabase = any;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 ESLint suppression removed without removing the any usage

The // eslint-disable-next-line @typescript-eslint/no-explicit-any comment was deleted, but type AnySupabase = any still uses an explicit any. If the project ever tightens the @typescript-eslint/no-explicit-any rule to "error", this line will start failing lint without any obvious history of why the suppression existed.

@ralyodio ralyodio closed this May 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug: affiliate offer edits crash on non-string title or description

2 participants