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,29 +1,48 @@
import { render, act } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import React from 'react';
import MemesArtSubmissionContainer from '@/components/waves/memes/submission/MemesArtSubmissionContainer';
import { SubmissionStep } from '@/components/waves/memes/submission/types/Steps';
import { useArtworkSubmissionForm } from '@/components/waves/memes/submission/hooks/useArtworkSubmissionForm';
import { useArtworkSubmissionMutation } from '@/components/waves/memes/submission/hooks/useArtworkSubmissionMutation';
import { useSeizeConnectContext } from '@/components/auth/SeizeConnectContext';
import type { InteractiveMediaMimeType } from '@/components/waves/memes/submission/constants/media';
import { render, act } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import React from "react";
import MemesArtSubmissionContainer from "@/components/waves/memes/submission/MemesArtSubmissionContainer";
import { SubmissionStep } from "@/components/waves/memes/submission/types/Steps";
import { useArtworkSubmissionForm } from "@/components/waves/memes/submission/hooks/useArtworkSubmissionForm";
import { useArtworkSubmissionMutation } from "@/components/waves/memes/submission/hooks/useArtworkSubmissionMutation";
import { useSeizeConnectContext } from "@/components/auth/SeizeConnectContext";
import type { InteractiveMediaMimeType } from "@/components/waves/memes/submission/constants/media";

jest.mock('@/components/waves/memes/submission/hooks/useArtworkSubmissionForm');
jest.mock('@/components/waves/memes/submission/hooks/useArtworkSubmissionMutation');
jest.mock('@/components/auth/SeizeConnectContext');
jest.mock('@/components/waves/memes/submission/layout/ModalLayout', () => ({ children }: any) => <div>{children}</div>);
jest.mock('@/components/waves/memes/submission/steps/AgreementStep', () => (props: any) => <div data-testid="agreement" {...props} />);
jest.mock("@/components/waves/memes/submission/hooks/useArtworkSubmissionForm");
jest.mock(
"@/components/waves/memes/submission/hooks/useArtworkSubmissionMutation"
);
jest.mock("@/components/auth/SeizeConnectContext");
jest.mock(
"@/components/waves/memes/submission/layout/ModalLayout",
() =>
({ children }: any) => <div>{children}</div>
);
jest.mock(
"@/components/waves/memes/submission/steps/AgreementStep",
() => (props: any) => <div data-testid="agreement" {...props} />
);
let artworkProps: any;
jest.mock('@/components/waves/memes/submission/steps/ArtworkStep', () => (props: any) => {
artworkProps = props; return <div data-testid="artwork" />;
});
jest.mock(
"@/components/waves/memes/submission/steps/ArtworkStep",
() => (props: any) => {
artworkProps = props;
return <div data-testid="artwork" />;
}
);

const mockForm = useArtworkSubmissionForm as jest.MockedFunction<typeof useArtworkSubmissionForm>;
const mockMutation = useArtworkSubmissionMutation as jest.MockedFunction<typeof useArtworkSubmissionMutation>;
const mockSeizeConnect = useSeizeConnectContext as jest.MockedFunction<typeof useSeizeConnectContext>;
const mockForm = useArtworkSubmissionForm as jest.MockedFunction<
typeof useArtworkSubmissionForm
>;
const mockMutation = useArtworkSubmissionMutation as jest.MockedFunction<
typeof useArtworkSubmissionMutation
>;
const mockSeizeConnect = useSeizeConnectContext as jest.MockedFunction<
typeof useSeizeConnectContext
>;

