Skip to content

Commit

Permalink
✨ [#52] Wire up the component edit form for selectboxes
Browse files Browse the repository at this point in the history
The selectboxes now allows specifying the values, either
manually or through an items expression. The labels of
options can be translated on the translations tab.
  • Loading branch information
sergei-maertens committed Nov 17, 2023
1 parent 913c792 commit 9ff5333
Show file tree
Hide file tree
Showing 5 changed files with 463 additions and 0 deletions.
209 changes: 209 additions & 0 deletions src/components/ComponentConfiguration.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -777,6 +777,10 @@ export const FileUpload: Story = {
component: {
id: 'kiweljhr',
storage: 'url',
webcam: false,
options: {
withCredentials: true,
},
url: '',
type: 'file',
key: 'file',
Expand Down Expand Up @@ -900,3 +904,208 @@ export const FileUpload: Story = {
});
},
};

export const SelectBoxes: Story = {
render: Template,
name: 'type: selectboxes',

args: {
component: {
id: 'wqimsadk',
type: 'selectboxes',
key: 'selectboxes',
label: 'A selectboxes field',
openForms: {
dataSrc: 'manual',
translations: {},
},
values: [],
defaultValue: {},
},

builderInfo: {
title: 'Select Boxes',
icon: 'plus-square',
group: 'basic',
weight: 60,
schema: {},
},
},

play: async ({canvasElement, step, args}) => {
const canvas = within(canvasElement);
const editForm = within(canvas.getByTestId('componentEditForm'));
const preview = within(canvas.getByTestId('componentPreview'));

await expect(canvas.getByLabelText('Label')).toHaveValue('A selectboxes field');
await waitFor(async () => {
await expect(canvas.getByLabelText('Property Name')).toHaveValue('aSelectboxesField');
});
await expect(canvas.getByLabelText('Description')).toHaveValue('');
await expect(canvas.getByLabelText('Tooltip')).toHaveValue('');
await expect(canvas.getByLabelText('Show in summary')).toBeChecked();
await expect(canvas.getByLabelText('Show in email')).not.toBeChecked();
await expect(canvas.getByLabelText('Show in PDF')).toBeChecked();

// ensure that changing fields in the edit form properly update the preview

await userEvent.clear(canvas.getByLabelText('Label'));
await userEvent.type(canvas.getByLabelText('Label'), 'Updated preview label');
expect(await preview.findByText('Updated preview label'));

const previewInput = preview.getByRole('checkbox');
await expect(previewInput).not.toBeChecked();

// Ensure that the manually entered key is kept instead of derived from the label,
// even when key/label components are not mounted.
const keyInput = canvas.getByLabelText('Property Name');
// fireEvent is deliberate, as userEvent.clear + userEvent.type briefly makes the field
// not have any value, which triggers the generate-key-from-label behaviour.
fireEvent.change(keyInput, {target: {value: 'customKey'}});
await userEvent.click(canvas.getByRole('tab', {name: 'Basic'}));
await userEvent.clear(canvas.getByLabelText('Label'));
await userEvent.type(canvas.getByLabelText('Label'), 'Other label', {delay: 50});
await expect(canvas.getByLabelText('Property Name')).toHaveDisplayValue('customKey');

await step('Set up manual options', async () => {
// enter some possible options
const firstOptionLabelInput = canvas.getByLabelText('Option label');
expect(firstOptionLabelInput).toHaveDisplayValue('');
await userEvent.type(firstOptionLabelInput, 'Option label 1');
const firstOptionValue = canvas.getByLabelText('Option value');
await waitFor(() => expect(firstOptionValue).toHaveDisplayValue('optionLabel1'));

// add a second option
await userEvent.click(canvas.getByRole('button', {name: 'Add another'}));
const optionLabels = canvas.queryAllByLabelText('Option label');
const optionValues = canvas.queryAllByLabelText('Option value');
expect(optionLabels).toHaveLength(2);
expect(optionValues).toHaveLength(2);
await userEvent.type(optionValues[1], 'manualValue');
await userEvent.type(optionLabels[1], 'Second option');

await userEvent.click(canvas.getByRole('button', {name: 'Save'}));
expect(args.onSubmit).toHaveBeenCalledWith({
id: 'wqimsadk',
type: 'selectboxes',
// basic tab
label: 'Other label',
key: 'customKey',
description: '',
tooltip: '',
showInSummary: true,
showInEmail: false,
showInPDF: true,
hidden: false,
clearOnHide: true,
isSensitiveData: false,
openForms: {
dataSrc: 'manual',
translations: {},
},
values: [
{
value: 'optionLabel1',
label: 'Option label 1',
},
{
value: 'manualValue',
label: 'Second option',
openForms: {translations: {}},
},
],
defaultValue: {
optionLabel1: false,
manualValue: false,
},
// Advanced tab
conditional: {
show: undefined,
when: '',
eq: '',
},
// Validation tab
validate: {
required: false,
plugins: [],
},
translatedErrors: {
nl: {required: ''},
},
// registration tab
registration: {
attribute: '',
},
});
// @ts-expect-error
args.onSubmit.mockClear();
});

await step('Option labels are translatable', async () => {
await userEvent.click(canvas.getByRole('tab', {name: 'Translations'}));

// check that the option labels are in the translations table
expect(await editForm.findByText('Option label 1')).toBeVisible();
expect(await editForm.findByText('Second option')).toBeVisible();
});

await step('Set up itemsExpression for options', async () => {
await userEvent.click(canvas.getByRole('tab', {name: 'Basic'}));

canvas.getByLabelText('Data source').focus();
await userEvent.keyboard('[ArrowDown]');
await userEvent.click(await canvas.findByText('From variable'));
const itemsExpressionInput = canvas.getByLabelText('Items expression');
await userEvent.clear(itemsExpressionInput);
// { needs to be escaped: https://github.com/testing-library/user-event/issues/584
const expression = '{"var": "someVar"}'.replace(/[{[]/g, '$&$&');
await userEvent.type(itemsExpressionInput, expression);

await expect(editForm.queryByLabelText('Default value')).toBeNull();
await expect(preview.getByRole('checkbox', {name: /Options from expression:/})).toBeVisible();

await userEvent.click(canvas.getByRole('button', {name: 'Save'}));
expect(args.onSubmit).toHaveBeenCalledWith({
id: 'wqimsadk',
type: 'selectboxes',
// basic tab
label: 'Other label',
key: 'customKey',
description: '',
tooltip: '',
showInSummary: true,
showInEmail: false,
showInPDF: true,
hidden: false,
clearOnHide: true,
isSensitiveData: false,
openForms: {
dataSrc: 'variable',
itemsExpression: {var: 'someVar'},
translations: {},
},
defaultValue: {},
// Advanced tab
conditional: {
show: undefined,
when: '',
eq: '',
},
// Validation tab
validate: {
required: false,
plugins: [],
},
translatedErrors: {
nl: {required: ''},
},
// registration tab
registration: {
attribute: '',
},
});
// @ts-expect-error
args.onSubmit.mockClear();
});
},
};
2 changes: 2 additions & 0 deletions src/registry/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import Licenseplate from './licenseplate';
import NumberField from './number';
import PhoneNumber from './phonenumber';
import Postcode from './postcode';
import Selectboxes from './selectboxes';
import TextField from './textfield';
import TimeField from './time';
import {Registry, RegistryEntry} from './types';
Expand Down Expand Up @@ -39,6 +40,7 @@ const REGISTRY: Registry = {
phoneNumber: PhoneNumber,
postcode: Postcode,
file: FileUpload,
selectboxes: Selectboxes,
currency: Currency,
// Special types:
iban: Iban,
Expand Down
Loading

0 comments on commit 9ff5333

Please sign in to comment.