Skip to content

Commit

Permalink
533-refactor: Widget courses (#545)
Browse files Browse the repository at this point in the history
* refactor: 533 - move test file to ui folder

* refactor: 533 - rename test file

* refactor: 533 - move title to localization variable

* refactor: 533 - move courses to the variable

* refactor: 533 - change div to the article

* refactor: 533 - make scss module file

* refactor: 533 - change margin to padding

* refactor: 533 - change data-testid name

* refactor: 533 - rename classes add ul and li component

* refactor: 533 - update tests

* refactor: 533 - delete localization variable

* refactor: 533 - update styles

* refactor: 533 - rename class and delete ul tag

* refactor: 533 - combine tests

* refactor: 533 - combine tests

* refactor: 533 - update tests

* refactor: 533 - update styles

* refactor: 533 - move constant to new file

* refactor: 533 - update class name and test

* refactor: 533 - delete line
  • Loading branch information
YulikK authored Sep 27, 2024
1 parent bcef1a6 commit 7200da2
Show file tree
Hide file tree
Showing 6 changed files with 114 additions and 105 deletions.
1 change: 1 addition & 0 deletions src/widgets/courses/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const path = 'courses';
57 changes: 0 additions & 57 deletions src/widgets/courses/other-courses.test.tsx

This file was deleted.

24 changes: 24 additions & 0 deletions src/widgets/courses/ui/courses.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
.courses-content {
display: flex;
flex-direction: column;
gap: 24px;

@include media-laptop {
width: 100%;
}
}

.courses-list {
display: grid;
grid-template: 1fr / repeat(3, 1fr);
gap: 22px;
width: 100%;

@include media-laptop-medium {
grid-template: 1fr / repeat(2, 1fr);
}

@include media-tablet {
grid-template: 1fr / 1fr;
}
}
43 changes: 0 additions & 43 deletions src/widgets/courses/ui/courses.scss

This file was deleted.

80 changes: 80 additions & 0 deletions src/widgets/courses/ui/courses.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import { screen } from '@testing-library/react';
import { Mock, describe, expect, it, vi } from 'vitest';
import { Courses } from './courses';
import { MOCKED_IMAGE_PATH } from '@/shared/__tests__/constants';
import { renderWithRouter } from '@/shared/__tests__/utils';
import { useDataByName } from '@/shared/hooks/use-data-by-name';

const widgetTitle = 'All courses';
const mockCourses = [
{
id: '1',
title: 'React course',
iconSrc: MOCKED_IMAGE_PATH,
startDate: '23 Oct, 2023',
language: ['ru', 'en'],
mode: 'online',
detailsUrl: 'https://rs.school/react/',
backgroundStyle: {
backgroundColor: '#EEF3FE',
accentColor: '#7356BF',
},
},
{
id: '2',
title: 'React course 2',
iconSrc: MOCKED_IMAGE_PATH,
startDate: '23 Oct, 2023',
language: ['ru', 'en'],
mode: 'online',
detailsUrl: 'https://rs.school/react/',
backgroundStyle: {
backgroundColor: '#EEF3FE',
accentColor: '#7356BF',
},
},
];

vi.mock('@/shared/hooks/use-data-by-name', () => {
return {
useDataByName: vi.fn(() => ({
data: mockCourses,
loading: false,
error: undefined,
})),
};
});

describe('Courses (other courses) component', () => {
it('renders widget without crashing and display correct content', () => {
renderWithRouter(<Courses />);
const widget = screen.getByTestId('all-courses');
const title = screen.getByTestId('widget-title');
const courseCards = screen.getAllByTestId('course-card');

expect(widget).toBeVisible();
expect(title).toBeVisible();
expect(title).toHaveTextContent(widgetTitle);
expect(courseCards.length).toBe(mockCourses.length);
courseCards.forEach((card, index) => {
expect(card).toBeVisible();
expect(card).toHaveTextContent(mockCourses[index].title);
});
});

it('displays a loading state for other courses', () => {
(useDataByName as Mock).mockImplementation(() => ({ loading: true }));
renderWithRouter(<Courses />);

expect(screen.getByText('Loading...')).toBeVisible();
});

it('displays a error state for other courses', () => {
const errorMessage = 'Something went wrong';

(useDataByName as Mock).mockImplementation(() => ({ error: new Error(errorMessage) }));
renderWithRouter(<Courses />);

expect(screen.getByText(errorMessage)).toBeVisible();
});
});
14 changes: 9 additions & 5 deletions src/widgets/courses/ui/courses.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
import classNames from 'classnames/bind';
import { path } from '../constants';
import { COURSE_STALE_AFTER_DAYS } from '@/app/const';
import { type Course, CourseCard } from '@/entities/course';
import { getActualData } from '@/shared/helpers/getActualData';
import { isCourse } from '@/shared/helpers/is-course';
import { useDataByName } from '@/shared/hooks/use-data-by-name';
import { WidgetTitle } from '@/shared/ui/widget-title';

import './courses.scss';
import styles from './courses.module.scss';

const cx = classNames.bind(styles);

export const Courses = () => {
const { data: courses, loading, error } = useDataByName('courses');
const { data: courses, loading, error } = useDataByName(path);

if (loading) {
return <h2>Loading...</h2>;
Expand All @@ -29,10 +33,10 @@ export const Courses = () => {
const sortedCourses: Course[] = getActualData(sortParams);

return (
<section className="rs-courses container" id="upcoming-courses">
<div className="rs-courses content">
<section className={cx('container')} data-testid="all-courses">
<div className={cx('content', 'courses-content')}>
<WidgetTitle>All courses</WidgetTitle>
<div className="rs-courses-wrapper" data-testid="courses-fancy">
<div className={cx('courses-list')}>
{sortedCourses.map((course) => {
return <CourseCard key={course.id} {...course} />;
})}
Expand Down

0 comments on commit 7200da2

Please sign in to comment.