Skip to content

Commit

Permalink
test: Shared Components Test Suite
Browse files Browse the repository at this point in the history
  • Loading branch information
nandodev-net committed Sep 12, 2024
1 parent 35c842c commit 29cf066
Show file tree
Hide file tree
Showing 8 changed files with 465 additions and 1 deletion.
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';

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
expect(defaultGauges[0].hasAttribute('aria-valuenow')).toBe(false);
});
});
Loading

0 comments on commit 29cf066

Please sign in to comment.