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,13 +1,15 @@
import React, { createRef } from 'react';
import { render, act } from '@testing-library/react';
import NewMentionsPlugin, { MentionTypeaheadOption } from '@/components/drops/create/lexical/plugins/mentions/MentionsPlugin';
import React, { createRef } from "react";
import { render, act } from "@testing-library/react";
import NewMentionsPlugin, {
MentionTypeaheadOption,
} from "@/components/drops/create/lexical/plugins/mentions/MentionsPlugin";

jest.mock('@lexical/react/LexicalComposerContext', () => ({
jest.mock("@lexical/react/LexicalComposerContext", () => ({
useLexicalComposerContext: () => [{ update: (fn: any) => fn() }],
}));

let capturedProps: any;
jest.mock('@lexical/react/LexicalTypeaheadMenuPlugin', () => ({
jest.mock("@lexical/react/LexicalTypeaheadMenuPlugin", () => ({
LexicalTypeaheadMenuPlugin: (props: any) => {
capturedProps = props;
return <div data-testid="typeahead" />;
Expand All @@ -16,23 +18,36 @@ jest.mock('@lexical/react/LexicalTypeaheadMenuPlugin', () => ({
useBasicTypeaheadTriggerMatch: () => jest.fn(),
}));

jest.mock('@/hooks/useIdentitiesSearch', () => ({
jest.mock("@/hooks/useIdentitiesSearch", () => ({
IDENTITY_SEARCH_MIN_HANDLE_LENGTH: 3,
useIdentitiesSearch: jest.fn(),
}));

jest.mock('@/components/drops/create/lexical/nodes/MentionNode', () => ({
$createMentionNode: jest.fn(() => ({ replace: jest.fn(), select: jest.fn() })),
jest.mock("@/components/drops/create/lexical/nodes/MentionNode", () => ({
$createMentionNode: jest.fn(() => ({
replace: jest.fn(),
select: jest.fn(),
})),
}));
jest.mock("@/components/drops/create/lexical/nodes/GroupMentionNode", () => ({
$createGroupMentionNode: jest.fn(() => ({
replace: jest.fn(),
select: jest.fn(),
})),
}));

const { useIdentitiesSearch } = require('@/hooks/useIdentitiesSearch');
const { $createMentionNode } = require('@/components/drops/create/lexical/nodes/MentionNode');
const { useIdentitiesSearch } = require("@/hooks/useIdentitiesSearch");
const {
$createMentionNode,
} = require("@/components/drops/create/lexical/nodes/MentionNode");
const {
$createGroupMentionNode,
} = require("@/components/drops/create/lexical/nodes/GroupMentionNode");

describe('MentionsPlugin', () => {
it('builds options from identities and exposes open state', () => {
describe("MentionsPlugin", () => {
it("builds options from identities and exposes open state", () => {
(useIdentitiesSearch as jest.Mock).mockReturnValue({
identities: [
{ id: '1', handle: 'alice', display: 'Alice', pfp: null },
],
identities: [{ id: "1", handle: "alice", display: "Alice", pfp: null }],
});
const ref = createRef<any>();
render(<NewMentionsPlugin waveId="w1" onSelect={jest.fn()} ref={ref} />);
Expand All @@ -49,12 +64,14 @@ describe('MentionsPlugin', () => {
expect(ref.current.isMentionsOpen()).toBe(false);
});

it('calls onSelect with mention info', () => {
it("calls onSelect with mention info", () => {
(useIdentitiesSearch as jest.Mock).mockReturnValue({
identities: [{ id: '1', handle: 'alice', display: 'Alice', pfp: null }],
identities: [{ id: "1", handle: "alice", display: "Alice", pfp: null }],
});
const onSelect = jest.fn();
render(<NewMentionsPlugin waveId="w1" onSelect={onSelect} ref={createRef()} />);
render(
<NewMentionsPlugin waveId="w1" onSelect={onSelect} ref={createRef()} />
);
const option = capturedProps.options[0];
const close = jest.fn();
act(() => {
Expand All @@ -67,4 +84,46 @@ describe('MentionsPlugin', () => {
});
expect(close).toHaveBeenCalled();
});

it("adds @all option for admins and emits group mention", () => {
(useIdentitiesSearch as jest.Mock).mockReturnValue({
identities: [],
});
const onSelectGroupMention = jest.fn();
render(
<NewMentionsPlugin
waveId="w1"
onSelect={jest.fn()}
onSelectGroupMention={onSelectGroupMention}
canMentionAll={true}
ref={createRef()}
/>
);
expect(capturedProps.options).toHaveLength(0);

act(() => {
capturedProps.onQueryChange("a");
});
expect(capturedProps.options).toHaveLength(0);

act(() => {
capturedProps.onQueryChange("al");
});
expect(capturedProps.options).toHaveLength(0);

act(() => {
capturedProps.onQueryChange("all");
});
const option = capturedProps.options[0];
const close = jest.fn();

act(() => {
capturedProps.onSelectOption(option, null, close);
});

expect(option.handle).toBe("@all");
expect($createGroupMentionNode).toHaveBeenCalledWith("@all");
expect(onSelectGroupMention).toHaveBeenCalledWith("ALL");
expect(close).toHaveBeenCalled();
});
});
Original file line number Diff line number Diff line change
@@ -1,27 +1,34 @@
import { render, screen, fireEvent } from '@testing-library/react';
import React from 'react';
import CreateDropStormViewPart from '@/components/drops/create/utils/storm/CreateDropStormViewPart';
import { render, screen, fireEvent } from "@testing-library/react";
import React from "react";
import CreateDropStormViewPart from "@/components/drops/create/utils/storm/CreateDropStormViewPart";

jest.mock('@/components/drops/view/part/DropPart', () => jest.fn(() => <div data-testid="drop-part" />));
jest.mock('@/components/drops/create/utils/storm/CreateDropStormViewPartQuote', () => jest.fn(() => <div data-testid="quote" />));
jest.mock("@/components/drops/view/part/DropPart", () =>
jest.fn(() => <div data-testid="drop-part" />)
);
jest.mock(
"@/components/drops/create/utils/storm/CreateDropStormViewPartQuote",
() => jest.fn(() => <div data-testid="quote" />)
);

const DropPartMock = require('@/components/drops/view/part/DropPart');
const QuoteMock = require('@/components/drops/create/utils/storm/CreateDropStormViewPartQuote');
const DropPartMock = require("@/components/drops/view/part/DropPart");
const QuoteMock = require("@/components/drops/create/utils/storm/CreateDropStormViewPartQuote");

describe('CreateDropStormViewPart', () => {
describe("CreateDropStormViewPart", () => {
beforeEach(() => {
(global as any).URL.createObjectURL = jest.fn(() => 'blob:url');
(global as any).URL.createObjectURL = jest.fn(() => "blob:url");
jest.clearAllMocks();
});

const baseProps = {
profile: {} as any,
part: {
content: 'c',
content: "c",
quoted_drop: null,
media: [new File(['1'], 'f.png', { type: 'image/png' })],
media: [new File(["1"], "f.png", { type: "image/png" })],
},
mentionedUsers: [],
mentionedGroups: [],
mentionedWaves: [],
referencedNfts: [],
createdAt: 1,
wave: null,
Expand All @@ -30,21 +37,34 @@ describe('CreateDropStormViewPart', () => {
removePart: jest.fn(),
};

it('passes transformed media to DropPart', () => {
it("passes transformed media to DropPart", () => {
render(<CreateDropStormViewPart {...baseProps} />);
const call = (DropPartMock as jest.Mock).mock.calls[0][0];
expect(call.partMedias).toEqual([{ mimeType: 'image/png', mediaSrc: 'blob:url' }]);
expect(call.partMedias).toEqual([
{ mimeType: "image/png", mediaSrc: "blob:url" },
]);
});

it('renders quoted drop when provided', () => {
render(<CreateDropStormViewPart {...baseProps} part={{ ...baseProps.part, quoted_drop: { id: 'q' } }} />);
it("renders quoted drop when provided", () => {
render(
<CreateDropStormViewPart
{...baseProps}
part={{ ...baseProps.part, quoted_drop: { id: "q" } }}
/>
);
expect(QuoteMock).toHaveBeenCalled();
});

it('calls removePart on click', () => {
it("calls removePart on click", () => {
const removePart = jest.fn();
render(<CreateDropStormViewPart {...baseProps} removePart={removePart} partIndex={3} />);
fireEvent.click(screen.getByRole('button', { name: /remove part/i }));
render(
<CreateDropStormViewPart
{...baseProps}
removePart={removePart}
partIndex={3}
/>
);
fireEvent.click(screen.getByRole("button", { name: /remove part/i }));
expect(removePart).toHaveBeenCalledWith(3);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ jest.mock(
() => (props: any) => <div data-testid="mention">{props.user.handle}</div>
);

jest.mock(
"@/components/drops/view/item/content/DropListItemContentGroupMention",
() => () => <div data-testid="group-mention">@all</div>
);

jest.mock(
"@/components/drops/view/item/content/DropListItemContentWaveMention",
() => (props: any) => (
Expand Down Expand Up @@ -58,4 +63,17 @@ describe("DropListItemContentPart", () => {
);
expect(screen.getByTestId("wave-mention")).toHaveTextContent("Wave One");
});

it("renders group mention", () => {
render(
<DropListItemContentPart
part={{
type: DropContentPartType.GROUP_MENTION,
value: "ALL" as any,
match: "",
}}
/>
);
expect(screen.getByTestId("group-mention")).toHaveTextContent("@all");
});
});
31 changes: 31 additions & 0 deletions __tests__/components/drops/view/part/DropPartMarkdown.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ import { render, screen, waitFor } from "@testing-library/react";
import userEvent from "@testing-library/user-event";

import DropPartMarkdown from "@/components/drops/view/part/DropPartMarkdown";
import { ApiDropGroupMention } from "@/generated/models/ApiDropGroupMention";

const setQueryDataMock = jest.fn();

Expand Down Expand Up @@ -218,6 +219,36 @@ describe("DropPartMarkdown", () => {
expect(a).toHaveAttribute("rel", "noopener noreferrer nofollow");
});

it("renders @all as a blue group mention only when ALL is in mentioned groups", () => {
const { rerender } = render(
<DropPartMarkdown
mentionedUsers={[]}
mentionedGroups={[ApiDropGroupMention.All]}
mentionedWaves={[]}
referencedNfts={[]}
partContent={"hello @all"}
onQuoteClick={jest.fn()}
/>
);

expect(screen.getByText("@all")).toHaveClass("tw-text-primary-400");

rerender(
<DropPartMarkdown
mentionedUsers={[]}
mentionedGroups={[]}
mentionedWaves={[]}
referencedNfts={[]}
partContent={"hello @all"}
onQuoteClick={jest.fn()}
/>
);

expect(screen.getByText("hello @all")).not.toHaveClass(
"tw-text-primary-400"
);
Comment thread
simo6529 marked this conversation as resolved.
});

it("renders Art Blocks token card when feature enabled", async () => {
publicEnv.VITE_FEATURE_AB_CARD = "true";
const content = "[token](https://www.artblocks.io/token/662000)";
Expand Down
24 changes: 13 additions & 11 deletions __tests__/components/waves/CreateDropStormPart.test.tsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,33 @@
import React from 'react';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import React from "react";
import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";

jest.mock('@/components/drops/view/part/DropPartMarkdown', () => () => (
jest.mock("@/components/drops/view/part/DropPartMarkdown", () => () => (
<div data-testid="markdown" />
));

import CreateDropStormPart from '@/components/waves/CreateDropStormPart';
import CreateDropStormPart from "@/components/waves/CreateDropStormPart";

const part = { content: 'hello', media: [] } as any;
const part = { content: "hello", media: [] } as any;

describe('CreateDropStormPart', () => {
it('renders part info and handles remove', async () => {
describe("CreateDropStormPart", () => {
it("renders part info and handles remove", async () => {
const onRemove = jest.fn();
render(
<CreateDropStormPart
partIndex={0}
part={part}
mentionedUsers={[]}
mentionedGroups={[]}
mentionedWaves={[]}
referencedNfts={[]}
onRemovePart={onRemove}
/>
);

expect(screen.getByText('Part 1')).toBeInTheDocument();
await userEvent.click(screen.getByRole('button'));
expect(screen.getByText("Part 1")).toBeInTheDocument();
await userEvent.click(screen.getByRole("button"));
expect(onRemove).toHaveBeenCalledWith(0);
expect(screen.getByTestId('markdown')).toBeInTheDocument();
expect(screen.getByTestId("markdown")).toBeInTheDocument();
});
});
2 changes: 2 additions & 0 deletions __tests__/components/waves/CreateDropStormParts.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ describe("CreateDropStormParts", () => {
<CreateDropStormParts
parts={parts}
mentionedUsers={[]}
mentionedGroups={[]}
mentionedWaves={[]}
referencedNfts={[]}
onRemovePart={jest.fn()}
/>
Expand Down
Loading
Loading