Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dev to Main Sync #139

Merged
merged 5 commits into from
Aug 29, 2024
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
32 changes: 0 additions & 32 deletions __tests__/components/App/InputSection.test.tsx

This file was deleted.

141 changes: 116 additions & 25 deletions __tests__/components/App/OutputSection.test.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import '@testing-library/jest-dom/extend-expect';

import { fireEvent, render, screen } from '@testing-library/react';

import OutputSection from '@/components/App/OutputSection';
Expand All @@ -6,21 +8,65 @@ describe('OutputSection component', () => {
const shortUrl = 'https://rds.li/123456';
const originalUrl = 'https://status.realdevsquad.com/task/details/josuets45sds';

const mockHandleCopyUrl = jest.fn();
const mockHandleCreateNew = jest.fn();

beforeAll(() => {
Object.assign(navigator, {
clipboard: {
writeText: jest.fn().mockResolvedValue(() => Promise.resolve()),
},
});
});

beforeEach(() => {
HTMLCanvasElement.prototype.getContext = jest.fn().mockReturnValue({
fillRect: jest.fn(),
clearRect: jest.fn(),
getImageData: jest.fn(),
putImageData: jest.fn(),
createImageData: jest.fn(),
setTransform: jest.fn(),
drawImage: jest.fn(),
save: jest.fn(),
fillText: jest.fn(),
restore: jest.fn(),
beginPath: jest.fn(),
moveTo: jest.fn(),
lineTo: jest.fn(),
closePath: jest.fn(),
stroke: jest.fn(),
translate: jest.fn(),
scale: jest.fn(),
rotate: jest.fn(),
arc: jest.fn(),
fill: jest.fn(),
measureText: jest.fn().mockReturnValue({ width: 0 }),
transform: jest.fn(),
rect: jest.fn(),
clip: jest.fn(),
isPointInPath: jest.fn(),
isPointInStroke: jest.fn(),
canvas: document.createElement('canvas'),
});

HTMLCanvasElement.prototype.toDataURL = jest.fn().mockReturnValue('data:image/png;base64,mocked');

jest.clearAllMocks();
});

it('renders OutputSection component correctly', () => {
render(
<OutputSection
shortUrl={shortUrl}
originalUrl={originalUrl}
isLoaded={true}
handleCopyUrl={mockHandleCopyUrl}
handleCreateNew={mockHandleCreateNew}
/>
);

expect(screen.getByTestId('copy-button')).toBeInTheDocument();
expect(screen.getByTestId('share-button')).toBeInTheDocument();
expect(screen.getByTestId('output-heading')).toHaveTextContent('Your shortened URL is ready!');
});

it('calls handleCopyUrl function on button click', () => {
Expand All @@ -29,14 +75,14 @@ describe('OutputSection component', () => {
shortUrl={shortUrl}
originalUrl={originalUrl}
isLoaded={true}
handleCopyUrl={mockHandleCopyUrl}
handleCreateNew={mockHandleCopyUrl}
handleCreateNew={mockHandleCreateNew}
/>
);

const copyButton = screen.getByTestId('copy-button');
fireEvent.click(copyButton);
expect(mockHandleCopyUrl).toHaveBeenCalled();

expect(navigator.clipboard.writeText).toHaveBeenCalledWith(shortUrl);
});

it('opens a new tab when share button is clicked', () => {
Expand All @@ -45,8 +91,7 @@ describe('OutputSection component', () => {
shortUrl={shortUrl}
originalUrl={originalUrl}
isLoaded={true}
handleCopyUrl={mockHandleCopyUrl}
handleCreateNew={mockHandleCopyUrl}
handleCreateNew={mockHandleCreateNew}
/>
);

Expand All @@ -55,52 +100,98 @@ describe('OutputSection component', () => {
expect(shareButton).toHaveAttribute('target', '_blank');
});

it('renders create new button when window width is less than 768px', () => {
it('renders social media share links', () => {
render(
<OutputSection
shortUrl={shortUrl}
originalUrl={originalUrl}
isLoaded={true}
handleCopyUrl={mockHandleCopyUrl}
handleCreateNew={mockHandleCreateNew}
/>
);

Object.defineProperty(window, 'innerWidth', { writable: true, configurable: true, value: 500 });
fireEvent(window, new Event('resize'));

const createNewButton = screen.getByText('Create New');
expect(createNewButton).toBeInTheDocument();
expect(screen.getByTestId('twitter-share')).toBeInTheDocument();
expect(screen.getByTestId('discord-share')).toBeInTheDocument();
expect(screen.getByTestId('linkedin-share')).toBeInTheDocument();
expect(screen.getByTestId('whatsapp-share')).toBeInTheDocument();
});
it('renders "Create New" button and calls the onClick handler when clicked', () => {

it('renders shimmer when isLoaded is false', () => {
render(
<OutputSection
originalUrl={originalUrl}
shortUrl={shortUrl}
isLoaded={false}
handleCreateNew={mockHandleCreateNew}
/>
);

const shimmer = screen.getByTestId('output-section-shimmer');
expect(shimmer).toBeInTheDocument();
});

it('updates the button text on download click', async () => {
render(
<OutputSection
shortUrl="https://example.com/short-url"
originalUrl="https://example.com/original-url"
isLoaded={true}
handleCopyUrl={mockHandleCopyUrl}
handleCreateNew={mockHandleCreateNew}
/>
);
const downloadButton = screen.getByTestId('download-button');
fireEvent.click(downloadButton);

const createNewButton = screen.getByText('Create New');
expect(createNewButton).toBeInTheDocument();
fireEvent.click(createNewButton);
expect(mockHandleCreateNew).toHaveBeenCalled();
const updatedText = await screen.findByText('Downloaded');
expect(updatedText).toBeInTheDocument();
});

it('renders shimmer when isLoaded is false', () => {
it('triggers the download process correctly', () => {
render(
<OutputSection
shortUrl={shortUrl}
originalUrl={originalUrl}
isLoaded={true}
handleCreateNew={mockHandleCreateNew}
/>
);

const downloadButton = screen.getByTestId('download-button');
fireEvent.click(downloadButton);
expect(HTMLCanvasElement.prototype.toDataURL).toHaveBeenCalled();
});

it('does nothing when canvas is not found during download', () => {
document.getElementById = jest.fn().mockReturnValue(null);

render(
<OutputSection
shortUrl={shortUrl}
isLoaded={false}
handleCopyUrl={mockHandleCopyUrl}
originalUrl={originalUrl}
isLoaded={true}
handleCreateNew={mockHandleCreateNew}
/>
);

const shimmer = screen.getByTestId('output-section-shimmer');
expect(shimmer).toBeInTheDocument();
const downloadButton = screen.getByTestId('download-button');
fireEvent.click(downloadButton);

expect(HTMLCanvasElement.prototype.toDataURL).not.toHaveBeenCalled();
});

it('does nothing when shortUrl is empty during copy', () => {
render(
<OutputSection
shortUrl=""
originalUrl={originalUrl}
isLoaded={true}
handleCreateNew={mockHandleCreateNew}
/>
);

const copyButton = screen.getByTestId('copy-button');
fireEvent.click(copyButton);

expect(navigator.clipboard.writeText).not.toHaveBeenCalled();
});
});
134 changes: 134 additions & 0 deletions __tests__/components/App/SortenUrlForm.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
import { fireEvent, render, screen } from '@testing-library/react';

import ShortenUrlForm, { HomeText } from '@/components/App/ShortenUrlForm';

describe('UrlForm component', () => {
const testUrl = 'https://stackoverflow.com/questions/26944762/when-to-use-chore-as-type-of-commit-message';

it('renders UrlForm component correctly', () => {
const mockSetUrl = jest.fn();
const mockOnSubmit = jest.fn();
const mockClearError = jest.fn();
render(
<ShortenUrlForm
url={testUrl}
setUrl={mockSetUrl}
onSubmit={mockOnSubmit}
error={null}
clearError={mockClearError}
loading={false}
/>
);
expect(screen.getByPlaceholderText('Enter the URL')).toBeInTheDocument();
expect(screen.getByTestId('shorten-button')).toBeInTheDocument();
});

it('calls setUrl function on input change and clearError', () => {
const mockSetUrl = jest.fn();
const mockOnSubmit = jest.fn();
const mockClearError = jest.fn();
render(
<ShortenUrlForm
url={testUrl}
setUrl={mockSetUrl}
onSubmit={mockOnSubmit}
error={null}
clearError={mockClearError}
loading={false}
/>
);
const inputElement = screen.getByPlaceholderText('Enter the URL');
fireEvent.change(inputElement, { target: { value: 'https://realdevsquad.com' } });
expect(mockSetUrl).toHaveBeenCalledWith('https://realdevsquad.com');
expect(mockClearError).toHaveBeenCalled();
});

it('calls onSubmit function on button click', () => {
const mockSetUrl = jest.fn();
const mockOnSubmit = jest.fn();
const mockClearError = jest.fn();
render(
<ShortenUrlForm
url={testUrl}
setUrl={mockSetUrl}
onSubmit={mockOnSubmit}
error={null}
clearError={mockClearError}
loading={false}
/>
);
const generateButton = screen.getByTestId('shorten-button');
fireEvent.click(generateButton);
expect(mockOnSubmit).toHaveBeenCalledWith(testUrl);
});

it('does not call onSubmit function if URL is empty', () => {
const mockSetUrl = jest.fn();
const mockOnSubmit = jest.fn();
const mockClearError = jest.fn();

render(
<ShortenUrlForm
url=""
setUrl={mockSetUrl}
onSubmit={mockOnSubmit}
error={null}
clearError={mockClearError}
loading={false}
/>
);

const generateButton = screen.getByTestId('shorten-button');
fireEvent.click(generateButton);

expect(mockOnSubmit).not.toHaveBeenCalled();
});

it('renders error message if error prop is passed', () => {
const errorMessage = 'Enter a valid URL';
render(
<ShortenUrlForm
url={testUrl}
setUrl={jest.fn()}
onSubmit={jest.fn()}
error={errorMessage}
clearError={jest.fn()}
loading={false}
/>
);
const errorElement = screen.getByText(errorMessage);
expect(errorElement).toBeInTheDocument();
expect(errorElement).toHaveTextContent(errorMessage);
});

it('renders the main heading correctly', () => {
render(<HomeText />);
const mainHeading = screen.getByText('Shorten Your URL');
expect(mainHeading).toBeInTheDocument();
expect(mainHeading).toHaveClass(
'text-3xl md:text-6xl xl:text-7xl sm:text-5xl text-center text-white font-semibold pb-2 lg:pb-4'
);
});

it('renders the subheading correctly', () => {
render(<HomeText />);
const subHeading = screen.getByText('Perfect Links Every Time');
expect(subHeading).toBeInTheDocument();
expect(subHeading).toHaveClass(
'text-2xl sm:text-3xl md:text-4xl xl:text-5xl text-center text-white font-semibold'
);
});

it('renders the paragraph text correctly', () => {
render(<HomeText />);
const paragraph = screen.getByText(/Ready to shorten your URL\? Enter your/i);
expect(paragraph).toBeInTheDocument();
expect(paragraph).toHaveClass('xl:text-xl text-base text-white mt-4 text-center');
});

it('renders the paragraph text with a line break for small screens', () => {
render(<HomeText />);
const paragraph = screen.getByText(/Ready to shorten your URL\? Enter your/i);
expect(paragraph.innerHTML).toContain('<br class="sm:hidden">');
});
});
Loading
Loading