Skip to content

Conversation

@Piyushrathoree
Copy link
Collaborator

Proposed change

Resolves #1765

created the frontend implementation for the user badges for user card with a count and all the badges on the user detail page with tooltip for its name and also the badges are sorted properly.

I have also attached the demo badges screenshots and the badges in the summary section will changes according to the css_class coming from backend.

Checklist

  • I've read and followed the contributing guidelines.
  • I've run make check-test locally; all checks and tests passed.
Screenshot From 2025-09-13 21-53-18 Screenshot From 2025-09-13 21-53-04

- Introduced BadgeNode for GraphQL representation of badges.
- Enhanced UserNode with badges and badge count fields.
- Updated UserCard to display badge count and integrated Badges component in UserDetailsPage.
- Added tests for badge display and functionality across components.
- Updated GraphQL queries to include badge data and counts.
- Improved formatting and readability in user_test.py by adjusting line breaks.
- Updated mockBadgeData.ts to enhance consistency in object formatting.
- Simplified Tooltip mock in Badges.test.tsx for better clarity.
- Minor adjustments in Badges.tsx for consistent className formatting.
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Sep 13, 2025

Summary by CodeRabbit

  • New Features

    • User profiles now display badges with icons and tooltips.
    • User cards show a medal icon and formatted badge count when available.
    • Badges render consistently with expanded icon support (award, medal, ribbon, star, bug, certificate).
    • Data views include badge count and badges for members and leaders.
  • Tests

    • Added comprehensive unit tests for badges, user card badge count, and user details badge rendering.
  • Chores

    • Pinned a dev dependency version to improve build stability.

Walkthrough

Adds badge support end-to-end: backend exposes UserNode.badge_count and refines badges resolver; indexing gains idx_badge_count. Badge model gains css_class choices and migration. Frontend introduces Badges component, updates UserCard and member pages, extends GraphQL queries and types, supplies icon map, and adds extensive unit tests. Also pins @swc/core.

Changes

Cohort / File(s) Summary
Backend GraphQL: User badges API
backend/apps/github/api/internal/nodes/user.py, backend/tests/apps/github/api/internal/nodes/user_test.py
Adds UserNode.badge_count field/resolver; refactors badges resolver ordering; updates tests to cover badge_count and badges ordering/select_related behavior.
Backend indexing: idx_badge_count
backend/apps/github/models/mixins/user.py, backend/apps/core/utils/index.py, backend/apps/github/index/registry/user.py, backend/apps/github/index/search/user.py, backend/tests/apps/core/utils/match_test.py
Introduces idx_badge_count property and includes it in index fields, search attributesToRetrieve, and index params; updates tests accordingly.
Backend model/migration: Badge css_class choices
backend/apps/nest/models/badge.py, backend/apps/nest/migrations/0007_alter_badge_css_class.py
Defines BadgeCssClass TextChoices; sets css_class choices and default MEDAL; adds migration altering css_class field; sets verbose_name_plural.
Frontend components: Badges and UserCard
frontend/src/components/Badges.tsx, frontend/src/components/UserCard.tsx, frontend/src/app/members/page.tsx, frontend/src/app/members/[memberKey]/page.tsx
Adds Badges component rendering FA icon with optional tooltip; updates UserCard to show badgeCount; passes badges/badgeCount from list/detail pages and renders badges on member page.
Frontend GraphQL queries and types
frontend/src/server/queries/userQueries.ts, frontend/src/types/badge.ts, frontend/src/types/user.ts, frontend/src/types/card.ts
Extends queries to fetch badgeCount and badges; adds Badge type; augments User and UserCardProps with badges/badgeCount.
Frontend utilities: icon map
frontend/src/utils/data.ts
Exports BADGE_CLASS_MAP mapping badge keys to FontAwesome icons; registers additional icons.
Frontend tests: components/pages/data
frontend/__tests__/unit/components/Badges.test.tsx, frontend/__tests__/unit/components/UserCard.test.tsx, frontend/__tests__/unit/pages/UserDetails.test.tsx, frontend/__tests__/unit/data/mockBadgeData.ts, frontend/__tests__/unit/data/mockUserDetails.ts
Adds unit tests for Badges and UserCard badgeCount; extends UserDetails tests for badge rendering; introduces mock badge data and augments user details mock.
Tooling
frontend/package.json
Pins devDependency @swc/core to 1.13.19 (removes caret).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~30 minutes

Possibly related PRs

Suggested reviewers

  • kasya

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings, 1 inconclusive)
Check name Status Explanation Resolution
Linked Issues Check ⚠️ Warning The implementation satisfies the detailed badge display on the user detail page, uses Font Awesome icons, includes graceful fallback behavior, and provides tests and screenshots, but it does not render up to six badge icons on the user list page and does not enable support for custom local OWASP-specific icons as described in the linked issue. Please extend the user list page to display individual badge icons (up to six) instead of only a count and add a mechanism for supplying custom local icons for OWASP-specific badges.
Out of Scope Changes Check ⚠️ Warning The pull request contains extensive back-end changes—including GraphQL schema updates, database migrations, search indexing modifications, and utility adjustments—that are not necessary to fulfill the front-end display objectives of the linked issue. Consider moving unrelated back-end changes into a separate pull request or clearly justifying their inclusion as prerequisites for front-end functionality.
Title Check ❓ Inconclusive The title “Task/badge implementation in frontend” does refer to implementing badges but uses a nonstandard “Task/” prefix, omits backend GraphQL and API changes that are part of this pull request, and is too narrow to convey the full scope of work. Consider updating the title to succinctly capture the main changes across both front-end and back-end, for example “Add badge count and detailed badge display to user cards and profiles.”
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed The pull request description clearly outlines the implementation for front-end user badges, references resolving the linked issue, notes the user card badge count and detailed badges with tooltips, and includes screenshots and test commands.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (15)
cspell/custom-dict.txt (1)

59-59: Consider adding other common FA tokens to avoid future cspell noise.
Add: far, fab, fa-solid, fa-regular, fa-brands.

 fas
+far
+fab
+fa-solid
+fa-regular
+fa-brands
frontend/src/types/badge.ts (1)

1-7: Make Badge props readonly to prevent accidental mutation across components.

