Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,43 +1,86 @@
import { render, screen } from '@testing-library/react';
import UserPageIdentityHeaderCIC from '@/components/user/identity/header/UserPageIdentityHeaderCIC';
import type { ApiIdentity } from '@/generated/models/ApiIdentity';
import { render, screen } from "@testing-library/react";
import UserPageIdentityHeaderCIC from "@/components/user/identity/header/UserPageIdentityHeaderCIC";
import type { ApiIdentity } from "@/generated/models/ApiIdentity";
import type { ApiCicOverview } from "@/generated/models/ApiCicOverview";

jest.mock('@tanstack/react-query', () => ({
useQuery: jest.fn(() => ({ data: { count: 2 } })),
}));
jest.mock(
"@/components/user/utils/user-cic-type/UserCICTypeIconWrapper",
() => ({
__esModule: true,
default: () => <div data-testid="icon" />,
})
);

jest.mock('@/components/user/utils/user-cic-type/UserCICTypeIconWrapper', () => ({
__esModule: true,
default: () => <div data-testid="icon" />,
}));

jest.mock('@/components/user/rep/header/TopRaterAvatars', () => ({
jest.mock("@/components/common/OverlappingAvatars", () => ({
__esModule: true,
default: () => <div data-testid="raters-avatars" />,
}));

jest.mock('@/components/user/utils/user-cic-status/UserCICStatus', () => ({
jest.mock("@/components/user/utils/user-cic-status/UserCICStatus", () => ({
__esModule: true,
default: ({ cic }: { cic: number }) => <div data-testid="status">{cic}</div>,
}));

describe('UserPageIdentityHeaderCIC', () => {
const baseProfile: ApiIdentity = { cic: 1000, handle: 'alice' } as ApiIdentity;
const makeCicOverview = (
totalCic: number,
contributorCount: number
): ApiCicOverview =>
({
total_cic: totalCic,
authenticated_user_contribution: null,
contributor_count: contributorCount,
contributors: {
data: [
{
contribution: 500,
profile: {
id: "1",
handle: "bob",
pfp: null,
primary_address: "0x123",
},
},
],
page: 1,
next: false,
},
}) as unknown as ApiCicOverview;

describe("UserPageIdentityHeaderCIC", () => {
const baseProfile: ApiIdentity = {
cic: 1000,
handle: "alice",
} as ApiIdentity;

it('displays NIC and status info', () => {
render(<UserPageIdentityHeaderCIC profile={baseProfile} />);
expect(screen.getByText('NIC')).toBeInTheDocument();
expect(screen.getByText('1,000')).toBeInTheDocument();
expect(screen.getByTestId('raters-avatars')).toBeInTheDocument();
expect(screen.getByText('2 raters')).toBeInTheDocument();
expect(screen.getByTestId('icon')).toBeInTheDocument();
expect(screen.getByTestId('status')).toHaveTextContent('1000');
it("displays NIC and status info from cicOverview", () => {
const overview = makeCicOverview(1000, 2);
render(
<UserPageIdentityHeaderCIC profile={baseProfile} cicOverview={overview} />
);
expect(screen.getByText("NIC")).toBeInTheDocument();
expect(screen.getByText("1,000")).toBeInTheDocument();
expect(screen.getByTestId("raters-avatars")).toBeInTheDocument();
expect(screen.getByText("2 raters")).toBeInTheDocument();
expect(screen.getByTestId("icon")).toBeInTheDocument();
expect(screen.getByTestId("status")).toHaveTextContent("1000");
});

it('updates when profile prop changes', () => {
const { rerender } = render(<UserPageIdentityHeaderCIC profile={baseProfile} />);
rerender(<UserPageIdentityHeaderCIC profile={{ cic: 2000, handle: 'alice' } as ApiIdentity} />);
expect(screen.getByText('2,000')).toBeInTheDocument();
expect(screen.getByTestId('status')).toHaveTextContent('2000');
it("updates when cicOverview prop changes", () => {
const overview1 = makeCicOverview(1000, 2);
const overview2 = makeCicOverview(2000, 3);
const { rerender } = render(
<UserPageIdentityHeaderCIC
profile={baseProfile}
cicOverview={overview1}
/>
);
rerender(
<UserPageIdentityHeaderCIC
profile={{ cic: 2000, handle: "alice" } as ApiIdentity}
cicOverview={overview2}
/>
);
expect(screen.getByText("2,000")).toBeInTheDocument();
expect(screen.getByTestId("status")).toHaveTextContent("2000");
});
});
51 changes: 35 additions & 16 deletions __tests__/components/user/rep/header/UserPageRepHeader.test.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,44 @@
import { render, screen } from '@testing-library/react';
import UserPageRepHeader from '@/components/user/rep/header/UserPageRepHeader';
import { render, screen } from "@testing-library/react";
import UserPageRepHeader from "@/components/user/rep/header/UserPageRepHeader";

const mockProfile = {
handle: 'testuser',
display: 'Test User',
query: 'testuser',
handle: "testuser",
display: "Test User",
query: "testuser",
} as any;

describe('UserPageRepHeader', () => {
it('shows rep totals when provided', () => {
const repRates = {
total_rep_rating: 1500,
number_of_raters: 25,
rating_stats: [],
describe("UserPageRepHeader", () => {
it("shows rep totals when provided", () => {
const overview = {
total_rep: 1500,
contributor_count: 25,
authenticated_user_contribution: null,
contributors: { data: [], page: 1, next: false },
} as any;
render(<UserPageRepHeader repRates={repRates} profile={mockProfile} />);
expect(screen.getByText('1,500')).toBeInTheDocument();
render(
<UserPageRepHeader
overview={overview}
categories={[]}
profile={mockProfile}
repDirection="received"
onRepDirectionChange={() => {}}
loading={false}
/>
);
expect(screen.getByText("1,500")).toBeInTheDocument();
});

it('renders without repRates', () => {
const { container } = render(<UserPageRepHeader repRates={null} profile={mockProfile} />);
expect(container).toHaveTextContent('Rep');
it("renders without overview", () => {
const { container } = render(
<UserPageRepHeader
overview={null}
categories={[]}
profile={mockProfile}
repDirection="received"
onRepDirectionChange={() => {}}
loading={false}
/>
);
expect(container).toHaveTextContent("Rep");
});
});
4 changes: 3 additions & 1 deletion components/mobile-wrapper-dialog/MobileWrapperDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export default function MobileWrapperDialog({
fixedHeight,
tabletModal,
showScrollbar,
maxWidthClass,
}: {
readonly title?: string | undefined;
readonly isOpen: boolean;
Expand All @@ -32,6 +33,7 @@ export default function MobileWrapperDialog({
readonly fixedHeight?: boolean | undefined;
readonly tabletModal?: boolean | undefined;
readonly showScrollbar?: boolean | undefined;
readonly maxWidthClass?: string | undefined;
}) {
const { isCapacitor, isIos } = useCapacitor();

Expand All @@ -50,7 +52,7 @@ export default function MobileWrapperDialog({
const panelClassNames = `mobile-wrapper-dialog tw-pointer-events-auto tw-relative tw-w-screen${
tabletModal ? "" : " md:tw-max-w-screen-md"
}${isIos ? "" : " tw-transform-gpu tw-will-change-transform"}${
tabletModal ? " md:tw-w-full md:tw-max-w-md" : ""
tabletModal ? ` md:tw-w-full ${maxWidthClass ?? "md:tw-max-w-md"}` : ""
}`;

const containerClassNames = `tw-pointer-events-none tw-fixed tw-inset-x-0 tw-bottom-0 tw-flex tw-max-w-full tw-justify-center tw-pt-10${
Expand Down
21 changes: 21 additions & 0 deletions components/react-query-wrapper/ReactQueryWrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,9 @@ export enum QueryKey {
COMMUNITY_METRICS_SERIES = "COMMUNITY_METRICS_SERIES",
MINT_METRICS = "MINT_METRICS",
MARKETPLACE_PREVIEW = "MARKETPLACE_PREVIEW",
REP_OVERVIEW = "REP_OVERVIEW",
REP_CATEGORIES = "REP_CATEGORIES",
CIC_OVERVIEW = "CIC_OVERVIEW",
Comment thread
ragnep marked this conversation as resolved.
}

interface ProfileRatersParams {
Expand Down Expand Up @@ -540,6 +543,9 @@ const createReactQueryContextValue = (
}) => {
invalidateProfile(targetProfile);
invalidateLogs();
queryClient.invalidateQueries({
queryKey: [QueryKey.CIC_OVERVIEW],
});
invalidateProfileRaters({
profile: targetProfile,
matter: RateMatter.NIC,
Expand Down Expand Up @@ -620,6 +626,12 @@ const createReactQueryContextValue = (
invalidateProfile(targetProfile);
invalidateProfileRepRatings(targetProfile);
invalidateLogs();
queryClient.invalidateQueries({
queryKey: [QueryKey.REP_OVERVIEW],
});
queryClient.invalidateQueries({
queryKey: [QueryKey.REP_CATEGORIES],
});
invalidateProfileRaters({
profile: targetProfile,
matter: RateMatter.REP,
Expand Down Expand Up @@ -866,6 +878,15 @@ const createReactQueryContextValue = (
queryClient.invalidateQueries({
queryKey: [QueryKey.PROFILE_REP_RATINGS],
});
queryClient.invalidateQueries({
queryKey: [QueryKey.REP_OVERVIEW],
});
queryClient.invalidateQueries({
queryKey: [QueryKey.REP_CATEGORIES],
});
queryClient.invalidateQueries({
queryKey: [QueryKey.CIC_OVERVIEW],
});
queryClient.invalidateQueries({
queryKey: [QueryKey.COMMUNITY_MEMBERS_TOP],
});
Expand Down
1 change: 1 addition & 0 deletions components/user/followers/UserPageFollowersModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export default function UserPageFollowersModal({
tall
fixedHeight
tabletModal
maxWidthClass="md:tw-max-w-md"
showScrollbar
>
<div className="tw-px-4 sm:tw-px-6">
Expand Down
10 changes: 7 additions & 3 deletions components/user/identity/header/UserPageIdentityHeader.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,26 @@
import type { ApiCicOverview } from "@/generated/models/ApiCicOverview";
import type { ApiIdentity } from "@/generated/models/ApiIdentity";
import UserPageIdentityHeaderCIC from "./UserPageIdentityHeaderCIC";

export default function UserPageIdentityHeader({
profile,
cicOverview,
}: {
readonly profile: ApiIdentity;
readonly cicOverview: ApiCicOverview | null;
}) {
return (
<div className="tw-px-6 tw-pt-6">
<div className="tw-mb-6">
<h2 className="tw-mb-1 tw-text-xl tw-font-semibold tw-text-iron-100">
Network Identity Check (NIC)
</h2>
<p className="tw-mb-0 tw-text-iron-500 tw-text-sm tw-font-normal tw-leading-relaxed">
Does the network believe this profile accurately represents its identity?
<p className="tw-mb-0 tw-text-sm tw-font-normal tw-leading-relaxed tw-text-iron-500">
Does the network believe this profile accurately represents its
identity?
</p>
</div>
<UserPageIdentityHeaderCIC profile={profile} />
<UserPageIdentityHeaderCIC profile={profile} cicOverview={cicOverview} />
</div>
);
}
Loading