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

PADV-1658 test: Shared Components Test Suite #20

Merged
merged 1 commit into from
Sep 12, 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
37 changes: 37 additions & 0 deletions src/shared/AlertMessage/tests/index.test.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import React from 'react';
import { render, screen } from '@testing-library/react';
import '@testing-library/jest-dom';
import AlertMessage from '../index';

describe('AlertMessage Component', () => {
it('renders with default props', () => {
render(<AlertMessage heading="Test Heading" />);

expect(screen.getByText('Test Heading')).toBeInTheDocument();

const alert = screen.getByRole('alert');
expect(alert).toHaveClass('alert-danger');
});

it('renders with a custom variant, heading, and message', () => {
render(
<AlertMessage variant="warning" heading="Custom Heading" message="Custom message" />,
);

expect(screen.getByText('Custom Heading')).toBeInTheDocument();
expect(screen.getByText('Custom message')).toBeInTheDocument();

const alert = screen.getByRole('alert');
expect(alert).toHaveClass('alert-warning');
});

it('renders children correctly', () => {
render(
<AlertMessage heading="Test Heading">
<button type="button">Click me</button>
</AlertMessage>,
);

expect(screen.getByRole('button', { name: 'Click me' })).toBeInTheDocument();
});
});
2 changes: 1 addition & 1 deletion src/shared/DashboardLaunchButton/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { Button } from 'react-paragon-topaz';

import AlertMessage from 'shared/AlertMessage';
import { skillableUrl, defaultErrorMessage } from 'constants';
import { eventManager } from 'helpers';
import { eventManager } from '../../helpers';
01001110J marked this conversation as resolved.
Show resolved Hide resolved

import './index.scss';

Expand Down
89 changes: 89 additions & 0 deletions src/shared/DashboardLaunchButton/tests/index.test.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import React from 'react';
import {
render,
screen,
fireEvent,
waitFor,
} from '@testing-library/react';
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
import DashboardLaunchButton from '../index';
import '@testing-library/jest-dom';

jest.mock('@edx/frontend-platform/auth', () => ({
getAuthenticatedHttpClient: jest.fn(),
}));
jest.mock('@edx/frontend-platform/logging', () => ({
logError: jest.fn(),
}));
jest.mock('shared/AlertMessage', () => () => <div>Mocked AlertMessage</div>);

const mockPost = jest.fn();
const mockCourseId = 'course-v1:edX+DemoX+Demo_Course';

describe('DashboardLaunchButton Component', () => {
beforeEach(() => {
getAuthenticatedHttpClient.mockReturnValue({ post: mockPost });
jest.clearAllMocks();
});

it('renders the component correctly with the given title', () => {
render(<DashboardLaunchButton courseId={mockCourseId} title="Test Title" />);
expect(screen.getByText('Test Title')).toBeInTheDocument();
});

it('does not show the button initially if is_ccx_course is false', async () => {
mockPost.mockResolvedValueOnce({ data: { is_ccx_course: false } });

render(<DashboardLaunchButton courseId={mockCourseId} title="Test Title" />);

await waitFor(() => {
expect(screen.queryByRole('button', { name: /Go To Instructor Dashboard/i })).not.toBeInTheDocument();
});
});

it('shows the button if is_ccx_course is true', async () => {
mockPost.mockResolvedValueOnce({ data: { is_ccx_course: true } });

render(<DashboardLaunchButton courseId={mockCourseId} title="Test Title" />);

await waitFor(() => {
expect(screen.getByRole('button', { name: /Go To Instructor Dashboard/i })).toBeInTheDocument();
});
});

it('handles button click and opens the dashboard URL if present', async () => {
mockPost.mockResolvedValueOnce({ data: { is_ccx_course: true } });
mockPost.mockResolvedValueOnce({ data: { url: 'https://example.com/dashboard' } });

render(<DashboardLaunchButton courseId={mockCourseId} title="Test Title" />);

await waitFor(() => {
expect(screen.getByRole('button', { name: /Go To Instructor Dashboard/i })).toBeInTheDocument();
});

window.open = jest.fn();

fireEvent.click(screen.getByRole('button', { name: /Go To Instructor Dashboard/i }));

await waitFor(() => {
expect(window.open).toHaveBeenCalledWith('https://example.com/dashboard', '_blank', 'noopener,noreferrer');
});
});

it('handles error when button is clicked and no URL is present', async () => {
mockPost.mockResolvedValueOnce({ data: { is_ccx_course: true } });
mockPost.mockResolvedValueOnce({ data: { url: '', error: 'Error message' } });

render(<DashboardLaunchButton courseId={mockCourseId} title="Test Title" />);

await waitFor(() => {
expect(screen.getByRole('button', { name: /Go To Instructor Dashboard/i })).toBeInTheDocument();
});

fireEvent.click(screen.getByRole('button', { name: /Go To Instructor Dashboard/i }));

await waitFor(() => {
expect(screen.getByText('Mocked AlertMessage')).toBeInTheDocument();
});
});
});
35 changes: 35 additions & 0 deletions src/shared/JsonViewer/tests/index.test.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import React from 'react';
import { render, screen } from '@testing-library/react';
import JsonViewer from '../index';
import '@testing-library/jest-dom';

