Skip to content

Commit

Permalink
Merge pull request #3164 from ilandikov/refactor-test-date-editor
Browse files Browse the repository at this point in the history
refactor: test `DateEditor` svelte component
  • Loading branch information
claremacrae authored Nov 1, 2024
2 parents 48ed4b2 + c59ebdc commit e1a8a1c
Show file tree
Hide file tree
Showing 5 changed files with 175 additions and 23 deletions.
3 changes: 2 additions & 1 deletion src/ui/DateEditor.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
export let forwardOnly: boolean;
export let accesskey: string | null;
let parsedDate: string;
// Use this for testing purposes only
export let parsedDate: string = '';
// let inputElement: HTMLInputElement;
// let flatpickrInstance: any;
//
Expand Down
117 changes: 117 additions & 0 deletions tests/ui/DateEditor.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
/**
* @jest-environment jsdom
*/
import { fireEvent, render } from '@testing-library/svelte';
import moment from 'moment/moment';
import DateEditorWrapper from './DateEditorWrapper.svelte';

import { getAndCheckRenderedElement } from './RenderingTestHelpers';

window.moment = moment;

function renderDateEditorWrapper(componentOptions: { forwardOnly: boolean }) {
const { container } = render(DateEditorWrapper, componentOptions);

expect(() => container).toBeTruthy();

return container;
}

function testInputValue(container: HTMLElement, inputId: string, expectedText: string) {
const input = getAndCheckRenderedElement<HTMLInputElement>(container, inputId);
expect(input.value).toEqual(expectedText);
}

async function testTypingInput(
{
userTyped,
expectedLeftText,
expectedRightText,
expectedReturnedDate,
}: {
userTyped: string;
expectedLeftText: string;
expectedRightText: string;
expectedReturnedDate: string;
},
{ forwardOnly }: { forwardOnly: boolean } = { forwardOnly: true },
) {
const container = renderDateEditorWrapper({ forwardOnly });

const dueDateInput = getAndCheckRenderedElement<HTMLInputElement>(container, 'due');
await fireEvent.input(dueDateInput, { target: { value: userTyped } });

testInputValue(container, 'due', expectedLeftText);
testInputValue(container, 'parsedDateFromDateEditor', expectedRightText);
testInputValue(container, 'dueDateFromDateEditor', expectedReturnedDate);
}

beforeEach(() => {
jest.useFakeTimers();
jest.setSystemTime(new Date('2024-04-20'));
});

afterEach(() => {
jest.useRealTimers();
});

describe('date editor wrapper tests', () => {
it('should initialise fields correctly', () => {
const container = renderDateEditorWrapper({ forwardOnly: true });

testInputValue(container, 'due', '');
testInputValue(container, 'parsedDateFromDateEditor', '<i>no due date</i>');
testInputValue(container, 'dueDateFromDateEditor', '');
});

it('should replace an empty date field with typed date value', async () => {
await testTypingInput({
userTyped: '2024-10-01',
expectedLeftText: '2024-10-01',
expectedRightText: '2024-10-01',
expectedReturnedDate: '2024-10-01',
});
});

it('should replace an empty date field with typed abbreviation', async () => {
await testTypingInput({
userTyped: 'tm ',
expectedLeftText: 'tomorrow',
expectedRightText: '2024-04-21',
expectedReturnedDate: 'tomorrow',
});
});

it('should show an error message for invalid date', async () => {
await testTypingInput({
userTyped: 'blah',
expectedLeftText: 'blah',
expectedRightText: '<i>invalid due date</i>',
expectedReturnedDate: 'blah',
});
});

it('should select a forward date', async () => {
await testTypingInput(
{
userTyped: 'friday',
expectedLeftText: 'friday',
expectedRightText: '2024-04-26',
expectedReturnedDate: 'friday',
},
{ forwardOnly: true },
);
});

it('should select a backward/earlier date', async () => {
await testTypingInput(
{
userTyped: 'friday',
expectedLeftText: 'friday',
expectedRightText: '2024-04-19',
expectedReturnedDate: 'friday',
},
{ forwardOnly: false },
);
});
});
27 changes: 27 additions & 0 deletions tests/ui/DateEditorWrapper.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<script lang="ts">
import { TASK_FORMATS } from '../../src/Config/Settings';
import DateEditor from '../../src/ui/DateEditor.svelte';
export let forwardOnly: boolean;
let dateFromDateEditor: string = '';
let parsedDateFromDateEditor: string = '';
let isDueDateValid = true;
</script>