-export type Badge = {
+export type Badge = {
-  id: string
-  name: string
-  cssClass?: string
-  description?: string
-  weight: number
+  readonly id: string
+  readonly name: string
+  readonly cssClass?: string
+  readonly description?: string
+  readonly weight: number
 }
frontend/src/app/members/[memberKey]/page.tsx (1)

212-226: Ensure icon fallback includes a style prefix and apply deterministic client-side sort as a safety net.
If backend sorting changes or a badge lacks cssClass, this keeps order and rendering stable.

-        {user?.badges && user.badges.length > 0 && (
+        {user?.badges && user.badges.length > 0 && (
           <div className="mt-2 flex flex-wrap gap-2">
             <span className="text-sm text-gray-500 dark:text-gray-400">Badges:</span>
-            {user.badges.map((badge) => (
+            {user.badges
+              .slice()
+              .sort((a, b) => (b.weight - a.weight) || a.name.localeCompare(b.name))
+              .map((badge) => (
               <Badges
                 key={badge.id}
                 name={badge.name}
-                cssClass={badge.cssClass || 'fa-medal'}
+                cssClass={badge.cssClass || 'fa-solid fa-medal'}
                 description={badge.description || ''}
                 weight={badge.weight}
                 showTooltip={true}
               />
             ))}
           </div>
         )}
frontend/src/app/members/page.tsx (1)

44-45: Tiny stylistic nit.
Use nullish coalescing for arrays as well.

-        badges={user.badges || []}
+        badges={user.badges ?? []}
backend/tests/apps/github/api/internal/nodes/user_test.py (1)

18-44: Add a schema-level test to assert camelCased GraphQL fields (badgeCount, cssClass).

Backend types use snake_case (badge_count, css_class) while the frontend queries use camelCase; Strawberry will auto-convert snake_case to camelCase by default — add a small SDL/schema test that asserts the presence of "badgeCount" and "cssClass" in the generated schema. (github.com)

Relevant files to check: backend/settings/graphql.py, backend/apps/github/api/internal/nodes/user.py (badge_count), backend/apps/nest/api/internal/nodes/badge.py (css_class), frontend/src/server/queries/userQueries.ts.

frontend/src/components/UserCard.tsx (2)

72-77: Add accessible label and remove stray space.

Provide an aria label for the medal icon and drop the trailing {' '} to avoid rendering a superfluous text node.

-            {badgeCount > 0 && (
-              <p className="mt-1 max-w-[250px] truncate text-sm text-gray-600 sm:text-base dark:text-gray-400">
-                <FontAwesomeIcon icon={faMedal} className="mr-1 h-4 w-4" />
-                {millify(badgeCount, { precision: 1 })}{' '}
-              </p>
-            )}
+            {badgeCount > 0 && (
+              <p className="mt-1 max-w=[250px] truncate text-sm text-gray-600 sm:text-base dark:text-gray-400">
+                <FontAwesomeIcon icon={faMedal} className="mr-1 h-4 w-4" aria-label="badges" />
+                {millify(badgeCount, { precision: 1 })}
+              </p>
+            )}

36-36: Next/Image: use style for object-fit (Next 13+).

objectFit prop is deprecated; set via style to avoid console warnings.

-            <Image fill src={`${avatar}&s=160`} alt={name || 'user'} objectFit="cover" />
+            <Image fill src={`${avatar}&s=160`} alt={name || 'user'} style={{ objectFit: 'cover' }} />
backend/apps/github/api/internal/nodes/user.py (1)

41-45: Guard against duplicate rows in count.

If the through table ever allows duplicates (migration or data drift), .count() could overstate. Using .values("badge_id").distinct().count() is safer at minimal cost.

-        return self.badges.filter(is_active=True).count()
+        return (
+            self.badges.filter(is_active=True)
+            .values("badge_id")
+            .distinct()
+            .count()
+        )
frontend/__tests__/unit/components/UserCard.test.tsx (1)

113-142: Add assertion for medal icon in full-props case.

Minor but helps ensure medal isn’t accidentally dropped when other stats render.

       render(<UserCard {...fullProps} />)
@@
       expect(screen.getByText('25')).toBeInTheDocument()
+      expect(screen.getByTestId('icon-medal')).toBeInTheDocument()
frontend/src/server/queries/userQueries.ts (1)

89-97: Consider over-fetching on some views.

If certain pages only need badgeCount, consider gating the badges { ... } selection via separate queries or fragments to keep payloads small. Not blocking.

frontend/src/components/Badges.tsx (2)

1-7: Bundle size caution: adding the entire fas pack is heavy.

Registering all solid icons bloats the client bundle. If feasible, maintain a small allowlist (e.g., map backend cssClass to a curated set) and add only those, or lazy-load uncommon icons.


16-21: Normalize multiple prefixes and odd inputs.

Small hardening: strip repeated fa- prefixes and convert underscores to dashes to match FA naming.

-  const safeCssClass = cssClass || 'fa-medal'
-  const iconName = String(safeCssClass).replace(/^fa-/, '') as IconName
+  const safeCssClass = (cssClass ?? 'fa-medal') as string
+  const iconName = String(safeCssClass).trim().replace(/^(?:fa-)+/, '').replace(/_/g, '-') as IconName
frontend/__tests__/unit/pages/UserDetails.test.tsx (3)

18-29: Broaden FontAwesome mock to cover all IconProp shapes and avoid future brittleness

Support string icons too and keep rest props separate from DOM-unsafe ones. This keeps the mock resilient to upstream changes.

-jest.mock('@fortawesome/react-fontawesome', () => ({
-  FontAwesomeIcon: ({
-    icon,
-    className,
-    ...props
-  }: {
-    icon: string[] | { iconName: string }
-    className?: string
-    [key: string]: unknown
-  }) => {
-    const iconName = Array.isArray(icon) ? icon[1] : icon.iconName
-    return <span data-testid={`icon-${iconName}`} className={className} {...props} />
-  },
-}))
+jest.mock('@fortawesome/react-fontawesome', () => ({
+  FontAwesomeIcon: ({
+    icon,
+    className,
+    ...rest
+  }: {
+    icon: string | [string, string] | { iconName: string }
+    className?: string
+    [key: string]: unknown
+  }) => {
+    const iconName = Array.isArray(icon)
+      ? icon[1]
+      : typeof icon === 'string'
+      ? icon
+      : icon.iconName
+    return <span data-testid={`icon-${iconName}`} className={className} {...rest} />
+  },
+}))

32-56: Stabilize badge test-id slugging to reduce selector brittleness

Current slug only replaces whitespace; special chars remain (e.g., “badge-&-more!”). Consider mirroring production slugging (strip non-alphanumerics, collapse dashes) to avoid fragile selectors and potential collisions.

-  const MockBadges = ({
+  const MockBadges = ({
     name,
     cssClass,
     showTooltip,
   }: {
     name: string
     cssClass: string
     showTooltip?: boolean
   }) => (
-    <div
-      data-testid={`badge-${name.toLowerCase().replace(/\s+/g, '-')}`}
+    <div
+      data-testid={`badge-${name
+        .toLowerCase()
+        .replace(/[^a-z0-9]+/g, '-')
+        .replace(/^-+|-+$/g, '')}`}
       data-css-class={cssClass}
       data-show-tooltip={showTooltip}
     >
       <span data-testid={`icon-${cssClass.replace('fa-', '')}`} />
     </div>
   )

If you adopt this, please update the two tests that assert special-char IDs accordingly.


676-703: Optional: prefer a safer test-id for special characters

Using raw special characters in data-testid can be error-prone in selectors and tooling. If you keep them, consider also asserting by visible name or role to reduce coupling to test-id formatting.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 88cc6dd and f22d2e0.

📒 Files selected for processing (17)
  • backend/apps/github/api/internal/nodes/user.py (2 hunks)
  • backend/apps/nest/api/internal/nodes/badge.py (1 hunks)
  • backend/tests/apps/github/api/internal/nodes/user_test.py (3 hunks)
  • cspell/custom-dict.txt (1 hunks)
  • frontend/__tests__/unit/components/Badges.test.tsx (1 hunks)
  • frontend/__tests__/unit/components/UserCard.test.tsx (3 hunks)
  • frontend/__tests__/unit/data/mockBadgeData.ts (1 hunks)
  • frontend/__tests__/unit/data/mockUserDetails.ts (1 hunks)
  • frontend/__tests__/unit/pages/UserDetails.test.tsx (2 hunks)
  • frontend/src/app/members/[memberKey]/page.tsx (2 hunks)
  • frontend/src/app/members/page.tsx (1 hunks)
  • frontend/src/components/Badges.tsx (1 hunks)
  • frontend/src/components/UserCard.tsx (3 hunks)
  • frontend/src/server/queries/userQueries.ts (3 hunks)
  • frontend/src/types/badge.ts (1 hunks)
  • frontend/src/types/card.ts (2 hunks)
  • frontend/src/types/user.ts (2 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-07-11T15:57:56.648Z
Learnt from: Rajgupta36
PR: OWASP/Nest#1717
File: backend/apps/mentorship/graphql/queries/module.py:39-50
Timestamp: 2025-07-11T15:57:56.648Z
Learning: In the OWASP Nest mentorship GraphQL queries, Strawberry GraphQL automatically converts between Django Module instances and ModuleNode types, so methods can return Module instances directly without manual conversion even when typed as ModuleNode.

Applied to files:

  • backend/apps/nest/api/internal/nodes/badge.py
🧬 Code graph analysis (7)
frontend/src/types/card.ts (1)
frontend/src/types/badge.ts (1)
  • Badge (1-7)
frontend/src/types/user.ts (1)
frontend/src/types/badge.ts (1)
  • Badge (1-7)
backend/apps/github/api/internal/nodes/user.py (1)
backend/apps/nest/api/internal/nodes/badge.py (1)
  • BadgeNode (18-19)
backend/apps/nest/api/internal/nodes/badge.py (1)
frontend/src/types/badge.ts (1)
  • Badge (1-7)
backend/tests/apps/github/api/internal/nodes/user_test.py (2)
backend/apps/nest/api/internal/nodes/badge.py (1)
  • BadgeNode (18-19)
backend/apps/github/api/internal/nodes/user.py (3)
  • badges (32-39)
  • UserNode (28-69)
  • badge_count (42-44)
frontend/__tests__/unit/data/mockBadgeData.ts (1)
frontend/src/types/badge.ts (1)
  • Badge (1-7)
frontend/__tests__/unit/pages/UserDetails.test.tsx (2)
frontend/__tests__/unit/data/mockUserDetails.ts (1)
  • mockUserDetailsData (1-83)
backend/apps/github/api/internal/nodes/user.py (1)
  • badges (32-39)
🔇 Additional comments (14)
cspell/custom-dict.txt (1)

59-59: LGTM — avoids false positives for Font Awesome style token.

frontend/src/types/card.ts (1)

3-3: LGTM — props surface aligned with types and pages.

Also applies to: 80-82

frontend/__tests__/unit/data/mockUserDetails.ts (1)

16-33: Confirm Font Awesome version and update icon class.
fa-shield-alt is FA5; in FA6 the icon is shield-halved — use "fa-solid fa-shield-halved" (or "fas fa-shield-halved"); update frontend/tests/unit/data/mockUserDetails.ts (lines 16–33) to replace 'fa-shield-alt' or enable FA6 legacy aliases.

frontend/src/app/members/page.tsx (1)

37-46: Prefer backend-provided badgeCount with nullish coalescing; verify Algolia 'users' index has the field.

Use backend badgeCount when present; fall back to badges.length.

File: frontend/src/app/members/page.tsx (lines ~37-46)

-    const badgeCount = user.badges?.length || 0
+    const badgeCount = user.badgeCount ?? user.badges?.length ?? 0

Ensure the Algolia "users" index includes badgeCount (or keep the fallback).

frontend/src/types/user.ts (1)

1-1: Type additions look good — GraphQL camelCase is enabled by default.
Schema is instantiated in backend/settings/graphql.py (schema = strawberry.Schema(...)) with no explicit auto_camel_case override; Strawberry converts snake_case field names to camelCase by default, so frontend fields (badgeCount, badges, avatarUrl) will be exposed as expected. (github.com)

frontend/src/components/UserCard.tsx (1)

17-27: LGTM: prop addition and wiring look correct.

badgeCount is optional, default-falsy behavior is fine and won’t render when absent/0. Tests cover negative/undefined scenarios.

backend/apps/nest/api/internal/nodes/badge.py (1)

1-20: LGTM: schema surface matches frontend needs.

Fields map cleanly to GraphQL (auto-camelCase → cssClass), and read-only exposure is appropriate.

frontend/__tests__/unit/components/UserCard.test.tsx (1)

385-420: LGTM: badge count test coverage is solid.

Positive, zero, negative, and large-number formatting cases are covered alongside combined metrics.

frontend/src/server/queries/userQueries.ts (2)

10-18: LGTM: server–client field naming aligns.

badges { id name description cssClass weight } and badgeCount match backend’s auto-camelCased fields.


111-111: LGTM: metadata query exposes badgeCount for lightweight needs.

frontend/__tests__/unit/data/mockBadgeData.ts (1)

1-64: LGTM: concise fixtures match type surface.

Covers both with/without badges and aligns with Badge shape.

backend/apps/github/api/internal/nodes/user.py (1)

31-40: Confirm relation semantics for self.badges (through-model vs direct M2M)

Sandbox verification failed; confirm whether self.badges is a through-model (e.g., UserBadge) with is_active and a ForeignKey named badge (so user_badge.badge is valid). If it's a direct ManyToMany to Badge, select_related("badge") and user_badge.badge are incorrect and the resolver should be adjusted accordingly.

File: backend/apps/github/api/internal/nodes/user.py (lines 31–40)

frontend/__tests__/unit/pages/UserDetails.test.tsx (2)

521-533: Good coverage: presence of badges section and basic rendering

This validates the high-level rendering path without overspecifying implementation details. Nicely scoped.


598-656: Fallback cssClass behavior is exercised well

Both undefined and empty string cases are covered; assertions on the propagated prop keep the test focused on UI contract rather than implementation.

Copy link
Collaborator

@arkid15r arkid15r left a comment

Choose a reason for hiding this comment

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

Please fix the conflicts and address bot's suggestions first.

@arkid15r arkid15r marked this pull request as draft September 13, 2025 18:48
@Piyushrathoree
Copy link
Collaborator Author

Please fix the conflicts and address bot's suggestions first.

Got it , I'll be doing it in morning

Piyushrathoree and others added 10 commits September 14, 2025 13:34
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
@Piyushrathoree Piyushrathoree marked this pull request as ready for review September 14, 2025 08:31
Copy link
Collaborator

@kasya kasya left a comment

Choose a reason for hiding this comment

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

Nice start! Left some requests.

// Fallback to a default icon if the specified icon doesn't exist
return (
<div className="inline-flex items-center">
{showTooltip ? (
Copy link
Collaborator

Choose a reason for hiding this comment

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

With this approach there's a code duplication for the same icon.
Tooltip component from heroui has isDisabled property that we can use instead and have just one line of code.

Copy link
Collaborator

Choose a reason for hiding this comment

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

@Piyushrathoree why was this resolved? 😮 I don't see changes I requested in this comment.

You don't need a showTooltip ternary logic here. You can use have Tooltip wrapper around a single FA icon element and pass in showTooltip to isDisabled property in the Tooltip


return (
<div className="inline-flex items-center">
{showTooltip ? (
Copy link
Collaborator

Choose a reason for hiding this comment

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

Same here for code duplication.

Comment on lines 31 to 36
try {
findIconDefinition(lookup)
iconFound = true
} catch {
iconFound = false
}
Copy link
Collaborator

@kasya kasya Sep 14, 2025

Choose a reason for hiding this comment

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

You should be able to simplify this without having to set iconFound separately. If icon is found - it's true else I believe it returns null (you'll need to verify though!)
So you could just return result of findIconDefinition() here

Copy link
Collaborator

Choose a reason for hiding this comment

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

Same here - this should not be marked as resoled if it wasn't addressed.
Did you try this out? If it's not possible - you need to respond with why this has not been applied

@{user?.login}
</Link>
<p className="text-gray-600 dark:text-gray-400">{formattedBio}</p>
{user?.badges && user.badges.length > 0 && (
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can we use badgeCount here instead? 🤔

@kasya
Copy link
Collaborator

kasya commented Sep 14, 2025

Also please run make check before pushing your changes 👌🏼

@Piyushrathoree
Copy link
Collaborator Author

Also please run make check before pushing your changes 👌🏼

thanks for this kate , I'll be solving all the issues soon and make sure this for next issues

@Piyushrathoree
Copy link
Collaborator Author

@arkid15r please take a look here

Copy link
Collaborator

@kasya kasya left a comment

Choose a reason for hiding this comment

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

Your approach with handling icons on the frontend is very limited.
At the moment, anything can be sent from the backend, and even if you add dynamic imports for these icons on the frontend, maintaining good performance will still be difficult.

I recommend you changing it to:

  • Limit what is saved on the Badge model on the backend for css_class field with choices and add validation (5-10 icons at most)
  • Import these icons on the frontend and add to library in utils/data.ts so we are always ready to show them.

This is the simplest solution.

@kasya
Copy link
Collaborator

kasya commented Oct 8, 2025

@Piyushrathoree just wanted to check if you will be working on this updates further? I'm just not sure after tour response.

@Piyushrathoree
Copy link
Collaborator Author

@Piyushrathoree just wanted to check if you will be working on this updates further? I'm just not sure after tour response.

i'll be working on this and fix all the things today

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
frontend/src/server/queries/userQueries.ts (1)

12-18: Inconsistent field ordering between queries.

The badges field selection has different ordering in GET_LEADER_DATA (id, name, description, cssClass) versus GET_USER_DATA (cssClass, description, id, name). While functionally equivalent, consistent ordering improves maintainability.

Apply this diff to standardize the field order in GET_USER_DATA:

       badges {
-        cssClass
-        description
         id
         name
+        description
+        cssClass
       }

Also applies to: 90-96

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fb1e403 and 05a694c.

⛔ Files ignored due to path filters (2)
  • frontend/src/types/__generated__/graphql.ts is excluded by !**/__generated__/**
  • frontend/src/types/__generated__/userQueries.generated.ts is excluded by !**/__generated__/**
📒 Files selected for processing (4)
  • frontend/__tests__/unit/pages/UserDetails.test.tsx (3 hunks)
  • frontend/src/app/members/[memberKey]/page.tsx (3 hunks)
  • frontend/src/server/queries/userQueries.ts (3 hunks)
  • frontend/src/types/user.ts (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • frontend/src/app/members/[memberKey]/page.tsx
🧰 Additional context used
🧬 Code graph analysis (2)
frontend/__tests__/unit/pages/UserDetails.test.tsx (1)
frontend/__tests__/unit/data/mockUserDetails.ts (1)
  • mockUserDetailsData (1-83)
frontend/src/types/user.ts (1)
frontend/src/types/badge.ts (1)
  • Badge (1-7)
🔇 Additional comments (6)
frontend/src/types/user.ts (1)

1-1: LGTM! Type extensions align with badge feature.

The Badge import and optional User type fields (badges and badgeCount) are correctly defined and consistent with the GraphQL schema extensions.

Also applies to: 14-15

frontend/__tests__/unit/pages/UserDetails.test.tsx (4)

18-30: LGTM! FontAwesomeIcon mock correctly handles different icon prop formats.

The mock properly extracts the icon name from both array format (e.g., ['fas', 'star']) and object format (e.g., { iconName: 'star' }), making it suitable for testing various FontAwesome icon usages.


32-56: LGTM! Badges component mock provides clear test hooks.

The MockBadges component correctly:

  • Accepts the expected props (name, cssClass, showTooltip)
  • Creates predictable test IDs by slugifying badge names
  • Exposes data attributes for assertion purposes
  • Renders a nested icon element for comprehensive testing

69-69: LGTM! Route parameter updated to match current naming.

The change from userKey to memberKey aligns with the route parameter rename to [memberKey].

Note: A past review comment indicated that other test files (Users.test.tsx, Projects.test.tsx) also need similar updates, but those files are not in the current review scope.


539-735: LGTM! Comprehensive badge test coverage.

The Badge Display Tests suite thoroughly covers:

  • Basic rendering when badges are present
  • Props validation (cssClass, showTooltip)
  • Graceful handling of empty/undefined badges
  • Fallback behavior for missing cssClass
  • Edge cases (special characters, long names)

This provides strong confidence in the badge display functionality.

frontend/src/server/queries/userQueries.ts (1)

12-18: No need to fetch weight—it’s unused on the frontend. No occurrences of .weight or "weight" were found in any .ts/.tsx files, so including it in the query is unnecessary.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 05a694c and 878059d.

📒 Files selected for processing (6)
  • backend/apps/nest/migrations/0007_alter_badge_css_class.py (1 hunks)
  • backend/apps/nest/models/badge.py (2 hunks)
  • frontend/__tests__/unit/components/Badges.test.tsx (1 hunks)
  • frontend/src/app/members/[memberKey]/page.tsx (3 hunks)
  • frontend/src/components/Badges.tsx (1 hunks)
  • frontend/src/utils/data.ts (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • frontend/src/components/Badges.tsx
  • frontend/src/app/members/[memberKey]/page.tsx
🧰 Additional context used
🧬 Code graph analysis (1)
frontend/__tests__/unit/components/Badges.test.tsx (1)
frontend/src/utils/data.ts (1)
  • BADGE_CLASS_MAP (77-84)
🪛 GitHub Actions: Run CI/CD
frontend/src/utils/data.ts

[error] 83-83: Object Literal Property name bug_slash must match one of the following formats: camelCase, UPPER_CASE (naming-convention)

frontend/__tests__/unit/components/Badges.test.tsx

[warning] 21-21: Unexpected any. Specify a different type. (no-explicit-any)


[warning] 34-34: Unexpected any. Specify a different type. (no-explicit-any)

🔇 Additional comments (6)
frontend/src/utils/data.ts (1)

35-50: LGTM!

The icon imports and library registrations are correctly implemented. All newly imported badge icons are properly added to the FontAwesome library.

backend/apps/nest/migrations/0007_alter_badge_css_class.py (1)

1-29: LGTM!

The migration correctly adds choices to the css_class field with appropriate defaults. The choices align with the BadgeCssClass enum defined in the model.

backend/apps/nest/models/badge.py (2)

13-19: LGTM!

The BadgeCssClass enum is correctly implemented using Django's TextChoices. The snake_case database values follow Django conventions, and display names are appropriately formatted.


26-31: LGTM!

The css_class field is correctly updated to use the BadgeCssClass choices with a sensible default value. This change improves data integrity by constraining values to the defined set.

frontend/__tests__/unit/components/Badges.test.tsx (2)

5-16: Improved mock implementation addresses past concerns.

This mock setup is a significant improvement over the previous overmocked version. By importing the actual BADGE_CLASS_MAP and using it to determine which icons are registered, the tests now more closely reflect production behavior.


72-104: LGTM!

The test cases provide good coverage of the component's core functionality, including valid/invalid icon rendering, fallback behavior, and tooltip visibility control.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
frontend/src/app/members/[memberKey]/page.tsx (1)

206-206: Remove unnecessary .slice() call.

The .slice() call creates a copy of the array before mapping, but it's not needed here since the operation is read-only and doesn't mutate the original array. This adds unnecessary overhead.

Apply this diff:

-             {user.badges.slice().map((badge: Badge) => (
+             {user.badges.map((badge: Badge) => (
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 878059d and 6e1bbe7.

📒 Files selected for processing (2)
  • frontend/src/app/members/[memberKey]/page.tsx (3 hunks)
  • frontend/src/utils/data.ts (3 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
frontend/src/app/members/[memberKey]/page.tsx (1)
frontend/src/types/badge.ts (1)
  • Badge (1-7)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: CodeQL (javascript-typescript)
🔇 Additional comments (2)
frontend/src/utils/data.ts (1)

77-84: Verify bugSlash icon mapping and badge key conversion

  • The key bugSlash maps to faBug; update to faBugSlash if that was intended.
  • Confirm that backend bug_slash identifiers are converted to camelCase before lookup in this map.
frontend/src/app/members/[memberKey]/page.tsx (1)

208-212: Badge component prop signature updated
The BadgeProps type in frontend/src/components/Badges.tsx is defined as

type BadgeProps = {
  name: string
  cssClass: string
  showTooltip?: boolean
}

It no longer accepts description or weight; passing only name, cssClass, and showTooltip is correct.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (5)
backend/apps/github/models/mixins/user.py (1)

185-189: LGTM! Consistent with existing index properties.

The implementation correctly filters active badges and returns the count. The approach is consistent with other count properties in this mixin (e.g., idx_issues_count, idx_releases_count).

Optional: If indexing performance becomes a concern, consider using select_related/prefetch_related at the indexing call site to minimize database queries, though this optimization would apply to all idx_ properties collectively rather than this one in isolation.

frontend/src/components/Badges.tsx (1)

18-21: Simplify icon resolution logic.

The function is clear, but you can streamline it slightly.

Consider:

 const resolveIcon = (cssClass: string) => {
-  const normalizedClass = normalizeCssClass(cssClass)
-  return BADGE_CLASS_MAP[normalizedClass] ?? DEFAULT_ICON
+  const normalized = normalizeCssClass(cssClass)
+  return BADGE_CLASS_MAP[normalized] || DEFAULT_ICON
 }
frontend/__tests__/unit/components/Badges.test.tsx (2)

8-19: Replace implicit any with proper TypeScript types.

The getName function parameter uses an implicit any type. While the logic is sound, adding explicit types improves type safety and maintainability.

Apply this diff:

+import type { IconDefinition } from '@fortawesome/fontawesome-svg-core'
+
 jest.mock('wrappers/FontAwesomeIconWrapper', () => {
   const RealWrapper = jest.requireActual('wrappers/FontAwesomeIconWrapper').default
 
-  const getName = (icon) => {
+  const getName = (icon: IconDefinition | string | [string, string] | undefined) => {
     if (!icon) return 'medal'
     if (typeof icon === 'string') {
       const m = icon.match(/fa-([a-z0-9-]+)$/i)
       if (m) return m[1]
       const last = icon.trim().split(/\s+/).pop() || ''
       return last.replace(/^fa-/, '') || 'medal'
     }
     if (Array.isArray(icon) && icon.length >= 2) return String(icon[1])
-    if (icon && typeof icon === 'object') return icon.iconName || String(icon[1] ?? 'medal')
+    if (icon && typeof icon === 'object' && 'iconName' in icon) {
+      return icon.iconName || 'medal'
+    }
     return 'medal'
   }

21-28: Replace implicit any type in mock function.

The props parameter uses an implicit any type.

Apply this diff:

-  return function MockFontAwesomeIconWrapper(props) {
+  return function MockFontAwesomeIconWrapper(props: {
+    icon: IconDefinition | string | [string, string] | undefined
+    [key: string]: unknown
+  }) {
     const name = getName(props.icon)
     return (
       <div data-testid={`icon-${name}`}>
         <RealWrapper {...props} />
       </div>
     )
   }
frontend/src/server/queries/userQueries.ts (1)

12-19: Consider removing unused weight field from badges query.

The weight field is queried in both GET_LEADER_DATA and GET_USER_DATA, but the Badges component (frontend/src/components/Badges.tsx) doesn't consume it. It only appears in test mock data. Unless you plan to use it for sorting or display logic in the near future, removing it reduces the GraphQL payload size.

If you intend to keep it for future use (e.g., client-side badge sorting), document that intent in a comment. Otherwise, apply:

       badges {
         id
         name
         description
         cssClass
-        weight
       }

Also applies to: 91-98

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6e1bbe7 and 848ae72.

⛔ Files ignored due to path filters (1)
  • frontend/src/types/__generated__/userQueries.generated.ts is excluded by !**/__generated__/**
📒 Files selected for processing (11)
  • backend/apps/core/utils/index.py (1 hunks)
  • backend/apps/github/index/registry/user.py (1 hunks)
  • backend/apps/github/index/search/user.py (1 hunks)
  • backend/apps/github/models/mixins/user.py (1 hunks)
  • frontend/__tests__/unit/components/Badges.test.tsx (1 hunks)
  • frontend/__tests__/unit/pages/UserDetails.test.tsx (3 hunks)
  • frontend/src/app/members/[memberKey]/page.tsx (3 hunks)
  • frontend/src/app/members/page.tsx (1 hunks)
  • frontend/src/components/Badges.tsx (1 hunks)
  • frontend/src/server/queries/userQueries.ts (3 hunks)
  • frontend/src/utils/data.ts (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • frontend/src/app/members/[memberKey]/page.tsx
  • frontend/src/utils/data.ts
  • frontend/src/app/members/page.tsx
🧰 Additional context used
🧬 Code graph analysis (2)
frontend/src/components/Badges.tsx (1)
frontend/src/utils/data.ts (1)
  • BADGE_CLASS_MAP (78-85)
frontend/__tests__/unit/pages/UserDetails.test.tsx (1)
frontend/__tests__/unit/data/mockUserDetails.ts (1)
  • mockUserDetailsData (1-83)
🔇 Additional comments (9)
backend/apps/core/utils/index.py (1)

199-199: LGTM! Proper alphabetical placement.

The addition of idx_badge_count to the users index attributes is correct and maintains alphabetical ordering.

backend/apps/github/index/search/user.py (1)

35-35: LGTM! Consistent alphabetical ordering.

The addition of idx_badge_count to the default attributes is correct and properly positioned alphabetically.

backend/apps/github/index/registry/user.py (1)

17-17: LGTM! Completes the indexing infrastructure.

The addition of idx_badge_count to the index fields properly integrates the new badge count capability into the Algolia index configuration, maintaining alphabetical order and completing the changes across the indexing stack (model → registry → search → utils).

frontend/src/components/Badges.tsx (1)

23-33: Implementation addresses past review concerns effectively.

The component now:

  • Uses BADGE_CLASS_MAP for consistent icon resolution
  • Leverages Tooltip's isDisabled prop to avoid code duplication
  • Falls back gracefully to the medal icon
  • Passes the resolved IconDefinition directly to FontAwesomeIconWrapper

This is a significant improvement over earlier iterations that had FA lookup issues and redundant conditional rendering.

frontend/__tests__/unit/components/Badges.test.tsx (1)

93-120: Backend enum icon tests are comprehensive.

The test suite correctly validates:

  • All backend enum values (including bug_slash with snake_case)
  • Snake_case to camelCase transformation
  • Direct camelCase input handling

This addresses the prior concern about inconsistent naming between backend and frontend.

frontend/src/server/queries/userQueries.ts (1)

106-116: GraphQL query additions align with badge requirements.

Adding badgeCount and the full badges array with necessary fields (id, name, description, cssClass) enables the frontend to render user badges per the PR objectives.

frontend/__tests__/unit/pages/UserDetails.test.tsx (3)

18-30: FontAwesomeIcon mock properly typed and flexible.

The updated mock correctly handles multiple icon format variations (array, object with iconName) and is now properly typed, addressing the TypeScript safety concern from earlier reviews.


32-56: MockBadges implementation exposes testable attributes.

The mock component:

  • Renders with a predictable data-testid based on the badge name
  • Exposes cssClass and showTooltip for verification
  • Nests the icon element with its own testid

This structure enables comprehensive assertions in the badge display tests below.


539-735: Badge display tests are thorough and cover edge cases.

The test suite validates:

  • Basic badge rendering and props
  • Empty/undefined badge arrays
  • Fallback behavior for missing/empty cssClass
  • Special characters and long names in badge names
  • Conditional rendering based on badge presence

This comprehensive coverage should catch rendering issues that earlier mocked tests missed.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
frontend/src/app/members/[memberKey]/page.tsx (1)

210-210: Remove unnecessary .slice() call.

The .slice() creates an array copy but the code doesn't mutate the array. Since the backend provides badges in the correct order (as discussed in previous comments), this allocation is unnecessary.

Apply this diff:

-                {user.badges.slice().map((badge: Badge) => (
+                {user.badges.map((badge: Badge) => (
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6e1bbe7 and 995f67a.

⛔ Files ignored due to path filters (2)
  • frontend/src/types/__generated__/graphql.ts is excluded by !**/__generated__/**
  • frontend/src/types/__generated__/userQueries.generated.ts is excluded by !**/__generated__/**
📒 Files selected for processing (12)
  • backend/apps/core/utils/index.py (1 hunks)
  • backend/apps/github/index/registry/user.py (1 hunks)
  • backend/apps/github/index/search/user.py (1 hunks)
  • backend/apps/github/models/mixins/user.py (1 hunks)
  • frontend/__tests__/unit/components/Badges.test.tsx (1 hunks)
  • frontend/__tests__/unit/pages/UserDetails.test.tsx (3 hunks)
  • frontend/src/app/members/[memberKey]/page.tsx (3 hunks)
  • frontend/src/app/members/page.tsx (1 hunks)
  • frontend/src/components/Badges.tsx (1 hunks)
  • frontend/src/server/queries/userQueries.ts (3 hunks)
  • frontend/src/types/card.ts (2 hunks)
  • frontend/src/utils/data.ts (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • frontend/tests/unit/components/Badges.test.tsx
  • frontend/src/server/queries/userQueries.ts
  • frontend/src/app/members/page.tsx
🧰 Additional context used
🧬 Code graph analysis (4)
frontend/src/types/card.ts (1)
frontend/src/types/badge.ts (1)
  • Badge (1-7)
frontend/__tests__/unit/pages/UserDetails.test.tsx (1)
frontend/__tests__/unit/data/mockUserDetails.ts (1)
  • mockUserDetailsData (1-83)
frontend/src/components/Badges.tsx (1)
frontend/src/utils/data.ts (1)
  • BADGE_CLASS_MAP (78-85)
frontend/src/app/members/[memberKey]/page.tsx (1)
frontend/src/types/badge.ts (1)
  • Badge (1-7)
🪛 GitHub Actions: Run CI/CD
frontend/src/utils/data.ts

[error] 72-72: Unstaged changes detected. Run make check and use git add to address it.

🔇 Additional comments (10)
backend/apps/github/models/mixins/user.py (1)

186-189: LGTM!

The idx_badge_count property correctly filters active badges and returns the count. The implementation is consistent with other indexing properties in this mixin.

backend/apps/github/index/search/user.py (1)

35-35: LGTM!

The idx_badge_count attribute is correctly added to the default retrieval list in alphabetical order, consistent with the indexing changes across the codebase.

backend/apps/github/index/registry/user.py (1)

17-17: LGTM!

The idx_badge_count field is properly registered in the UserIndex fields tuple, maintaining alphabetical order and consistency with the model property.

backend/apps/core/utils/index.py (1)

199-199: LGTM!

The idx_badge_count attribute is correctly included in the attributesToRetrieve list for the "users" index, maintaining alphabetical order and consistency with the broader indexing changes.

frontend/src/types/card.ts (1)

3-3: LGTM!

The Badge type import and the new optional badges and badgeCount fields on UserCardProps are correctly typed and appropriately optional, allowing components to render badge data when available.

Also applies to: 82-83

frontend/src/utils/data.ts (1)

1-1: LGTM!

The badge icon imports, library registration, and BADGE_CLASS_MAP are correctly implemented. The naming convention issue with bugSlash (previously bug_slash) has been resolved, and all icons are properly imported and added to the FontAwesome library.

Note: The pipeline failure regarding unstaged changes should be resolved by running make check and staging the formatted changes, as indicated by the CI error.

Also applies to: 35-40, 47-51, 78-85

frontend/src/app/members/[memberKey]/page.tsx (1)

208-220: Consider displaying the badge count.

The badgeCount field is available from the GraphQL query (as seen in UserCardProps), but it's not displayed in the UI. Showing a count (e.g., "5 badges" or a numeric indicator) could enhance the user experience, especially if there are many badges.

Should the badge count be displayed in the user detail header, or is rendering all badges sufficient for this view? On the members list page (where space is limited), a count might be more appropriate than rendering all badges.

frontend/src/components/Badges.tsx (1)

23-33: LGTM!

The Badges component implementation is clean and correct:

  • Uses Tooltip's isDisabled prop to conditionally show tooltips without code duplication (addressing previous feedback).
  • Resolves icons via BADGE_CLASS_MAP with a sensible fallback to DEFAULT_ICON.
  • Passes IconDefinition objects directly to FontAwesomeIconWrapper, which is the correct pattern.
  • Includes data-testid for testing.
frontend/__tests__/unit/pages/UserDetails.test.tsx (2)

18-29: LGTM - FontAwesomeIcon mock handles both icon formats correctly.

The updated mock properly extracts the icon name from either array format ['prefix', 'iconName'] or object format { iconName: 'name' }, making it flexible for different FontAwesome usage patterns in the codebase.


32-56: Mock props align with real Badges component

The mock’s name, cssClass, and optional showTooltip props exactly match the BadgeProps in frontend/src/components/Badges.tsx. No changes required.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
backend/tests/apps/github/api/internal/nodes/user_test.py (1)

131-190: LGTM!

The test correctly verifies that the badges resolver configures the queryset with proper ordering (order_by("badge__weight", "badge__name")) and returns badges in the expected sequence.

Optional: Consider removing unused mock attributes.

The weight and name attributes on the mock badges (lines 135-148) are never accessed since this unit test only verifies the ORM method calls, not the actual sorting logic. While they serve as documentation, removing them would clarify that this test validates the queryset configuration rather than the sorting behavior itself.

If you prefer to keep them for documentation purposes, that's also fine.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2078a70 and bf7e112.

📒 Files selected for processing (4)
  • backend/apps/github/api/internal/nodes/user.py (1 hunks)
  • backend/tests/apps/core/utils/match_test.py (1 hunks)
  • backend/tests/apps/github/api/internal/nodes/user_test.py (3 hunks)
  • frontend/__tests__/unit/pages/UserDetails.test.tsx (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • backend/apps/github/api/internal/nodes/user.py
🧰 Additional context used
🧬 Code graph analysis (2)
backend/tests/apps/github/api/internal/nodes/user_test.py (2)
backend/apps/nest/api/internal/nodes/badge.py (1)
  • BadgeNode (19-20)
backend/apps/github/api/internal/nodes/user.py (3)
  • UserNode (28-67)
  • badge_count (40-42)
  • badges (32-37)
frontend/__tests__/unit/pages/UserDetails.test.tsx (1)
frontend/__tests__/unit/data/mockUserDetails.ts (1)
  • mockUserDetailsData (1-83)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Run frontend e2e tests
  • GitHub Check: Run frontend unit tests
  • GitHub Check: Run backend tests
🔇 Additional comments (9)
backend/tests/apps/core/utils/match_test.py (1)

117-117: LGTM! Test correctly updated to reflect implementation changes.

The addition of "idx_badge_count" to the attributesToRetrieve list is correctly positioned in alphabetical order and aligns with the implementation changes that introduce badge count indexing for users.

backend/tests/apps/github/api/internal/nodes/user_test.py (5)

8-8: LGTM!

The BadgeNode import is correctly added and used appropriately in the test methods below.


21-23: LGTM!

The addition of "badge_count" to the expected field names correctly reflects the new public API field on UserNode.


86-97: LGTM!

The test correctly verifies the badge_count resolver implementation, properly mocking the queryset chain (values("badge_id").distinct().count()) and confirming all method calls are made as expected.


99-111: LGTM!

The test correctly verifies the badges resolver behavior with an empty badges list, ensuring the queryset chain (select_related("badge").order_by("badge__weight", "badge__name")) is properly configured even when no badges are present.


113-129: LGTM!

The test correctly verifies the badges resolver with a single badge, properly using spec=BadgeNode for type safety and confirming the queryset chain is configured correctly.

frontend/__tests__/unit/pages/UserDetails.test.tsx (3)

18-29: LGTM — FontAwesomeIcon mock handles both icon formats correctly.

The updated mock appropriately derives iconName from either array or object format and renders the expected test elements.


32-56: LGTM — Badges mock component is well-structured for testing.

The mock correctly exposes badge properties via data attributes and test IDs, enabling thorough verification of badge rendering behavior.


540-734: Excellent edge case coverage for badge rendering.

The test suite comprehensively covers:

  • Presence/absence of badges
  • Undefined/empty badge arrays
  • Fallback cssClass behavior
  • Special characters and long names

@sonarqubecloud
Copy link

@arkid15r arkid15r enabled auto-merge October 13, 2025 04:05
Copy link
Collaborator

@kasya kasya left a comment

Choose a reason for hiding this comment

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

hey @Piyushrathoree !

This was taking way too long to address all the comments, so I ended up pushing changes myself so that we can release this today.
Thank you for working on this.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
backend/apps/github/api/internal/nodes/user.py (1)

31-34: Eliminate code duplication by reusing idx_badge_count.

The badge_count field duplicates the logic from idx_badge_count in the UserIndexMixin. Consider reusing the existing property for consistency and maintainability.

Apply this diff:

 @strawberry.field
 def badge_count(self) -> int:
     """Resolve badge count."""
-    return self.user_badges.filter(is_active=True).count()
+    return self.idx_badge_count
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bf7e112 and 6c2a612.

⛔ Files ignored due to path filters (2)
  • frontend/pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
  • frontend/src/types/__generated__/userQueries.generated.ts is excluded by !**/__generated__/**
📒 Files selected for processing (11)
  • backend/apps/github/api/internal/nodes/user.py (1 hunks)
  • backend/apps/github/models/mixins/user.py (1 hunks)
  • backend/apps/nest/models/badge.py (2 hunks)
  • backend/tests/apps/github/api/internal/nodes/user_test.py (3 hunks)
  • frontend/package.json (1 hunks)
  • frontend/src/app/members/page.tsx (1 hunks)
  • frontend/src/server/queries/userQueries.ts (3 hunks)
  • frontend/src/types/badge.ts (1 hunks)
  • frontend/src/types/card.ts (2 hunks)
  • frontend/src/types/user.ts (2 hunks)
  • frontend/src/utils/data.ts (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (5)
  • frontend/src/types/badge.ts
  • backend/apps/nest/models/badge.py
  • frontend/src/server/queries/userQueries.ts
  • frontend/src/types/card.ts
  • frontend/src/app/members/page.tsx
🧰 Additional context used
🧬 Code graph analysis (3)
frontend/src/types/user.ts (2)
backend/apps/nest/models/badge.py (1)
  • Badge (10-50)
frontend/src/types/badge.ts (1)
  • Badge (1-7)
backend/tests/apps/github/api/internal/nodes/user_test.py (3)
frontend/src/types/__generated__/graphql.ts (2)
  • BadgeNode (40-47)
  • UserNode (877-899)
backend/apps/nest/api/internal/nodes/badge.py (1)
  • BadgeNode (19-20)
backend/apps/github/api/internal/nodes/user.py (3)
  • UserNode (28-76)
  • badge_count (32-34)
  • badges (37-51)
backend/apps/github/api/internal/nodes/user.py (2)
frontend/src/types/__generated__/graphql.ts (1)
  • BadgeNode (40-47)
backend/apps/nest/api/internal/nodes/badge.py (1)
  • BadgeNode (19-20)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Run frontend unit tests
  • GitHub Check: Run frontend e2e tests
  • GitHub Check: Run backend tests
🔇 Additional comments (10)
frontend/package.json (1)

80-80: Why downgrade and pin @swc/core?

This change downgrades from the previously allowed ^1.13.20 (which includes 1.13.20 and newer patch releases) to a pinned 1.13.19, dropping fixes and security patches published in 1.13.20+. Please confirm the regression you’re avoiding and consider pinning to at least 1.13.20 (or whatever patch contains the required fix) so we don’t lock in an older, potentially vulnerable build.

backend/apps/github/models/mixins/user.py (1)

27-30: LGTM!

The idx_badge_count property correctly filters active badges and returns the count. The implementation is consistent with other index properties in this mixin.

backend/apps/github/api/internal/nodes/user.py (1)

36-51: LGTM!

The badges resolver correctly:

  • Filters for active badges
  • Uses select_related("badge") to avoid N+1 queries
  • Orders by weight and name
  • Returns the badge objects
backend/tests/apps/github/api/internal/nodes/user_test.py (6)

8-8: LGTM!

Import of BadgeNode is necessary for the new badge-related tests.


23-23: LGTM!

Correctly adds badge_count to the expected field names, reflecting the new field on UserNode.


86-96: LGTM!

The test correctly validates that badge_count calls filter(is_active=True).count() on the user_badges queryset and returns the expected count.


98-111: LGTM!

The test properly verifies the empty badges scenario, ensuring the queryset chain (filterselect_relatedorder_by) is called with correct arguments and returns an empty list.


113-130: LGTM!

The test correctly validates single badge resolution, verifying both the queryset chain and the returned badge object.


132-192: LGTM!

This comprehensive test validates the sorting behavior with multiple badges of varying weights and names. The test setup and assertions correctly verify:

  • Badges are ordered by weight (ascending), then by name (ascending)
  • The queryset methods are called with the correct arguments
  • The returned list matches the expected order
frontend/src/types/user.ts (1)

13-14: User badge fields wired correctly

Optional badgeCount/badges align with backend additions and keep the User type backward-compatible. Nice work.

@arkid15r arkid15r added this pull request to the merge queue Oct 13, 2025
Merged via the queue into OWASP:main with commit 9766b3c Oct 13, 2025
26 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Display user badges on frontend

3 participants