describe('JsonViewer Component', () => {
const mockLabName = 'Test Lab';
const mockLabData = {
key1: 'value1',
key2: 2,
key3: true,
};

it('renders the component correctly', () => {
render(<JsonViewer labName={mockLabName} labData={mockLabData} />);

expect(screen.getByText('Test Lab')).toBeInTheDocument();
});

it('initializes JSONEditor with correct options and data', () => {
render(<JsonViewer labName={mockLabName} labData={mockLabData} />);

const editorContainer = document.querySelector('.jsoneditor');
expect(editorContainer).toBeInTheDocument();
});

it('destroys JSONEditor instance on component unmount', () => {
const { unmount } = render(<JsonViewer labName={mockLabName} labData={mockLabData} />);

unmount();

const editorContainer = document.querySelector('.jsoneditor');
expect(editorContainer).not.toBeInTheDocument();
});
});
63 changes: 63 additions & 0 deletions src/shared/LabDetailsCard/tests/index.test.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import React from 'react';
import { render, screen } from '@testing-library/react';
import '@testing-library/jest-dom';
import LabDetailsCard from '../index';

describe('LabDetailsCard Component', () => {
it('renders with default props', () => {
render(<LabDetailsCard />);

expect(screen.getByText('LAB PROFILE NAME')).toBeInTheDocument();
expect(screen.getByText('USER FIRST NAME')).toBeInTheDocument();
expect(screen.getByText('USER LAST NAME')).toBeInTheDocument();
expect(screen.getByText('START TIME')).toBeInTheDocument();
expect(screen.getByText('END TIME')).toBeInTheDocument();
expect(screen.getByText('STATE')).toBeInTheDocument();
expect(screen.getByText('COMPLETION STATUS')).toBeInTheDocument();
expect(screen.getByText('TOTAL RUN TIME')).toBeInTheDocument();
expect(screen.getByText('EXAM PASSED')).toBeInTheDocument();

expect(screen.getAllByText('N/A')).toHaveLength(8);
});

it('renders with provided props', () => {
const details = {
labProfileName: 'Sample Lab',
userFirstName: 'John',
userLastName: 'Doe',
startTime: '01/01/2023 10:00 AM',
endTime: '01/01/2023 12:00 PM',
state: 'Completed',
completionStatus: 'Success',
totalRunTime: '2 hours',
examPassed: 'Yes',
};

render(<LabDetailsCard details={details} />);

expect(screen.getByText('Sample Lab')).toBeInTheDocument();
expect(screen.getByText('John')).toBeInTheDocument();
expect(screen.getByText('Doe')).toBeInTheDocument();
expect(screen.getByText('01/01/2023 10:00 AM')).toBeInTheDocument();
expect(screen.getByText('01/01/2023 12:00 PM')).toBeInTheDocument();
expect(screen.getByText('Completed')).toBeInTheDocument();
expect(screen.getByText('Success')).toBeInTheDocument();
expect(screen.getByText('2 hours')).toBeInTheDocument();
expect(screen.getByText('Yes')).toBeInTheDocument();
});

it('renders correctly when some props are missing', () => {
const details = {
labProfileName: 'Partial Lab',
userFirstName: 'Jane',
};

render(<LabDetailsCard details={details} />);

expect(screen.getByText('Partial Lab')).toBeInTheDocument();
expect(screen.getByText('Jane')).toBeInTheDocument();

const emptySpans = document.querySelectorAll('.lab-details-item span:empty');
expect(emptySpans.length).toBe(7);
});
});
77 changes: 77 additions & 0 deletions src/shared/LabDetailsChartCard/tests/index.test.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import React from 'react';
import { render, screen } from '@testing-library/react';
import '@testing-library/jest-dom';
import LabDetailsChartCard from '../index';

