Skip to content

Commit

Permalink
fix: call fileItem onChange only when there is actually a change (pod…
Browse files Browse the repository at this point in the history
…man-desktop#9075)

* fix: call fileItem onChange only when it actually changes

Signed-off-by: lstocchi <[email protected]>

* fix: use callback

Signed-off-by: lstocchi <[email protected]>

* fix: extract lambda to function

Signed-off-by: lstocchi <[email protected]>

* fix: handle input

Signed-off-by: lstocchi <[email protected]>

---------

Signed-off-by: lstocchi <[email protected]>
  • Loading branch information
lstocchi authored Sep 26, 2024
1 parent 90762a1 commit f1e7687
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import type { IConfigurationPropertyRecordedSchema } from '../../../../../main/s
import FileItem from './FileItem.svelte';

const openDialogMock = vi.fn();

beforeAll(() => {
(window as any).getConfigurationValue = vi.fn();
(window as any).openDialog = openDialogMock;
Expand Down Expand Up @@ -91,3 +92,27 @@ test('Ensure clicking on browse invokes openDialog with corresponding directory
selectors: ['openDirectory'],
});
});

test('Ensure the onChange is called if the fileInput onChange is triggered', async () => {
const filename = 'somefile';
openDialogMock.mockResolvedValue([filename]);

const record: IConfigurationPropertyRecordedSchema = {
id: 'record',
title: 'record',
parentId: 'parent.record',
description: 'record-description',
type: 'string',
format: 'file',
};

const onChangeMock = vi.fn().mockResolvedValue('');
render(FileItem, { record, value: '', onChange: onChangeMock });
const browseButton = screen.getByRole('button');
expect(browseButton).toBeInTheDocument();
await userEvent.click(browseButton);

expect(openDialogMock).toHaveBeenCalled();

expect(onChangeMock).toHaveBeenCalled();
});
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,16 @@ export let record: IConfigurationPropertyRecordedSchema;
export let value: string = '';
export let onChange = async (_id: string, _value: string) => {};
let lastValue: string;
let invalidEntry = false;
let dialogOptions: OpenDialogOptions = {
title: `Select ${record.description}`,
selectors: record.format === 'folder' ? ['openDirectory'] : ['openFile'],
};
$: if (value !== lastValue) {
function onChangeFileInput(value: string): void {
if (record.id) {
onChange(record.id, value).catch((_: unknown) => (invalidEntry = true));
}
lastValue = value;
}
</script>

Expand All @@ -30,6 +27,7 @@ $: if (value !== lastValue) {
id="input-standard-{record.id}"
name={record.id}
bind:value={value}
onChange={onChangeFileInput}
readonly={record.readonly ?? true}
placeholder={record.placeholder}
options={dialogOptions}
Expand Down
46 changes: 44 additions & 2 deletions packages/renderer/src/lib/ui/FileInput.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,12 @@ test('Expect clicking the button opens file dialog', async () => {
expect(openDialogMock).toHaveBeenCalled();
});

test('Expect value to change when selecting via file dialog', async () => {
test('Expect onChange function called with new value when selecting via file dialog', async () => {
const filename = 'somefile';
openDialogMock.mockResolvedValue([filename]);

render(FileInput, {});
const onChangeMock = vi.fn();
render(FileInput, { options: { title: 'title' }, onChange: onChangeMock });

const browseButton = screen.getByRole('button');
expect(browseButton).toBeInTheDocument();
Expand All @@ -57,4 +58,45 @@ test('Expect value to change when selecting via file dialog', async () => {
const input = screen.getByRole('textbox');
expect(input).toBeInTheDocument();
expect(input).toHaveValue(filename);

expect(onChangeMock).toHaveBeenCalledWith(filename);
});

test('Expect onChange function called if user types', async () => {
const filename = 'somefile';
const onChangeMock = vi.fn();
render(FileInput, { options: { title: 'title' }, onChange: onChangeMock });

const browseButton = screen.getByRole('button');
expect(browseButton).toBeInTheDocument();
await userEvent.click(browseButton);

expect(openDialogMock).toHaveBeenCalled();

const input = screen.getByRole('textbox');
expect(input).toBeInTheDocument();

await userEvent.type(input, filename);

expect(onChangeMock).toHaveBeenCalledWith(filename);
});

test('Expect onChange function called if user paste content', async () => {
const filename = 'somefile';
const onChangeMock = vi.fn();
render(FileInput, { options: { title: 'title' }, onChange: onChangeMock });

const browseButton = screen.getByRole('button');
expect(browseButton).toBeInTheDocument();
await userEvent.click(browseButton);

expect(openDialogMock).toHaveBeenCalled();

const input = screen.getByRole('textbox');
expect(input).toBeInTheDocument();

await userEvent.click(input);
await userEvent.paste(filename);

expect(onChangeMock).toHaveBeenCalledWith(filename);
});
9 changes: 8 additions & 1 deletion packages/renderer/src/lib/ui/FileInput.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,20 @@ export let value: string | undefined = undefined;
export let options: OpenDialogOptions;
export let readonly: boolean = false;
export let required: boolean = false;
export let onChange: (value: string) => void = () => {};
async function openDialog() {
const result = await window.openDialog(options);
if (result?.[0]) {
value = result[0];
onChange(value);
}
}
function onInput(event: Event): void {
const inputEvent = event as Event & { target: HTMLInputElement };
onChange(inputEvent.target.value);
}
</script>

<div class="flex flex-row grow space-x-1.5">
Expand All @@ -25,7 +32,7 @@ async function openDialog() {
name={name}
class={$$props.class || ''}
bind:value={value}
on:input
on:input={onInput}
on:keypress
placeholder={placeholder}
readonly={readonly}
Expand Down

0 comments on commit f1e7687

Please sign in to comment.