<DateEditor
id="due"
dateSymbol={TASK_FORMATS.tasksPluginEmoji.taskSerializer.symbols.dueDateSymbol}
bind:date={dateFromDateEditor}
bind:isDateValid={isDueDateValid}
{forwardOnly}
accesskey={null}
on:open={() => {}}
on:close={() => {}}
bind:parsedDate={parsedDateFromDateEditor}
/>
<input bind:value={dateFromDateEditor} id="dueDateFromDateEditor" />
<input bind:value={parsedDateFromDateEditor} id="parsedDateFromDateEditor" />

<style>
</style>
27 changes: 5 additions & 22 deletions tests/ui/EditTask.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ import { verifyWithFileExtension } from '../TestingTools/ApprovalTestHelpers';
import { verifyAllCombinations3Async } from '../TestingTools/CombinationApprovalsAsync';
import { prettifyHTML } from '../TestingTools/HTMLHelpers';
import { TaskBuilder } from '../TestingTools/TaskBuilder';
import {
getAndCheckApplyButton,
getAndCheckRenderedDescriptionElement,
getAndCheckRenderedElement,
} from './RenderingTestHelpers';

window.moment = moment;
/**
Expand Down Expand Up @@ -50,28 +55,6 @@ function renderAndCheckModal(task: Task, onSubmit: (updatedTasks: Task[]) => voi
return { result, container };
}

/**
* Find the element with the given id.
* Template type T might be, for example, HTMLInputElement or HTMLSelectElement
* @param container
* @param elementId
*/
function getAndCheckRenderedElement<T>(container: HTMLElement, elementId: string) {
const element = container.ownerDocument.getElementById(elementId) as T;
expect(() => element).toBeTruthy();
return element;
}

function getAndCheckRenderedDescriptionElement(container: HTMLElement): HTMLInputElement {
return getAndCheckRenderedElement<HTMLInputElement>(container, 'description');
}

function getAndCheckApplyButton(result: RenderResult<EditTask>): HTMLButtonElement {
const submit = result.getByText('Apply') as HTMLButtonElement;
expect(submit).toBeTruthy();
return submit;
}

async function editInputElement(inputElement: HTMLInputElement, newValue: string) {
await fireEvent.input(inputElement, { target: { value: newValue } });
}
Expand Down
24 changes: 24 additions & 0 deletions tests/ui/RenderingTestHelpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import type { RenderResult } from '@testing-library/svelte';
import type EditTask from '../../src/ui/EditTask.svelte';

/**
* Find the element with the given id.
* Template type T might be, for example, HTMLInputElement or HTMLSelectElement
* @param container
* @param elementId
*/
export function getAndCheckRenderedElement<T>(container: HTMLElement, elementId: string) {
const element = container.ownerDocument.getElementById(elementId) as T;
expect(() => element).toBeTruthy();
return element;
}

export function getAndCheckRenderedDescriptionElement(container: HTMLElement): HTMLInputElement {
return getAndCheckRenderedElement<HTMLInputElement>(container, 'description');
}

export function getAndCheckApplyButton(result: RenderResult<EditTask>): HTMLButtonElement {
const submit = result.getByText('Apply') as HTMLButtonElement;
expect(submit).toBeTruthy();
return submit;
}

0 comments on commit e1a8a1c

Please sign in to comment.