describe('LabDetailsChartCard Component', () => {
it('renders with default props', () => {
render(<LabDetailsChartCard />);

expect(screen.getByText('NUMBER OF TASKS')).toBeInTheDocument();
expect(screen.getAllByText('COMPLETED TASKS')).toHaveLength(2);
expect(screen.getByText('SCORE')).toBeInTheDocument();

const numberOfTasks = screen.getByText('NUMBER OF TASKS').nextSibling;
const completedTasksElements = screen.getAllByText('COMPLETED TASKS');
const completedTasksFirstInstance = completedTasksElements[0].closest('.lab-details-item').querySelector('span');
const defaultGauges = screen.getAllByRole('meter'); // Get all gauges

expect(numberOfTasks).toHaveTextContent('0');
expect(completedTasksFirstInstance).toHaveTextContent('0');
expect(defaultGauges).toHaveLength(2); // Expecting 2 gauges
expect(defaultGauges[0]).toHaveAttribute('aria-valuenow', '0');
});

it('renders with provided props', () => {
const mockDetails = {
NumTasks: 10,
NumCompletedTasks: 7,
ExamMaxPossibleScore: 100,
ExamScore: 85,
};

render(<LabDetailsChartCard details={mockDetails} />);

expect(screen.getByText('NUMBER OF TASKS')).toBeInTheDocument();
expect(screen.getByText('10')).toBeInTheDocument();
expect(screen.getAllByText('COMPLETED TASKS')).toHaveLength(2);
expect(screen.getByText('SCORE')).toBeInTheDocument();
});

it('renders the Gauge charts correctly', () => {
const mockDetails = {
NumTasks: 8,
NumCompletedTasks: 5,
ExamMaxPossibleScore: 50,
ExamScore: 30,
};

render(<LabDetailsChartCard details={mockDetails} />);

// Check for the presence of the Gauge charts by role
const gauges = screen.getAllByRole('meter'); // 'meter' is the role for gauge elements
expect(gauges).toHaveLength(2);
});

it('handles missing details correctly', () => {
const partialDetails = {
NumTasks: 5,
};

render(<LabDetailsChartCard details={partialDetails} />);

expect(screen.getByText('5')).toBeInTheDocument();

const completedTasksElements = screen.getAllByText('COMPLETED TASKS');
const completedTasksItem = completedTasksElements[0].closest('.lab-details-item');
const completedTasksSpan = completedTasksItem.querySelector('span');

const defaultGauges = screen.getAllByRole('meter'); // Get all gauges

expect(completedTasksItem).not.toBeNull();
expect(completedTasksSpan).not.toBeNull();
expect(completedTasksSpan).toHaveTextContent('');
expect(defaultGauges).toHaveLength(2); // Expecting 2 gauges
01001110J marked this conversation as resolved.
Show resolved Hide resolved
expect(defaultGauges[0].hasAttribute('aria-valuenow')).toBe(false);
});
});
Loading
Loading