Skip to content

Commit

Permalink
Add missing tests and fix broken tests
Browse files Browse the repository at this point in the history
Include ts files into the test runner config
  • Loading branch information
fekete965 committed Oct 10, 2023
1 parent 95a8015 commit 743eac0
Show file tree
Hide file tree
Showing 6 changed files with 203 additions and 118 deletions.
38 changes: 20 additions & 18 deletions src/__tests__/components/Select.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,47 +4,49 @@ import { describe, expect, it } from 'vitest';

// TODO: Migrate to TS and use component's props
// eg.: const renderSelect = (props: React.componentProps<typeof Select>) => ...
const renderSelect = (name, value, onChange) => {
return render(<Select name={name} onChange={onChange} value={value} />);
const renderSelect = ({ checked, name, onChange, value }) => {
return render(
<Select checked={checked} name={name} onChange={onChange} value={value} />
);
};

const baseProps = {
checked: false,
name: 'Test Name',
onChange: () => null,
value: 'Test Value',
};

describe('Select', () => {
it('should renders the select input with the correct name', () => {
renderSelect('Test Name', 'Test Value');
renderSelect(baseProps);

const selectInput = screen.getByRole('radio');
expect(selectInput).toBeInTheDocument();
expect(selectInput).toHaveAttribute('name', 'language');
expect(selectInput).toHaveAttribute('name', 'Test Name');
});

it('should renders the label with the correct text', () => {
renderSelect('Test Name', 'Test Value');
renderSelect(baseProps);

const label = screen.getByText(/Test Name/i);
expect(label).toBeInTheDocument();
});

it('should checks the input if the value matches the name', () => {
renderSelect('Test Name', 'Test Name');
it('should render the input as checked', () => {
renderSelect({ ...baseProps, checked: true });

const selectInput = screen.getByRole('radio');
expect(selectInput).toBeChecked();
});

it('should does not check the input if the value does not match the name', () => {
renderSelect('Test Name', 'Different Value');

const selectInput = screen.getByRole('radio');
expect(selectInput).not.toBeChecked();
});

it('should fire onChange correctly', () => {
let state = null;
const onChange = (e) => {
state = e.currentTarget.id;
};

renderSelect('Test Name', 'Different Value', onChange);
renderSelect({
...baseProps,
onChange: (e) => (state = e.currentTarget.id),
});

const selectInput = screen.getByRole('radio');
expect(selectInput).toBeInTheDocument();
Expand Down
32 changes: 0 additions & 32 deletions src/__tests__/components/SortBy.test.jsx

This file was deleted.

54 changes: 54 additions & 0 deletions src/__tests__/components/SortingTagFilter.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { SortingTagFilter } from '@/components';
import { getSortingTagLabel } from '@/models/SortingTag';
import { RenderResult, fireEvent, render } from '@testing-library/react';
import { ComponentProps } from 'react';
import { describe, expect, it, vi } from 'vitest';

type Props = ComponentProps<typeof SortingTagFilter>;

const renderElement = (props: Props): RenderResult => {
return render(<SortingTagFilter {...props} />);
};

const baseProps: Props = {
isSelected: false,
onClick: () => null,
ordering: 'desc',
value: 'best-match',
};

describe('SortingTagFilter', () => {
it('should render an unselected button WITHOUT tool-tip correctly', () => {
const screen = renderElement(baseProps);

const expectedLabelText = getSortingTagLabel(baseProps.value);
const expectedToolTipText = `Sorted by ${expectedLabelText} in ${baseProps.ordering}`;

expect(screen.queryByText(expectedLabelText)).toBeInTheDocument();
expect(screen.queryByText(expectedToolTipText)).not.toBeInTheDocument();
});

it('should render a selected button WITH tool-tip correctly', () => {
const props: Props = { ...baseProps, isSelected: true };
const screen = renderElement(props);

const expectedLabelText = getSortingTagLabel(props.value);
const expectedToolTipText = `Sorted by ${expectedLabelText} in ${props.ordering}`;

expect(screen.queryByText(expectedLabelText)).toBeInTheDocument();
expect(screen.queryByText(expectedToolTipText)).toBeInTheDocument();
});

it('should invoke onClick on button click', () => {
const props: Props = {
isSelected: false,
onClick: vi.fn(),
ordering: 'desc',
value: 'reactions',
};
const screen = renderElement(props);

fireEvent.click(screen.getByRole('button', { name: /reactions/i }));
expect(props.onClick).to.toBeCalled();
});
});
67 changes: 0 additions & 67 deletions src/__tests__/hooks/use-url.test.jsx

This file was deleted.

128 changes: 128 additions & 0 deletions src/__tests__/hooks/useUrlValues.test.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
import {
DEFAULT_LANGUAGE,
DEFAULT_ORDERING,
DEFAULT_PAGE,
DEFAULT_SORTING_TAG,
} from '@/lib/utils/config';
import { composeUrl } from '@/lib/utils/helper';
import UrlProvider, { useUrlValues } from '@/providers/urlProvider';
import { act, render } from '@testing-library/react';
import { beforeEach, describe, expect, it } from 'vitest';

describe('useUrlValues', () => {
let result;
function TestComponent() {
result = useUrlValues();
return null;
}

beforeEach(() => {
render(
<UrlProvider>
<TestComponent />
</UrlProvider>
);
});

it('should provide the correct initial context values', () => {
expect(result).toEqual({
dispatch: expect.any(Function),
language: DEFAULT_LANGUAGE,
ordering: DEFAULT_ORDERING,
page: DEFAULT_PAGE,
sortingTag: DEFAULT_SORTING_TAG,
url: composeUrl(
DEFAULT_LANGUAGE,
DEFAULT_PAGE,
DEFAULT_SORTING_TAG,
DEFAULT_ORDERING
),
});
});

it('should update the page number correctly', () => {
act(() => {
result.dispatch({ type: 'update-page', payload: 2 });
});

expect(result.page).toBe(2);
});

it('should update the language correctly', () => {
act(() => {
result.dispatch({ type: 'update-language', payload: 'javascript' });
});

expect(result.language).toBe('javascript');
});

it('should update the sorting tag correctly', () => {
act(() => {
result.dispatch({ type: 'update-sorting-tag', payload: 'reactions' });
});

expect(result.sortingTag).toBe('reactions');
});

it('should reset the page number when language changes', () => {
act(() => {
result.dispatch({ type: 'update-page', payload: 2 });
result.dispatch({ type: 'update-language', payload: 'javascript' });
});

expect(result.language).toBe('javascript');
expect(result.page).toBe(1);
});

it('should not change page number to a value less than 1', () => {
act(() => {
result.dispatch({ type: 'update-page', payload: -2 });
});

expect(result.page).toBe(1);
});

it('should update the url on any state changes', () => {
act(() => {
// Update page
result.dispatch({ type: 'update-page', payload: 2 });
});

let expectedUrl = composeUrl(
DEFAULT_LANGUAGE,
2,
DEFAULT_SORTING_TAG,
DEFAULT_ORDERING
);
expect(result.url).toBe(expectedUrl);

act(() => {
// Update the language
result.dispatch({ type: 'update-language', payload: 'javascript' });
});

expectedUrl = composeUrl(
'javascript',
2,
DEFAULT_SORTING_TAG,
DEFAULT_ORDERING
);
expect(result.url).toBe(expectedUrl);

act(() => {
// Update the sorting tag, this will also reset the page number and the ordering
result.dispatch({ type: 'update-sorting-tag', payload: 'reactions' });
});

expectedUrl = composeUrl('javascript', 1, 'reactions', DEFAULT_ORDERING);
expect(result.url).toBe(expectedUrl);

act(() => {
// Update the ordering by selecting the same language
result.dispatch({ type: 'update-sorting-tag', payload: 'reactions' });
});

expectedUrl = composeUrl('javascript', 1, 'reactions', 'asc');
expect(result.url).toBe(expectedUrl);
});
});
2 changes: 1 addition & 1 deletion vitest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export default defineConfig({
test: {
environment: 'jsdom',
setupFiles: ['./src/__tests__/setup.js'],
include: ['./src/__tests__/**/*.test.jsx'],
include: ['./src/__tests__/**/*.test.{js,ts,jsx,tsx}'],
globals: true,
},
resolve: {
Expand Down

0 comments on commit 743eac0

Please sign in to comment.