Skip to content

Feature Spec: Article Favorites (REST + GraphQL) test coverage #186

Description

@devin-ai-integration

Feature Spec: Article Favorites

As a registered user, I can favorite and unfavorite articles so I can curate a reading list, and any client can see accurate favorite state and counts. This spec covers the REST endpoints, the GraphQL mutations, and the favorite read-model behavior.

Behavior / Acceptance Criteria

Favorite an article (REST POST /articles/{slug}/favorite)

  • AC1: An authenticated user favoriting an existing article receives 200 and the returned article.favorited is true.
  • AC2: The returned article.favoritesCount reflects the article's favorite count including this user.
  • AC3: Favoriting an article that does not exist returns 404.
  • AC4: An unauthenticated request returns 401 and does not change favorite state.
  • AC5: Favoriting an article the user has already favorited is idempotent — still 200, favorited=true, and the count is not double-incremented.

Unfavorite an article (REST DELETE /articles/{slug}/favorite)

  • AC6: An authenticated user unfavoriting a previously favorited article receives 200 and article.favorited is false.
  • AC7: article.favoritesCount decreases accordingly after unfavoriting.
  • AC8: Unfavoriting an article that does not exist returns 404.
  • AC9: An unauthenticated request returns 401.
  • AC10: Unfavoriting an article the user had not favorited is a no-op — 200, favorited=false, count unchanged.

GraphQL parity

  • AC11: The favoriteArticle(slug) mutation sets favorited=true and returns the updated favoritesCount, matching the REST result for the same user/article.
  • AC12: The unfavoriteArticle(slug) mutation sets favorited=false, matching the REST result.

Read-model / persistence

  • AC13: The favorite read model reports the correct favorited flag per (article, viewer) pair — true only for the viewing user's own favorites.
  • AC14: The favorites count for an article equals the number of distinct users who have favorited it.

Notes

  • Follow the repo's existing test conventions per tier.
  • favorited is always relative to the authenticated/viewing user; an anonymous viewer sees favorited=false.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions