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
63 changes: 47 additions & 16 deletions __tests__/components/waves/WavePicture.test.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,58 @@
import React from 'react';
import { render, screen } from '@testing-library/react';
import WavePicture from '@/components/waves/WavePicture';
import React from "react";
import { render, screen } from "@testing-library/react";
import { AuthContext } from "@/components/auth/Auth";
import WavePicture from "@/components/waves/WavePicture";

describe('WavePicture', () => {
it('renders picture image when provided', () => {
describe("WavePicture", () => {
it("renders picture image when provided", () => {
render(<WavePicture name="wave" picture="pic.jpg" contributors={[]} />);
const img = screen.getByRole('img', { name: 'wave' });
expect(img.getAttribute('src')).toContain('pic.jpg');
expect(img).toHaveAttribute('alt', 'wave');
const img = screen.getByRole("img", { name: "wave" });
expect(img.getAttribute("src")).toContain("pic.jpg");
expect(img).toHaveAttribute("alt", "wave");
});

it('renders gradient when no picture and no contributors', () => {
const { container } = render(<WavePicture name="wave" picture={null} contributors={[]} />);
it("renders gradient when no picture and no contributors", () => {
const { container } = render(
<WavePicture name="wave" picture={null} contributors={[]} />
);
expect(container.firstChild).toBeInTheDocument();
});

it('renders contributor images sliced', () => {
it("renders contributor images sliced", () => {
const contributors = [{ pfp: "a.png" }, { pfp: "b.png" }, { pfp: "c.png" }];
render(
<WavePicture name="wave" picture={null} contributors={contributors} />
);
expect(screen.getAllByRole("img").length).toBe(3);
});

it("excludes authenticated user contributor from collage when identity matches", () => {
const contributors = [
{ pfp: 'a.png' },
{ pfp: 'b.png' },
{ pfp: 'c.png' },
{ pfp: "mine.png", identity: "id-0xabc" },
{ pfp: "a.png", identity: "alice" },
{ pfp: "b.png", identity: "bob" },
];
render(<WavePicture name="wave" picture={null} contributors={contributors} />);
expect(screen.getAllByRole('img').length).toBe(3);

render(
<AuthContext.Provider
value={
{
connectedProfile: {
id: "user-id",
handle: "me",
normalised_handle: "me",
primary_wallet: "0xabc",
query: "id-0xabc",
wallets: [{ wallet: "0xabc" }],
},
activeProfileProxy: null,
} as any
}
>
<WavePicture name="wave" picture={null} contributors={contributors} />
</AuthContext.Provider>
);

expect(screen.getAllByRole("img")).toHaveLength(2);
});
});
92 changes: 66 additions & 26 deletions __tests__/components/waves/header/WaveHeader.test.tsx
Original file line number Diff line number Diff line change
@@ -1,44 +1,84 @@
import { render } from '@testing-library/react';
import React from 'react';
import WaveHeader, { WaveHeaderPinnedSide } from '@/components/waves/header/WaveHeader';
import { ApiWaveType } from '@/generated/models/ApiWaveType';
import { AuthContext } from '@/components/auth/Auth';

jest.mock('@/components/waves/header/WaveHeaderFollow', () => () => <div />);
jest.mock('@/components/waves/header/options/WaveHeaderOptions', () => () => <div />);
jest.mock('@/components/waves/header/name/WaveHeaderName', () => () => <div data-testid="name" />);
jest.mock('@/components/waves/header/WaveHeaderFollowers', () => () => <div />);
jest.mock('@/components/waves/header/WaveHeaderDescription', () => () => <div data-testid="description" />);
jest.mock('@/components/waves/WavePicture', () => () => <div />);
jest.mock('@/components/waves/specs/WaveNotificationSettings', () => () => <div />);
import { render, screen } from "@testing-library/react";
import React from "react";
import WaveHeader, {
WaveHeaderPinnedSide,
} from "@/components/waves/header/WaveHeader";
import { ApiWaveType } from "@/generated/models/ApiWaveType";
import { AuthContext } from "@/components/auth/Auth";

jest.mock("@/components/waves/header/WaveHeaderFollow", () => () => <div />);
jest.mock("@/components/waves/header/options/WaveHeaderOptions", () => () => (
<div />
));
jest.mock("@/components/waves/header/name/WaveHeaderName", () => () => (
<div data-testid="name" />
));
jest.mock("@/components/waves/header/WaveHeaderFollowers", () => () => <div />);
jest.mock("@/components/waves/header/WaveHeaderDescription", () => () => (
<div data-testid="description" />
));
jest.mock("@/components/waves/WavePicture", () => () => <div />);
jest.mock("@/components/waves/specs/WaveNotificationSettings", () => () => (
<div />
));
jest.mock("@/helpers/waves/waves.helpers", () => ({ canEditWave: jest.fn() }));

const { canEditWave } = require("@/helpers/waves/waves.helpers");

const baseWave: any = {
id: 'w',
name: 'Wave',
id: "w",
name: "Wave",
created_at: 0,
picture: 'p',
author: { handle: 'a', banner1_color: '#000', banner2_color: '#111' },
picture: "p",
author: { handle: "a", banner1_color: "#000", banner2_color: "#111" },
contributors_overview: [],
metrics: { drops_count: 1 },
chat: { scope: { group: { is_direct_message: false } } },
wave: { type: ApiWaveType.Chat },
};

describe('WaveHeader', () => {
const wrapper = (wave:any, props?:any) =>
describe("WaveHeader", () => {
beforeEach(() => {
(canEditWave as jest.Mock).mockReset();
(canEditWave as jest.Mock).mockReturnValue(false);
});

const wrapper = (wave: any, props?: any) =>
render(
<AuthContext.Provider value={{ connectedProfile: null, activeProfileProxy: null } as any}>
<AuthContext.Provider
value={{ connectedProfile: null, activeProfileProxy: null } as any}
>
<WaveHeader wave={wave} onFollowersClick={jest.fn()} {...props} />
</AuthContext.Provider>
);

it('shows drop icon when wave not chat', () => {
it("shows drop icon when wave not chat", () => {
wrapper({ ...baseWave, wave: { type: ApiWaveType.Approve } });
expect(document.querySelector('svg')).toBeInTheDocument();
expect(document.querySelector("svg")).toBeInTheDocument();
});

it("omits drop icon for chat waves and applies ring classes", () => {
const { container } = wrapper(baseWave, {
useRing: false,
useRounded: false,
pinnedSide: WaveHeaderPinnedSide.RIGHT,
});
expect(document.querySelector("svg")).toBeNull();
expect(container.firstChild?.firstChild).not.toHaveClass("tw-ring-1");
});

it("shows picture edit action for editable non-DM waves", () => {
(canEditWave as jest.Mock).mockReturnValue(true);
wrapper(baseWave);
expect(screen.getByLabelText("Edit wave picture")).toBeInTheDocument();
});

it('omits drop icon for chat waves and applies ring classes', () => {
const { container } = wrapper(baseWave, { useRing: false, useRounded: false, pinnedSide: WaveHeaderPinnedSide.RIGHT });
expect(document.querySelector('svg')).toBeNull();
expect(container.firstChild?.firstChild).not.toHaveClass('tw-ring-1');
it("hides picture edit action for DM waves even when editable", () => {
(canEditWave as jest.Mock).mockReturnValue(true);
wrapper({
...baseWave,
chat: { scope: { group: { is_direct_message: true } } },
});
expect(screen.queryByLabelText("Edit wave picture")).toBeNull();
});
});
13 changes: 13 additions & 0 deletions __tests__/components/waves/header/name/WaveHeaderName.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,17 @@ describe("WaveHeaderName", () => {
render(<WaveHeaderName wave={wave} />);
expect(screen.queryByTestId("edit")).toBeNull();
});

it("hides edit button for DM waves even when user can edit", () => {
(canEditWave as jest.Mock).mockReturnValue(true);
render(
<WaveHeaderName
wave={{
...wave,
chat: { scope: { group: { is_direct_message: true } } },
}}
/>
);
expect(screen.queryByTestId("edit")).toBeNull();
});
});
1 change: 1 addition & 0 deletions components/brain/content/BrainContentPinnedWave.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ const BrainContentPinnedWave: React.FC<BrainContentPinnedWaveProps> = ({
picture={wave.picture}
contributors={wave.contributors_overview.map((c) => ({
pfp: c.contributor_pfp,
identity: c.contributor_identity,
}))}
/>
) : (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ const MyStreamWaveTabsDefault: React.FC<MyStreamWaveTabsDefaultProps> = ({
picture={wave.picture}
contributors={wave.contributors_overview.map((c) => ({
pfp: c.contributor_pfp,
identity: c.contributor_identity,
}))}
/>
</div>
Expand Down
1 change: 1 addition & 0 deletions components/brain/my-stream/tabs/MyStreamWaveTabsMeme.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ const MyStreamWaveTabsMeme: React.FC<MyStreamWaveTabsMemeProps> = ({
picture={wave.picture}
contributors={wave.contributors_overview.map((c) => ({
pfp: c.contributor_pfp,
identity: c.contributor_identity,
}))}
/>
</div>
Expand Down
5 changes: 3 additions & 2 deletions components/header/AppHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,8 @@ export default function AppHeader() {
const hasUnreadOnOtherConnectedProfiles = connectedAccounts.some(
(account) =>
!account.isActive &&
(connectedAccountUnreadNotifications[account.address.toLowerCase()] ?? 0) >
0
(connectedAccountUnreadNotifications[account.address.toLowerCase()] ??
0) > 0
);

const pathSegments = pathname.split("/").filter(Boolean);
Expand Down Expand Up @@ -310,6 +310,7 @@ export default function AppHeader() {
picture={activeWave.picture ?? null}
contributors={activeWave.contributors_overview.map((c) => ({
pfp: c.contributor_pfp,
identity: c.contributor_identity,
}))}
/>
</div>
Expand Down
Loading