describe('MemesArtSubmissionContainer', () => {
const wave = { id: 'w1', participation: { terms: 't' } } as any;
describe("MemesArtSubmissionContainer", () => {
const wave = { id: "w1", participation: { terms: "t" } } as any;
const onClose = jest.fn();

beforeEach(() => {
Expand All @@ -34,20 +53,20 @@ describe('MemesArtSubmissionContainer', () => {
setAgreements: jest.fn(),
handleContinueFromTerms: jest.fn(),
handleContinueFromArtwork: jest.fn(async () => true),
traits: { title: 't', description: 'd' },
traits: { title: "t", description: "d" },
setTraits: jest.fn(),
updateTraitField: jest.fn(),
artworkUploaded: false,
artworkUrl: '',
artworkUrl: "",
selectedFile: null,
mediaSource: 'upload',
externalMediaUrl: '',
externalMediaPreviewUrl: '',
externalMediaHashInput: '',
externalMediaProvider: 'ipfs',
externalMediaMimeType: 'text/html',
mediaSource: "upload",
externalMediaUrl: "",
externalMediaPreviewUrl: "",
externalMediaHashInput: "",
externalMediaProvider: "ipfs",
externalMediaMimeType: "text/html",
externalMediaError: null,
externalMediaValidationStatus: 'idle',
externalMediaValidationStatus: "idle",
isExternalMediaValid: false,
operationalData: {
airdrop_config: [{ id: "test-initial", address: "", count: 20 }],
Expand All @@ -61,6 +80,7 @@ describe('MemesArtSubmissionContainer', () => {
artist_profile_media: [],
artwork_commentary_media: [],
preview_image: "",
promo_video: "",
},
commentary: "",
about_artist: "",
Expand All @@ -84,37 +104,39 @@ describe('MemesArtSubmissionContainer', () => {
formState.handleFileSelect = jest.fn((file: File) => {
formState.selectedFile = file;
formState.artworkUploaded = true;
formState.artworkUrl = 'object-url';
formState.artworkUrl = "object-url";
});

formState.setMediaSource = jest.fn((mode: 'upload' | 'url') => {
formState.setMediaSource = jest.fn((mode: "upload" | "url") => {
formState.mediaSource = mode;
});

formState.setExternalMediaHash = jest.fn((hash: string) => {
formState.externalMediaHashInput = hash;
if (hash) {
formState.externalMediaUrl = `${formState.externalMediaProvider === 'arweave' ? 'https://arweave.net/' : 'ipfs://'}${hash}`;
formState.externalMediaUrl = `${formState.externalMediaProvider === "arweave" ? "https://arweave.net/" : "ipfs://"}${hash}`;
formState.externalMediaPreviewUrl =
formState.externalMediaProvider === 'arweave'
formState.externalMediaProvider === "arweave"
? `https://arweave.net/${hash}`
: `https://ipfs.io/ipfs/${hash}`;
formState.isExternalMediaValid = true;
formState.externalMediaValidationStatus = 'valid';
formState.externalMediaValidationStatus = "valid";
formState.externalMediaError = null;
} else {
formState.externalMediaUrl = '';
formState.externalMediaPreviewUrl = '';
formState.externalMediaUrl = "";
formState.externalMediaPreviewUrl = "";
formState.isExternalMediaValid = false;
formState.externalMediaValidationStatus = 'idle';
formState.externalMediaValidationStatus = "idle";
formState.externalMediaError = null;
}
});

formState.setExternalMediaProvider = jest.fn((provider: 'ipfs' | 'arweave') => {
formState.externalMediaProvider = provider;
formState.setExternalMediaHash(formState.externalMediaHashInput);
});
formState.setExternalMediaProvider = jest.fn(
(provider: "ipfs" | "arweave") => {
formState.externalMediaProvider = provider;
formState.setExternalMediaHash(formState.externalMediaHashInput);
}
);

formState.setExternalMediaMimeType = jest.fn(
(mimeType: InteractiveMediaMimeType) => {
Expand All @@ -123,15 +145,15 @@ describe('MemesArtSubmissionContainer', () => {
);

formState.clearExternalMedia = jest.fn(() => {
formState.externalMediaHashInput = '';
formState.externalMediaUrl = '';
formState.externalMediaPreviewUrl = '';
formState.externalMediaHashInput = "";
formState.externalMediaUrl = "";
formState.externalMediaPreviewUrl = "";
formState.isExternalMediaValid = false;
formState.externalMediaValidationStatus = 'idle';
formState.externalMediaValidationStatus = "idle";
formState.externalMediaError = null;
});

formState.getSubmissionData = () => ({ traits: { title: 't' } });
formState.getSubmissionData = () => ({ traits: { title: "t" } });
formState.getMediaSelection = jest.fn(() => ({
mediaSource: formState.mediaSource,
selectedFile: formState.selectedFile,
Expand All @@ -145,17 +167,17 @@ describe('MemesArtSubmissionContainer', () => {

mockForm.mockReturnValue(formState);
mockMutation.mockReturnValue({
submitArtwork: jest.fn(async () => 'ok'),
submitArtwork: jest.fn(async () => "ok"),
uploadProgress: 0,
submissionPhase: 'idle',
submissionPhase: "idle",
submissionError: undefined,
isSubmitting: false,
} as any);
mockSeizeConnect.mockReturnValue({
address: '0x123',
address: "0x123",
isSafeWallet: false,
walletName: 'MetaMask',
walletIcon: 'metamask-icon.svg',
walletName: "MetaMask",
walletIcon: "metamask-icon.svg",
seizeConnect: jest.fn(),
seizeDisconnect: jest.fn(),
seizeDisconnectAndLogout: jest.fn(),
Expand All @@ -166,12 +188,12 @@ describe('MemesArtSubmissionContainer', () => {
} as any);
});

it('auto closes on success', () => {
it("auto closes on success", () => {
jest.useFakeTimers();
mockMutation.mockReturnValueOnce({
submitArtwork: jest.fn(),
uploadProgress: 0,
submissionPhase: 'success',
submissionPhase: "success",
submissionError: undefined,
isSubmitting: false,
} as any);
Expand All @@ -180,18 +202,18 @@ describe('MemesArtSubmissionContainer', () => {
expect(onClose).toHaveBeenCalled();
});

it('submits artwork when file selected', async () => {
it("submits artwork when file selected", async () => {
const user = userEvent.setup();
const submitArtwork = jest.fn(async () => 'result');
const submitArtwork = jest.fn(async () => "result");
mockMutation.mockReturnValueOnce({
submitArtwork,
uploadProgress: 0,
submissionPhase: 'idle',
submissionPhase: "idle",
submissionError: undefined,
isSubmitting: false,
} as any);
render(<MemesArtSubmissionContainer onClose={onClose} wave={wave} />);
const file = new File(['a'], 'a.png', { type: 'image/png' });
const file = new File(["a"], "a.png", { type: "image/png" });
await act(async () => {
artworkProps.handleFileSelect(file);
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import AdditionalMediaUpload from "@/components/waves/memes/submission/components/AdditionalMediaUpload";
import type { MetadataValueLengthStatus } from "@/components/waves/memes/submission/utils/submissionMetadata";

describe("AdditionalMediaUpload", () => {
const defaultProps = {
Expand Down Expand Up @@ -28,28 +29,52 @@ describe("AdditionalMediaUpload", () => {
});

it("shows preview section when video submission", () => {
render(<AdditionalMediaUpload {...defaultProps} requiresPreviewImage previewRequiredMediaType="Video" />);
render(
<AdditionalMediaUpload
{...defaultProps}
requiresPreviewImage
previewRequiredMediaType="Video"
/>
);
expect(screen.getByText(/Preview \*/i)).toBeInTheDocument();
expect(
screen.getByText(/Video submissions require a preview image/i)
).toBeInTheDocument();
});

it("does not show preview section for regular submissions", () => {
render(<AdditionalMediaUpload {...defaultProps} requiresPreviewImage={false} />);
render(
<AdditionalMediaUpload {...defaultProps} requiresPreviewImage={false} />
);
expect(screen.queryByText(/Preview \*/i)).not.toBeInTheDocument();
});

it("shows promo video section for HTML submissions", () => {
render(<AdditionalMediaUpload {...defaultProps} requiresPreviewImage requiresPromoVideoOption previewRequiredMediaType="HTML" />);
render(
<AdditionalMediaUpload
{...defaultProps}
requiresPreviewImage
requiresPromoVideoOption
previewRequiredMediaType="HTML"
/>
);
expect(screen.getByText("Promo Video")).toBeInTheDocument();
expect(
screen.getByText(/For HTML submissions, we recommend providing a promo video/i)
screen.getByText(
/For HTML submissions, we recommend providing a promo video/i
)
).toBeInTheDocument();
});

it("does not show promo video section for video submissions", () => {
render(<AdditionalMediaUpload {...defaultProps} requiresPreviewImage requiresPromoVideoOption={false} previewRequiredMediaType="Video" />);
render(
<AdditionalMediaUpload
{...defaultProps}
requiresPreviewImage
requiresPromoVideoOption={false}
previewRequiredMediaType="Video"
/>
);
expect(screen.queryByText("Promo Video")).not.toBeInTheDocument();
});

Expand All @@ -70,4 +95,25 @@ describe("AdditionalMediaUpload", () => {

expect(onArtworkCommentaryChange).toHaveBeenCalled();
});

it("shows metadata warning hint for about artist", () => {
const warningStatus: MetadataValueLengthStatus = {
dataKey: "about_artist",
length: 4700,
maxLength: 5000,
warningThreshold: 4500,
remaining: 300,
isWarning: true,
isError: false,
};

render(
<AdditionalMediaUpload
{...defaultProps}
aboutArtistLengthStatus={warningStatus}
/>
);

expect(screen.getByText("4700/5000 characters.")).toBeInTheDocument();
});
});
Loading