+
+
+
+
+
+
+
+ }
+ />
+ );
+ };
- const renderWeekdayFormatField = () => {
+ const renderWeekdayFormatField = useCallback(() => {
return (
}
+ label={
+
+ }
name={`${name}.weekdayFormat.value`}
required
validate={requiredValidator}
/>
);
- };
+ }, [intl, name]);
- const renderMonthDayFormatField = () => {
+ const renderMonthDayFormatField = useCallback(() => {
return (
);
- };
+ }, [intl, name]);
- const renderMonthFormatField = () => {
+ const renderMonthFormatField = useCallback(() => {
return (
}
+ label={
+
+ }
name={`${name}.monthFormat.value`}
required
validate={requiredValidator}
/>
);
- };
+ }, [intl, name]);
- const renderYearFormatField = () => {
+ const renderYearFormatField = useCallback(() => {
return (
}
+ label={
+
+ }
name={`${name}.yearFormat.value`}
required
validate={requiredValidator}
/>
);
- };
+ }, [intl, name]);
- const chronologyFormats = {
- chronology_date: {
- fields: [
- renderWeekdayFormatField(),
- renderMonthDayFormatField(),
- renderMonthFormatField(),
- renderYearFormatField(),
-
-
- {chronologyValues[tokenIndex]}
-
,
- ],
- },
- chronology_month: {
- fields: [
- renderMonthFormatField(),
- renderYearFormatField(),
-
-
- {chronologyValues[tokenIndex]}
-
,
- ],
- },
- chronology_year: {
- fields: [
- renderYearFormatField(),
-
-
- {chronologyValues[tokenIndex]}
-
,
- ],
- },
- };
+ const chronologyFormats = useMemo(
+ () => ({
+ chronology_date: {
+ getFields: () => [
+ renderWeekdayFormatField(),
+ renderMonthDayFormatField(),
+ renderMonthFormatField(),
+ renderYearFormatField(),
+
+
+ {tokenText}
+
,
+ ],
+ },
+ chronology_month: {
+ getFields: () => [
+ renderMonthFormatField(),
+ renderYearFormatField(),
+
+
+ {tokenText}
+
,
+ ],
+ },
+ chronology_year: {
+ getFields: () => [
+ renderYearFormatField(),
+
+
+ {tokenText}
+
,
+ ],
+ },
+ }),
+ [
+ renderMonthDayFormatField,
+ renderMonthFormatField,
+ renderWeekdayFormatField,
+ renderYearFormatField,
+ tokenText,
+ ]
+ );
return (
<>
{chronologyFormats[
- templateConfig?.ruleType?.templateMetadataRuleFormat
- ]?.fields?.map((chronologyField, index) => {
+ chronologyRule?.templateMetadataRuleFormat
+ ]?.getFields()?.map((chronologyField, fieldIndex) => {
return (
-
+
{chronologyField}
);
@@ -201,10 +238,8 @@ const ChronologyField = ({
ChronologyField.propTypes = {
name: PropTypes.string,
- templateConfig: PropTypes.object,
- tokensInfo: PropTypes.func,
- tokenIndex: PropTypes.number,
- values: PropTypes.object
+ chronologyRule: PropTypes.object,
+ index: PropTypes.number,
};
export default ChronologyField;
diff --git a/src/components/RulesetFormSections/ChronologyField/ChronologyField.test.js b/src/components/RulesetFormSections/ChronologyField/ChronologyField.test.js
index 018cde76..204add9d 100644
--- a/src/components/RulesetFormSections/ChronologyField/ChronologyField.test.js
+++ b/src/components/RulesetFormSections/ChronologyField/ChronologyField.test.js
@@ -1,9 +1,8 @@
-import { waitFor } from '@folio/jest-config-stripes/testing-library/react';
import {
renderWithIntl,
TestForm,
Select,
- Button,
+ testSelect,
} from '@folio/stripes-erm-testing';
import ChronologyField from './ChronologyField';
@@ -11,78 +10,6 @@ import ChronologyField from './ChronologyField';
import { translationsProperties } from '../../../../test/helpers';
import mockRefdata from '../../../../test/resources/refdata';
-const templateConfig = {
- templateMetadataRuleType: 'chronology',
- ruleType: {
- templateMetadataRuleFormat: 'chronology_date',
- ruleFormat: {
- weekdayFormat: {
- value: 'full_lower',
- },
- monthDayFormat: {
- value: 'ordinal',
- },
- monthFormat: {
- value: 'full',
- },
- yearFormat: {
- value: 'full',
- },
- },
- },
-};
-
-const tokenIndex = 2;
-
-const values = {
- 'rulesetStatus': {
- 'value': 'active'
- },
- 'templateConfig': {
- 'rules': [
- {
- 'templateMetadataRuleType': 'enumeration',
- 'ruleType': {
- 'templateMetadataRuleFormat': 'enumeration_numeric',
- 'ruleFormat': {
- 'levels': [
- '{}'
- ]
- }
- }
- },
- {
- 'templateMetadataRuleType': 'enumeration',
- 'ruleType': {
- 'templateMetadataRuleFormat': 'enumeration_numeric',
- 'ruleFormat': '{levels: Array(1)}'
- }
- },
- {
- 'templateMetadataRuleType': 'chronology',
- 'ruleType': {
- 'ruleLocale': 'en',
- 'templateMetadataRuleFormat': 'chronology_date'
- }
- },
- {
- 'templateMetadataRuleType': 'chronology',
- 'ruleType': {
- 'ruleLocale': 'en',
- 'templateMetadataRuleFormat': 'chronology_year'
- }
- },
- {
- 'templateMetadataRuleType': 'enumeration',
- 'ruleType': {
- 'templateMetadataRuleFormat': 'enumeration_textual',
- 'ruleFormat': '{levels: Array(1)}'
- }
- }
- ]
- }
-};
-
jest.mock('../../utils', () => ({
...jest.requireActual('../../utils'),
useSerialsManagementRefdata: () => mockRefdata,
@@ -90,101 +17,101 @@ jest.mock('../../utils', () => ({
const onSubmit = jest.fn();
-let renderComponent;
-describe('ChronologyField', () => {
- beforeEach(() => {
- renderComponent = renderWithIntl(
-
-
- ,
- translationsProperties
- );
- });
-
- test('renders the expected template tokens label', async () => {
- const { getByText } = renderComponent;
- expect(getByText('Template tokens')).toBeInTheDocument();
- });
-
- test('renders the expected template tokens', async () => {
- const { getByText } = renderComponent;
- expect(
- getByText(
- '{{chronology1.weekday}} {{chronology1.monthDay}} {{chronology1.month}} {{chronology1.year}}'
- )
- ).toBeInTheDocument();
- });
-
- test('renders the expected text', async () => {
- const { getByText } = renderComponent;
- expect(getByText('Weekday format')).toBeInTheDocument();
- });
-
- test('renders the expected text', async () => {
- const { getByText } = renderComponent;
- expect(getByText('Month day format')).toBeInTheDocument();
- });
-
- test('renders the expected text', async () => {
- const { getByText } = renderComponent;
- expect(getByText('Month format')).toBeInTheDocument();
- });
-
- test('renders the expected text', async () => {
- const { getByText } = renderComponent;
- expect(getByText('Year format')).toBeInTheDocument();
- });
-
- test('renders the expected label', async () => {
- const { getByText } = renderComponent;
- expect(getByText('Template tokens')).toBeInTheDocument();
- });
-
- test('renders a Select for Weekday format', async () => {
- await Select('Weekday format*').exists();
- });
-
- test('renders the Weekday format dropdown with correct options', async () => {
- await Select('Weekday format*').exists();
- await waitFor(async () => {
- await Select('Weekday format*').choose('Monday');
- await Select('Weekday format*').choose('MONDAY');
- await Select('Weekday format*').choose('Mon');
- await Select('Weekday format*').choose('MON');
- });
- });
+// These are the name, label and options for all selectors rendered by the chronology field
+// Options array should be use findRefDataCategory values, however due to weird translation stuff we do it has to be like this
+// See selectOptionTranslations as to why
+const weekdaySelector = {
+ selector: {
+ name: 'templateConfig.chronologyRules[0].ruleFormat.weekdayFormat.value',
+ },
+ selectorName: 'Weekday format*',
+ optionsArray: ['Monday', 'MONDAY', 'Mon', 'MON', ''],
+};
+const monthDaySelector = {
+ selector: {
+ name: 'templateConfig.chronologyRules[0].ruleFormat.monthDayFormat.value',
+ },
+ selectorName: 'Month day format*',
+ optionsArray: ['3', '3rd', ''],
+};
+const monthSelector = {
+ selector: {
+ name: 'templateConfig.chronologyRules[0].ruleFormat.monthFormat.value',
+ },
+ selectorName: 'Month format*',
+ optionsArray: ['October', '10', 'Oct', ''],
+};
+const yearSelector = {
+ selector: { name: 'templateConfig.chronologyRules[0].ruleFormat.yearFormat.value' },
+ selectorName: 'Year format*',
+ optionsArray: ['2023', '23', ''],
+};
- test('renders the Month day format dropdown with correct options', async () => {
- await Select('Month day format*').exists();
- await waitFor(async () => {
- await Select('Month day format*').choose('3');
- await Select('Month day format*').choose('3rd');
+describe('ChronologyField', () => {
+ // TODO These values need to be moved over to using the centralised resources
+ // Should be using the getRulesetFormValues utils to change the ruleset from persistent values in centralised resources
+ // into form values as this is what happens to the values that are passed from the forms route level
+ //
+ // Besides that this is passing down a title for description purposes along with the props that would be set within the ChronologyFieldArray
+ // It additionally passes down the fields which will be renders based on the templateMetadataRuleFormat
+ describe.each([
+ {
+ title: 'chronology_date',
+ componentProps: {
+ chronologyRule: {
+ ruleLocale: 'en',
+ templateMetadataRuleFormat: 'chronology_date',
+ },
+ },
+ fields: [weekdaySelector, monthDaySelector, monthSelector, yearSelector],
+ },
+ {
+ title: 'chronology_month',
+ componentProps: {
+ chronologyRule: {
+ ruleLocale: 'en',
+ templateMetadataRuleFormat: 'chronology_month',
+ },
+ },
+ fields: [monthSelector, yearSelector],
+ },
+ {
+ title: 'chronology_year',
+ componentProps: {
+ chronologyRule: {
+ ruleLocale: 'en',
+ templateMetadataRuleFormat: 'chronology_year',
+ },
+ },
+ fields: [yearSelector],
+ },
+ ])('with $title templateMetadataRuleFormat', ({ componentProps, fields }) => {
+ // Renders the component with the above component props
+ beforeEach(() => {
+ renderWithIntl(
+
+
+ ,
+ translationsProperties
+ );
});
- });
- test('renders the Month format dropdown with correct options', async () => {
- await Select('Month format*').exists();
- await waitFor(async () => {
- await Select('Month format*').choose('October');
- await Select('Month format*').choose('10');
- await Select('Month format*').choose('Oct');
- });
- });
+ // Checks that all of the fields are rendered
+ test.each(fields)(
+ 'renders Select component with label $selectorName ',
+ (field) => {
+ Select(field.selectorName).exists();
+ }
+ );
- test('renders the Year format dropdown with correct options', async () => {
- await Select('Year format*').exists();
- await waitFor(async () => {
- await Select('Year format*').choose('2023');
- await Select('Year format*').choose('23');
+ // Then tests each field and all options and checks that the correct option is selected
+ // NOTE This is not in version 2.2.1 of stripes-erm-testing so cannot be back ported
+ describe.each(fields)('$selectorName select', (field) => {
+ testSelect(field);
});
});
-
- test('renders the submit button', async () => {
- await Button('Submit').exists();
- });
});
diff --git a/src/components/RulesetFormSections/ChronologyFieldArray/ChronologyFieldArray.js b/src/components/RulesetFormSections/ChronologyFieldArray/ChronologyFieldArray.js
new file mode 100644
index 00000000..fc7eaa2e
--- /dev/null
+++ b/src/components/RulesetFormSections/ChronologyFieldArray/ChronologyFieldArray.js
@@ -0,0 +1,156 @@
+import { useCallback, useMemo } from 'react';
+import { FieldArray } from 'react-final-form-arrays';
+import { useFormState, Field, useForm } from 'react-final-form';
+import { FormattedMessage } from 'react-intl';
+
+import { Button, Select, Row, Col, Selection } from '@folio/stripes/components';
+import {
+ EditCard,
+ requiredValidator,
+ selectifyRefdata,
+} from '@folio/stripes-erm-components';
+
+import { useKiwtFieldArray } from '@k-int/stripes-kint-components';
+
+import { useSerialsManagementRefdata } from '../../utils';
+
+import ChronologyField from '../ChronologyField';
+import { useLocales } from '../../../hooks';
+
+const [CHRONOLOGY_LABEL_FORMAT] = [
+ 'ChronologyTemplateMetadataRule.TemplateMetadataRuleFormat',
+];
+
+const ChronologyFieldArray = () => {
+ const { values } = useFormState();
+ const { change } = useForm();
+ const { data: locales } = useLocales();
+ const { items, onAddField, onDeleteField } = useKiwtFieldArray(
+ 'templateConfig.chronologyRules'
+ );
+
+ const refdataValues = useSerialsManagementRefdata([CHRONOLOGY_LABEL_FORMAT]);
+
+ const chronologyOptions = useMemo(() => {
+ return selectifyRefdata(refdataValues, CHRONOLOGY_LABEL_FORMAT, 'value');
+ }, [refdataValues]);
+
+ const filterSelectValues = (value, dataOptions) => {
+ const regex = new RegExp(value, 'i');
+
+ return dataOptions.filter(({ label }) => label.search(regex) !== -1);
+ };
+
+ const chronologySelectorOnChange = useCallback(
+ (e, index) => {
+ change(`templateConfig.chronologyRules[${index}]`, {
+ ruleLocale: 'en',
+ templateMetadataRuleFormat: e?.target?.value,
+ ruleFormat: {},
+ });
+ },
+ [change]
+ );
+
+ const renderLabelRule = (chronologyRule, index) => {
+ // Using indexCount to prevent sonarlint from flagging this as an issue
+ const indexKey = index;
+
+ return (
+
+ }
+ header={
+ <>
+
+ >
+ }
+ onDelete={() => onDeleteField(index, chronologyRule)}
+ >
+
+ <>
+
+ {
+ return (
+
+ }
+ meta={meta}
+ onChange={(e) => chronologySelectorOnChange(e, index)}
+ required
+ />
+ );
+ }}
+ validate={requiredValidator}
+ />
+
+
+
+ }
+ name={`templateConfig.chronologyRules[${index}].ruleLocale`}
+ onFilter={filterSelectValues}
+ parse={(v) => v}
+ required
+ validate={requiredValidator}
+ />
+
+ >
+
+ {values?.templateConfig?.chronologyRules[index]
+ ?.templateMetadataRuleFormat && (
+
+ )}
+
+ );
+ };
+
+ return (
+ <>
+
+ {() => items.map((chronologyRule, index) => {
+ return renderLabelRule(chronologyRule, index);
+ })
+ }
+
+ {!values?.templateConfig?.chronologyRules?.length > 0 && (
+ <>
+
+
+
+
+ >
+ )}
+
+ >
+ );
+};
+
+export default ChronologyFieldArray;
diff --git a/src/components/RulesetFormSections/ChronologyFieldArray/ChronologyFieldArray.test.js b/src/components/RulesetFormSections/ChronologyFieldArray/ChronologyFieldArray.test.js
new file mode 100644
index 00000000..fd804fe6
--- /dev/null
+++ b/src/components/RulesetFormSections/ChronologyFieldArray/ChronologyFieldArray.test.js
@@ -0,0 +1,114 @@
+import { waitFor } from '@folio/jest-config-stripes/testing-library/react';
+import {
+ renderWithIntl,
+ TestForm,
+ Button,
+ Selection,
+ Select,
+} from '@folio/stripes-erm-testing';
+
+import { translationsProperties } from '../../../../test/helpers';
+import mockRefdata from '../../../../test/resources/refdata';
+import { locales } from '../../../../test/resources';
+
+import ChronologyFieldArray from './ChronologyFieldArray';
+
+jest.mock('../ChronologyField', () => () => ChronologyField
);
+
+const onSubmit = jest.fn();
+
+const mockLocales = locales;
+
+jest.mock('../../../hooks', () => ({
+ ...jest.requireActual('../../../hooks'),
+ useLocales: () => {
+ return { data: mockLocales };
+ },
+}));
+
+jest.mock('../../utils', () => ({
+ ...jest.requireActual('../../utils'),
+ useSerialsManagementRefdata: () => {
+ return mockRefdata.filter((mr) => {
+ return (
+ mr.desc === 'ChronologyTemplateMetadataRule.TemplateMetadataRuleFormat'
+ );
+ });
+ },
+}));
+
+let renderComponent;
+describe('EnumerationFieldArray', () => {
+ describe('with no values', () => {
+ beforeEach(() => {
+ renderComponent = renderWithIntl(
+
+
+ ,
+ translationsProperties
+ );
+ });
+
+ test('renders the expected empty chronology rules label', async () => {
+ const { getByText } = renderComponent;
+ expect(
+ getByText('No chronology labels for this publication pattern')
+ ).toBeInTheDocument();
+ });
+
+ test('renders the add chronology rule button', async () => {
+ await Button('Add chronology label').exists();
+ });
+
+ describe('clicking the add chronology rule button', () => {
+ beforeEach(async () => {
+ await waitFor(async () => {
+ await Button('Add chronology label').click();
+ });
+ });
+
+ test('renders an chronology index card', async () => {
+ const { getByText } = renderComponent;
+ await waitFor(() => {
+ expect(getByText('Chronology label 1')).toBeInTheDocument();
+ });
+ });
+
+ test('renders the chronology format select field', async () => {
+ await Select('Chronology format*').exists();
+ });
+
+ test('renders the locale select field', async () => {
+ await Selection('Locale*').exists();
+ });
+
+ describe('selecting a chronology format value', () => {
+ beforeEach(async () => {
+ await waitFor(async () => {
+ await Select('Chronology format*').choose('Date');
+ });
+ });
+
+ test('renders a chronology field', () => {
+ const { queryByText } = renderComponent;
+ expect(queryByText('ChronologyField')).toBeInTheDocument();
+ });
+ });
+
+ // TODO Broken test
+ // describe('deleting the chronology label', () => {
+ // beforeEach(async () => {
+ // await waitFor(async () => {
+ // await Button({ id: 'chronology-0-delete-button' }).click();
+ // });
+ // });
+
+ // test('no longer renders an chronology index card', () => {
+ // const { queryByText } = renderComponent;
+ // screen.debug();
+ // expect(queryByText('Chronology label 1')).not.toBeInTheDocument();
+ // });
+ // });
+ });
+ });
+});
diff --git a/src/components/RulesetFormSections/ChronologyFieldArray/index.js b/src/components/RulesetFormSections/ChronologyFieldArray/index.js
new file mode 100644
index 00000000..d780dfab
--- /dev/null
+++ b/src/components/RulesetFormSections/ChronologyFieldArray/index.js
@@ -0,0 +1 @@
+export { default } from './ChronologyFieldArray';
diff --git a/src/components/RulesetFormSections/EnumerationFieldArray/EnumerationFieldArray.js b/src/components/RulesetFormSections/EnumerationFieldArray/EnumerationFieldArray.js
new file mode 100644
index 00000000..139d6397
--- /dev/null
+++ b/src/components/RulesetFormSections/EnumerationFieldArray/EnumerationFieldArray.js
@@ -0,0 +1,147 @@
+import { useCallback, useMemo } from 'react';
+import { FieldArray } from 'react-final-form-arrays';
+import { useFormState, Field, useForm } from 'react-final-form';
+import { FormattedMessage } from 'react-intl';
+
+import { Button, Select, Row, Col } from '@folio/stripes/components';
+import {
+ EditCard,
+ requiredValidator,
+ selectifyRefdata,
+} from '@folio/stripes-erm-components';
+
+import { useKiwtFieldArray } from '@k-int/stripes-kint-components';
+
+import { useSerialsManagementRefdata } from '../../utils';
+
+import EnumerationNumericFieldArray from '../EnumerationNumericFieldArray';
+import EnumerationTextualFieldArray from '../EnumerationTextualFieldArray';
+
+const [ENUMERATION_LABEL_FORMAT] = [
+ 'EnumerationTemplateMetadataRule.TemplateMetadataRuleFormat',
+];
+
+const EnumerationFieldArray = () => {
+ const { values } = useFormState();
+ const { change } = useForm();
+ const { items, onAddField, onDeleteField } = useKiwtFieldArray(
+ 'templateConfig.enumerationRules'
+ );
+
+ const refdataValues = useSerialsManagementRefdata([ENUMERATION_LABEL_FORMAT]);
+
+ const enumerationOptions = useMemo(() => {
+ return selectifyRefdata(refdataValues, ENUMERATION_LABEL_FORMAT, 'value');
+ }, [refdataValues]);
+
+ const enumerationSelectorOnChange = useCallback(
+ (e, index) => {
+ change(`templateConfig.enumerationRules[${index}]`, {
+ templateMetadataRuleFormat: e?.target?.value,
+ ruleFormat: {
+ levels: [{}],
+ },
+ });
+ },
+ [change]
+ );
+
+ const renderLabelRule = (templateConfig, index) => {
+ // Using indexCount to prevent sonarlint from flagging this as an issue
+ const indexKey = index;
+
+ return (
+
+ }
+ header={
+ <>
+
+ >
+ }
+ onDelete={() => onDeleteField(index, templateConfig)}
+ >
+
+
+ {
+ return (
+
+ }
+ meta={meta}
+ onChange={(e) => enumerationSelectorOnChange(e, index)}
+ required
+ />
+ );
+ }}
+ validate={requiredValidator}
+ />
+
+
+ {/*
+ Previously discussed that this could maybe be a switch, as it stands I think its fine
+ If we end up expanding the enumeration options, then its something to reconsider
+ */}
+ {values?.templateConfig?.enumerationRules[index]
+ ?.templateMetadataRuleFormat === 'enumeration_numeric' && (
+ <>
+
+ >
+ )}
+ {values?.templateConfig?.enumerationRules[index]
+ ?.templateMetadataRuleFormat === 'enumeration_textual' && (
+ <>
+
+ >
+ )}
+
+ );
+ };
+
+ return (
+ <>
+
+ {() => items.map((enumerationRule, index) => {
+ return renderLabelRule(enumerationRule, index);
+ })
+ }
+
+ {!values?.templateConfig?.enumerationRules?.length > 0 && (
+ <>
+
+
+
+
+ >
+ )}
+
+ >
+ );
+};
+
+export default EnumerationFieldArray;
diff --git a/src/components/RulesetFormSections/EnumerationFieldArray/EnumerationFieldArray.test.js b/src/components/RulesetFormSections/EnumerationFieldArray/EnumerationFieldArray.test.js
new file mode 100644
index 00000000..e4b8dc69
--- /dev/null
+++ b/src/components/RulesetFormSections/EnumerationFieldArray/EnumerationFieldArray.test.js
@@ -0,0 +1,114 @@
+import { waitFor } from '@folio/jest-config-stripes/testing-library/react';
+import {
+ renderWithIntl,
+ TestForm,
+ Button,
+ Select,
+ IconButton,
+} from '@folio/stripes-erm-testing';
+
+import EnumerationFieldArray from './EnumerationFieldArray';
+import { translationsProperties } from '../../../../test/helpers';
+import mockRefdata from '../../../../test/resources/refdata';
+
+jest.mock('../EnumerationTextualFieldArray', () => () => (
+ EnumerationTextualFieldArray
+));
+jest.mock('../EnumerationNumericFieldArray', () => () => (
+ EnumerationNumericFieldArray
+));
+const onSubmit = jest.fn();
+
+jest.mock('../../utils', () => ({
+ ...jest.requireActual('../../utils'),
+ useSerialsManagementRefdata: () => mockRefdata.filter(
+ (mr) => mr.desc === 'EnumerationTemplateMetadataRule.TemplateMetadataRuleFormat'
+ ),
+}));
+
+let renderComponent;
+describe('EnumerationFieldArray', () => {
+ describe('with no values', () => {
+ beforeEach(() => {
+ renderComponent = renderWithIntl(
+
+
+ ,
+ translationsProperties
+ );
+ });
+
+ test('renders the expected empty enumeration rules label', async () => {
+ const { getByText } = renderComponent;
+ expect(
+ getByText('No enumeration labels for this publication pattern')
+ ).toBeInTheDocument();
+ });
+
+ test('renders the add enumeration rule button', async () => {
+ await Button('Add enumeration label').exists();
+ });
+
+ describe('clicking the add enumeration rule button', () => {
+ beforeEach(async () => {
+ await waitFor(async () => {
+ await Button('Add enumeration label').click();
+ });
+ });
+
+ test('renders an enumeration index card', async () => {
+ const { getByText } = renderComponent;
+ await waitFor(() => {
+ expect(getByText('Enumeration label 1')).toBeInTheDocument();
+ });
+ });
+
+ test('renders the enumeration format select field', async () => {
+ await Select('Enumeration format*').exists();
+ });
+
+ describe('selecting the numeric enumeration format value', () => {
+ beforeEach(async () => {
+ await waitFor(async () => {
+ await Select('Enumeration format*').choose('Numeric');
+ });
+ });
+
+ test('renders an enumeration numeric field array', () => {
+ const { queryByText } = renderComponent;
+ expect(
+ queryByText('EnumerationNumericFieldArray')
+ ).toBeInTheDocument();
+ });
+ });
+
+ describe('selecting the textual enumeration format value', () => {
+ beforeEach(async () => {
+ await waitFor(async () => {
+ await Select('Enumeration format*').choose('Textual');
+ });
+ });
+
+ test('renders an enumeration numeric field array', () => {
+ const { queryByText } = renderComponent;
+ expect(
+ queryByText('EnumerationTextualFieldArray')
+ ).toBeInTheDocument();
+ });
+ });
+
+ describe('deleting the enumeration label', () => {
+ beforeEach(async () => {
+ await waitFor(async () => {
+ await IconButton({ icon: 'trash' }).click(); // Should probs grab a specific one
+ });
+ });
+
+ test('no longer renders an enumeration index card', () => {
+ const { queryByText } = renderComponent;
+ expect(queryByText('Enumeration label 1')).not.toBeInTheDocument();
+ });
+ });
+ });
+ });
+});
diff --git a/src/components/RulesetFormSections/EnumerationFieldArray/index.js b/src/components/RulesetFormSections/EnumerationFieldArray/index.js
new file mode 100644
index 00000000..7786511d
--- /dev/null
+++ b/src/components/RulesetFormSections/EnumerationFieldArray/index.js
@@ -0,0 +1 @@
+export { default } from './EnumerationFieldArray';
diff --git a/src/components/RulesetFormSections/EnumerationNumericField/EnumerationNumericField.test.js b/src/components/RulesetFormSections/EnumerationNumericField/EnumerationNumericField.test.js
index d7a55473..d6b5452e 100644
--- a/src/components/RulesetFormSections/EnumerationNumericField/EnumerationNumericField.test.js
+++ b/src/components/RulesetFormSections/EnumerationNumericField/EnumerationNumericField.test.js
@@ -53,7 +53,7 @@ describe('EnumerationNumericField', () => {
index={0}
items={items}
level={level}
- name="templateConfig.rules[0].ruleType.ruleFormat.levels[0]"
+ name="templateConfig.enumerationRules[0].ruleFormat.levels[0]"
onDeleteField={onDeleteField}
/>
,
diff --git a/src/components/RulesetFormSections/EnumerationNumericFieldArray/EnumerationNumericFieldArray.js b/src/components/RulesetFormSections/EnumerationNumericFieldArray/EnumerationNumericFieldArray.js
index 172fcd0d..075161a3 100644
--- a/src/components/RulesetFormSections/EnumerationNumericFieldArray/EnumerationNumericFieldArray.js
+++ b/src/components/RulesetFormSections/EnumerationNumericFieldArray/EnumerationNumericFieldArray.js
@@ -2,14 +2,59 @@ import PropTypes from 'prop-types';
import { FieldArray } from 'react-final-form-arrays';
import { FormattedMessage } from 'react-intl';
-import { Button, Label, Row, Col } from '@folio/stripes/components';
+
+import {
+ Button,
+ Label,
+ Row,
+ Col,
+ InfoPopover,
+ Layout,
+} from '@folio/stripes/components';
+import { ClipCopy } from '@folio/stripes/smart-components';
import { useKiwtFieldArray } from '@k-int/stripes-kint-components';
import EnumerationNumericField from '../EnumerationNumericField';
-const EnumerationNumericFieldArray = ({ name }) => {
- const { items, onAddField, onDeleteField } = useKiwtFieldArray(`${name}.levels`);
+const EnumerationNumericFieldArray = ({ name, index }) => {
+ const { items, onAddField, onDeleteField } = useKiwtFieldArray(
+ `${name}.levels`
+ );
+
+ const renderTemplateTokensInfo = () => {
+ return (
+
+
+
+
+
+
+
+
+ }
+ />
+ );
+ };
+
+ const renderTokenText = () => {
+ const stringArray = items?.reduce(
+ (a, _l, li) => [...a, `{{enumeration${index + 1}.level${li + 1}}}`],
+ []
+ );
+ return stringArray.join(' ');
+ };
return (
<>
@@ -41,28 +86,36 @@ const EnumerationNumericFieldArray = ({ name }) => {
- {() => items?.map((level, index) => {
+ {() => items?.map((level, levelIndex) => {
return (
);
- })}
+ })
+ }
+
+ {renderTokenText()}
>
);
};
EnumerationNumericFieldArray.propTypes = {
- name: PropTypes.string
+ name: PropTypes.string,
+ index: PropTypes.number,
};
export default EnumerationNumericFieldArray;
diff --git a/src/components/RulesetFormSections/EnumerationTextualFieldArray/EnumerationTextualFieldArray.js b/src/components/RulesetFormSections/EnumerationTextualFieldArray/EnumerationTextualFieldArray.js
index cd9d5170..05043870 100644
--- a/src/components/RulesetFormSections/EnumerationTextualFieldArray/EnumerationTextualFieldArray.js
+++ b/src/components/RulesetFormSections/EnumerationTextualFieldArray/EnumerationTextualFieldArray.js
@@ -6,7 +6,17 @@ import { FieldArray } from 'react-final-form-arrays';
import { FormattedMessage } from 'react-intl';
-import { Button, Label, Row, Col, Select } from '@folio/stripes/components';
+import {
+ Button,
+ Label,
+ Row,
+ Col,
+ Select,
+ InfoPopover,
+ Layout,
+} from '@folio/stripes/components';
+
+import { ClipCopy } from '@folio/stripes/smart-components';
import { requiredValidator } from '@folio/stripes-erm-components';
@@ -15,7 +25,7 @@ import { useKiwtFieldArray } from '@k-int/stripes-kint-components';
import { useSerialsManagementRefdata } from '../../utils';
import EnumerationTextualField from '../EnumerationTextualField';
-const EnumerationTextualFieldArray = ({ name }) => {
+const EnumerationTextualFieldArray = ({ name, index }) => {
const { values } = useFormState();
const { change } = useForm();
const { items, onAddField, onDeleteField } = useKiwtFieldArray(
@@ -28,6 +38,34 @@ const EnumerationTextualFieldArray = ({ name }) => {
return { label: e?.desc, value: e?.desc };
}) ?? [];
+ const tokenText = `{{enumeration${index + 1}}}`;
+
+ const renderTemplateTokensInfo = () => {
+ return (
+
+
+
+
+
+
+
+
+ }
+ />
+ );
+ };
+
return (
<>
@@ -84,10 +122,10 @@ const EnumerationTextualFieldArray = ({ name }) => {
- {() => items?.map((level, index) => {
+ {() => items?.map((level, levelIndex) => {
return (
{
return { label: e?.label, value: e?.label };
}) ?? []
}
- index={index}
+ index={levelIndex}
items={items}
level={level}
- name={`${name}.levels[${index}]`}
+ name={`${name}.levels[${levelIndex}]`}
onDeleteField={onDeleteField}
/>
);
@@ -110,12 +148,19 @@ const EnumerationTextualFieldArray = ({ name }) => {
+
+ {tokenText}
>
);
};
EnumerationTextualFieldArray.propTypes = {
name: PropTypes.string,
+ index: PropTypes.number,
};
export default EnumerationTextualFieldArray;
diff --git a/src/components/RulesetFormSections/LabelFieldArray/LabelFieldArray.js b/src/components/RulesetFormSections/LabelFieldArray/LabelFieldArray.js
deleted file mode 100644
index 23d37a26..00000000
--- a/src/components/RulesetFormSections/LabelFieldArray/LabelFieldArray.js
+++ /dev/null
@@ -1,388 +0,0 @@
-import { useState, useEffect } from 'react';
-import { FieldArray } from 'react-final-form-arrays';
-import { useFormState, Field, useForm } from 'react-final-form';
-import { FormattedMessage } from 'react-intl';
-import { ClipCopy } from '@folio/stripes/smart-components';
-
-import {
- Button,
- Select,
- Row,
- Col,
- TextArea,
- Selection,
- InfoPopover,
- Layout,
- Label,
-} from '@folio/stripes/components';
-import {
- EditCard,
- requiredValidator,
- selectifyRefdata,
-} from '@folio/stripes-erm-components';
-
-import { useKiwtFieldArray } from '@k-int/stripes-kint-components';
-
-import { useSerialsManagementRefdata } from '../../utils';
-
-import ChronologyField from '../ChronologyField';
-import EnumerationNumericFieldArray from '../EnumerationNumericFieldArray';
-import EnumerationTextualFieldArray from '../EnumerationTextualFieldArray';
-import { useLocales } from '../../../hooks';
-
-const [RULE_TYPE, CHRONOLOGY_LABEL_FORMAT, ENUMERATION_LABEL_FORMAT] = [
- 'TemplateMetadataRule.TemplateMetadataRuleType',
- 'ChronologyTemplateMetadataRule.TemplateMetadataRuleFormat',
- 'EnumerationTemplateMetadataRule.TemplateMetadataRuleFormat',
-];
-
-const LabelFieldArray = () => {
- const { values } = useFormState();
- const { change } = useForm();
- const { data: locales } = useLocales();
- const { items, onAddField, onDeleteField } = useKiwtFieldArray(
- 'templateConfig.rules'
- );
-
- const [ruleLabelValues, setRuleLabelValues] = useState([]);
- const [enumerationValues, setEnumerationValues] = useState([]);
-
- useEffect(() => {
- let chronologyCount = 0;
- let enumerationCount = 0;
-
- const ruleLabelArray = values?.templateConfig?.rules?.map((r) => {
- if (r?.templateMetadataRuleType === 'chronology') {
- chronologyCount++;
- return `: chronology ${chronologyCount}`;
- } else if (r?.templateMetadataRuleType === 'enumeration') {
- enumerationCount++;
- return `: enumeration ${enumerationCount}`;
- } else {
- return '';
- }
- });
-
- let enumerationTokenCount = 0;
- const enumerationTokenArray = values?.templateConfig?.rules?.map((e) => {
- if (e?.ruleType?.templateMetadataRuleFormat === 'enumeration_textual') {
- enumerationTokenCount++;
- return `{{enumeration${enumerationTokenCount}}}`;
- } else if (
- e?.ruleType?.templateMetadataRuleFormat === 'enumeration_numeric'
- ) {
- enumerationTokenCount++;
- const stringArray = e?.ruleType?.ruleFormat?.levels?.reduce(
- (a, _l, li) => [
- ...a,
- `{{enumeration${enumerationTokenCount}.level${li + 1}}}`,
- ],
- []
- );
- return stringArray.join(' ');
- } else {
- return '';
- }
- });
- setRuleLabelValues(ruleLabelArray);
- setEnumerationValues(enumerationTokenArray);
- }, [values]);
-
- const refdataValues = useSerialsManagementRefdata([
- RULE_TYPE,
- CHRONOLOGY_LABEL_FORMAT,
- ENUMERATION_LABEL_FORMAT,
- ]);
-
- const filterSelectValues = (value, dataOptions) => {
- const regex = new RegExp(value, 'i');
-
- return dataOptions.filter(({ label }) => label.search(regex) !== -1);
- };
-
- const renderTemplateInfo = () => {
- return (
-
-
-
-
-
-
-
-
- }
- />
- );
- };
-
- const renderTemplateTokensInfo = () => {
- return (
-
-
-
-
-
-
-
-
- }
- />
- );
- };
- const renderLabelRule = (templateConfig, index) => {
- // Using indexCount to prevent sonarlint from flagging this as an issue
- const indexKey = index;
-
- return (
-
- }
- header={
- <>
-
- {ruleLabelValues[index]}
- >
- }
- onDelete={() => onDeleteField(index, templateConfig)}
- >
-
-
- (
-
- }
- meta={meta}
- onChange={(e) => {
- change(`templateConfig.rules[${index}]`, {
- templateMetadataRuleType: e?.target?.value,
- });
- if (e?.target?.value === 'chronology') {
- change(`templateConfig.rules[${index}].ruleType`, {
- ruleLocale: 'en',
- });
- } else {
- change(
- `templateConfig.rules[${index}].ruleType`,
- undefined
- );
- }
- }}
- required
- />
- )}
- validate={requiredValidator}
- />
-
- {values?.templateConfig?.rules[index]?.templateMetadataRuleType && (
- <>
-
- {
- let selectedDataOptions = [];
- if (
- values?.templateConfig?.rules[index]
- ?.templateMetadataRuleType === 'chronology'
- ) {
- selectedDataOptions = selectifyRefdata(
- refdataValues,
- CHRONOLOGY_LABEL_FORMAT,
- 'value'
- );
- } else if (
- values?.templateConfig?.rules[index]
- ?.templateMetadataRuleType === 'enumeration'
- ) {
- selectedDataOptions = selectifyRefdata(
- refdataValues,
- ENUMERATION_LABEL_FORMAT,
- 'value'
- );
- }
- return (
-
- }
- meta={meta}
- onChange={(e) => {
- change(
- `templateConfig.rules[${index}].ruleType.templateMetadataRuleFormat`,
- e?.target?.value
- );
- change(
- `templateConfig.rules[${index}].ruleType.ruleFormat`,
- undefined
- );
- if (
- values?.templateConfig?.rules[index]
- ?.templateMetadataRuleType === 'enumeration'
- ) {
- change(
- `templateConfig.rules[${index}].ruleType.ruleFormat.levels`,
- [{}]
- );
- }
- }}
- required
- />
- );
- }}
- validate={requiredValidator}
- />
-
- {values?.templateConfig?.rules[index]
- ?.templateMetadataRuleType === 'chronology' && (
-
-
- }
- name={`templateConfig.rules[${index}].ruleType.ruleLocale`}
- onFilter={filterSelectValues}
- parse={(v) => v}
- required
- validate={requiredValidator}
- />
-
- )}
- >
- )}
-
- {values?.templateConfig?.rules[index]?.templateMetadataRuleType ===
- 'chronology' &&
- values?.templateConfig?.rules[index]?.ruleType
- ?.templateMetadataRuleFormat && (
-
- )}
- {values?.templateConfig?.rules[index]?.templateMetadataRuleType ===
- 'enumeration' &&
- values?.templateConfig?.rules[index]?.ruleType
- ?.templateMetadataRuleFormat === 'enumeration_numeric' && (
- <>
-
-
- {enumerationValues[index]}
- >
- )}
- {values?.templateConfig?.rules[index]?.templateMetadataRuleType ===
- 'enumeration' &&
- values?.templateConfig?.rules[index]?.ruleType
- ?.templateMetadataRuleFormat === 'enumeration_textual' && (
- <>
-
-
- {enumerationValues[index]}
- >
- )}
-
- );
- };
-
- return (
- <>
-
- {() => items.map((templateConfig, index) => {
- return renderLabelRule(templateConfig, index);
- })
- }
-
- {!values?.templateConfig && (
- <>
-
-
-
-
- >
- )}
-
-
-
-
-
- {renderTemplateInfo()}
- >
- }
- name="templateConfig.templateString"
- required
- validate={requiredValidator}
- />
-
-
- >
- );
-};
-
-export default LabelFieldArray;
diff --git a/src/components/RulesetFormSections/LabelFieldArray/LabelFieldArray.test.js b/src/components/RulesetFormSections/LabelFieldArray/LabelFieldArray.test.js
deleted file mode 100644
index 2bbb9a69..00000000
--- a/src/components/RulesetFormSections/LabelFieldArray/LabelFieldArray.test.js
+++ /dev/null
@@ -1,438 +0,0 @@
-import { waitFor } from '@folio/jest-config-stripes/testing-library/react';
-import {
- renderWithIntl,
- TestForm,
- Button,
- Select,
- TextArea,
-} from '@folio/stripes-erm-testing';
-
-import mockRefdata from '../../../../test/resources/refdata';
-import { locales as mockLocales } from '../../../../test/resources';
-import LabelFieldArray from './LabelFieldArray';
-import { translationsProperties } from '../../../../test/helpers';
-
-jest.mock('react-final-form', () => ({
- ...jest.requireActual('react-final-form'),
- useFormContext: () => ({
- handleSubmit: () => jest.fn(),
- getValues: () => jest.fn(),
- }),
-}));
-
-jest.mock('../../utils', () => ({
- ...jest.requireActual('../../utils'),
- useSerialsManagementRefdata: () => mockRefdata,
- useLocales: () => mockRefdata,
-}));
-
-jest.mock('../../../hooks', () => ({
- ...jest.requireActual('../../../hooks'),
- useLocales: () => ({ isLoading: false, data: mockLocales }),
-}));
-
-jest.mock('../ChronologyField', () => () => ChronologyField
);
-jest.mock('../EnumerationNumericFieldArray', () => () => (
- EnumerationNumericFieldArray
-));
-
-jest.mock('../EnumerationTextualFieldArray', () => () => (
- EnumerationTextualFieldArray
-));
-
-jest.mock('../ChronologyField', () => () => ChronologyField
);
-const onSubmit = jest.fn();
-
-const numericProps = {
- rulesetStatus: {
- value: 'active',
- },
- templateConfig: {
- templateString: 'test',
- rules: [
- {
- templateMetadataRuleType: 'enumeration',
- ruleType: {
- templateMetadataRuleFormat: 'enumeration_numeric',
- ruleFormat: {
- levels: [
- {
- units: '1',
- format: {
- value: 'number',
- },
- sequence: {
- value: 'continuous',
- },
- internalNote: 'test note',
- },
- ],
- },
- },
- },
- ],
- },
-};
-
-const textualProps = {
- rulesetStatus: {
- value: 'active',
- },
- templateConfig: {
- templateString: 'test',
- rules: [
- {
- templateMetadataRuleType: 'enumeration',
- ruleType: {
- templateMetadataRuleFormat: 'enumeration_textual',
- ruleFormat: {
- levels: [
- {
- units: '1',
- value: 'Friday',
- internalNote: 'note test',
- },
- ],
- refdataCategory: 'Global.Weekday',
- },
- },
- },
- ],
- },
-};
-
-const chronologyProps = {
- rulesetStatus: {
- value: 'active',
- },
- templateConfig: {
- templateString: 'test',
- rules: [
- {
- templateMetadataRuleType: 'chronology',
- ruleType: {
- templateMetadataRuleFormat: 'chronology_date',
- ruleFormat: {
- weekdayFormat: {
- value: 'full_lower',
- },
- monthDayFormat: {
- value: 'ordinal',
- },
- monthFormat: {
- value: 'full',
- },
- yearFormat: {
- value: 'full',
- },
- },
- },
- },
- ],
- },
-};
-
-let renderComponent;
-describe('LabelFieldArray', () => {
- describe('without initial values', () => {
- beforeEach(() => {
- renderComponent = renderWithIntl(
-
-
- ,
- translationsProperties
- );
- });
-
- test('renders the expected Template label', async () => {
- const { getByText } = renderComponent;
- expect(getByText('Label template')).toBeInTheDocument();
- });
-
- test('renders the expected empty label text', async () => {
- const { getByText } = renderComponent;
- expect(
- getByText('No labels for this publication pattern')
- ).toBeInTheDocument();
- });
-
- test('renders the Add label button', async () => {
- await Button('Add label').exists();
- });
-
- test('not renders ChronologyField', () => {
- const { queryByText } = renderComponent;
- expect(queryByText('ChronologyField')).not.toBeInTheDocument();
- });
-
- test('not renders the EnumerationNumericFieldArray', () => {
- const { queryByText } = renderComponent;
- expect(
- queryByText('EnumerationNumericFieldArray')
- ).not.toBeInTheDocument();
- });
-
- test(' not renders EnumerationTextualFieldArray', () => {
- const { queryByText } = renderComponent;
- expect(
- queryByText('EnumerationTextualFieldArray')
- ).not.toBeInTheDocument();
- });
-
- describe('Adding label', () => {
- beforeEach(async () => {
- const { getByText } = renderComponent;
- await waitFor(async () => {
- await Button('Add label').click();
- });
-
- // Ensure the template has been added in the beforeEach is a way to shortcut the waits in each test
- await waitFor(() => {
- expect(getByText('Label template')).toBeInTheDocument();
- });
- });
-
- // TODO test names should be clearer about what they're testing
- test('renders the expected Template label', async () => {
- const { getByText } = renderComponent;
- // (follows from above) otherwise you need a waitFor at this level
- // There is no "right" answer here, but this way makes this test redundant and repeated
- // and removing it would make the test case implicit, which isn't necessarily the best idea always
- // await waitFor(() => {
- expect(getByText('Label template')).toBeInTheDocument();
- // });
- });
-
- test('renders the expected Template label', async () => {
- const { getByText } = renderComponent;
- expect(getByText('Remove label 1')).toBeInTheDocument();
- });
-
- test('renders a label card', () => {
- const { getByText } = renderComponent;
- expect(getByText('Label 1')).toBeInTheDocument();
- });
-
- test('renders a label style ', () => {
- const { getByText } = renderComponent;
- expect(getByText('Label style')).toBeInTheDocument();
- });
-
- test('renders a Select for label style', async () => {
- await Select('Label style*').exists();
- });
-
- test('renders the EditCard by id', () => {
- const { getByTestId } = renderComponent;
- expect(getByTestId('editCard')).toBeInTheDocument();
- });
-
- describe('testing label style', () => {
- test('renders the Label style dropdown', async () => {
- await Select('Label style*').exists();
- });
-
- // There's many ways to do this, this way is "choose and check it got chosen"
- describe.each(['Chronology', 'Enumeration'])(
- 'choosing %s',
- (option) => {
- beforeEach(async () => {
- await waitFor(async () => {
- await Select('Label style*').choose(option);
- });
- });
-
- test('label style has correct value', async () => {
- await Select('Label style*').has({ checkedOptionText: option });
- });
- }
- );
- });
- });
- });
-
- describe('with initial values', () => {
- beforeEach(() => {
- renderComponent = renderWithIntl(
-
-
- ,
- translationsProperties
- );
- });
-
- // TODO Async only needs to be applied to those tests acting asynchronously
- test('renders the expected Template label', async () => {
- const { getByText } = renderComponent;
- expect(getByText('Label template')).toBeInTheDocument();
- });
-
- test('renders the Add label button', async () => {
- await Button('Add label').exists();
- });
-
- test('not renders ChronologyField', () => {
- const { queryByText } = renderComponent;
- expect(queryByText('ChronologyField')).not.toBeInTheDocument();
- });
-
- test('not renders the EnumerationNumericFieldArray', () => {
- const { queryByText } = renderComponent;
- expect(queryByText('EnumerationNumericFieldArray')).toBeInTheDocument();
- });
-
- test(' not renders EnumerationTextualFieldArray', () => {
- const { queryByText } = renderComponent;
- expect(
- queryByText('EnumerationTextualFieldArray')
- ).not.toBeInTheDocument();
- });
-
- describe('Adding label', () => {
- beforeEach(async () => {
- await waitFor(async () => {
- await Button('Add label').click();
- });
- });
-
- test('renders the expected Template with correct value', async () => {
- await TextArea('Label template*').has({ value: 'test' });
- });
-
- test('renders a label card', () => {
- const { getByText } = renderComponent;
- expect(getByText('Label 1: enumeration 1')).toBeInTheDocument();
- });
-
- test('renders the expected Template label', async () => {
- const { getByText } = renderComponent;
- expect(getByText('Remove label 1')).toBeInTheDocument();
- });
-
- test('renders the expected Template tokens label', async () => {
- const { getByText } = renderComponent;
- expect(getByText('Template tokens')).toBeInTheDocument();
- });
-
- test('renders the expected label', async () => {
- const { getByText } = renderComponent;
- expect(getByText('{{enumeration1.level1}}')).toBeInTheDocument();
- });
-
- test('renders a Select for label style', async () => {
- await Select('Label style*').exists();
- });
-
- describe('testing enumeration format', () => {
- test('renders the Enumeration format dropdown', async () => {
- await Select('Enumeration format*').exists();
- });
-
- // There's many ways to do this, this way is "choose and check it got chosen"
- describe.each(['Numeric', 'Textual'])(
- 'choosing %s',
- (option) => {
- beforeEach(async () => {
- await waitFor(async () => {
- await Select('Enumeration format*').choose(option);
- });
- });
-
- test('enumeration format has correct value', async () => {
- await Select('Enumeration format*').has({
- checkedOptionText: option,
- });
- });
- }
- );
- });
-
- test('renders the EnumerationNumericFieldArray', () => {
- const { queryByText } = renderComponent;
- expect(queryByText('EnumerationNumericFieldArray')).toBeInTheDocument();
- });
- });
- });
-
- describe('with initial values (textual)', () => {
- beforeEach(() => {
- renderComponent = renderWithIntl(
-
-
- ,
- translationsProperties
- );
- });
-
- // TODO Repeating this logic isn't the best... should be trying to not have to repeat tests wherever possible
- // I'd like to see the repeated tests EXACT like this one to be covered by describe.each, and the type of testing covered by a utility function.
- // Perhaps "testSelectOptions" as a utility function allowing you to also plug in any follow up tests...
- // That sort of utility could live in stripes-erm-testing and be very handy for speeding up test writing.
- describe('testing enumeration format', () => {
- test('renders the Enumeration format dropdown', async () => {
- await Select('Enumeration format*').exists();
- });
-
- describe.each(['Numeric', 'Textual'])(
- 'choosing %s',
- (option) => {
- beforeEach(async () => {
- await waitFor(async () => {
- await Select('Enumeration format*').choose(option);
- });
- });
-
- test('enumeration format has correct value', async () => {
- await Select('Enumeration format*').has({
- checkedOptionText: option,
- });
- });
- }
- );
- });
-
- test('renders EnumerationTextualFieldArray', () => {
- const { queryByText } = renderComponent;
- expect(queryByText('EnumerationTextualFieldArray')).toBeInTheDocument();
- });
- });
-
- describe('with initial values (textual)', () => {
- beforeEach(() => {
- renderComponent = renderWithIntl(
-
-
- ,
- translationsProperties
- );
- });
-
- describe('testing chronology format', () => {
- test('renders the Chronology format dropdown', async () => {
- await Select('Chronology format*').exists();
- });
-
- describe.each(['Date', 'Month', 'Year'])(
- 'choosing %s',
- (option) => {
- beforeEach(async () => {
- await waitFor(async () => {
- await Select('Chronology format*').choose(option);
- });
- });
-
- test('Chronology format has correct value', async () => {
- await Select('Chronology format*').has({
- checkedOptionText: option,
- });
- });
- }
- );
- });
-
- test('renders ChronologyField', () => {
- const { queryByText } = renderComponent;
- expect(queryByText('ChronologyField')).toBeInTheDocument();
- });
- });
-});
diff --git a/src/components/RulesetFormSections/LabelFieldArray/index.js b/src/components/RulesetFormSections/LabelFieldArray/index.js
deleted file mode 100644
index e73fb6a4..00000000
--- a/src/components/RulesetFormSections/LabelFieldArray/index.js
+++ /dev/null
@@ -1 +0,0 @@
-export { default } from './LabelFieldArray';
diff --git a/src/components/RulesetFormSections/TemplateStringField/TemplateStringField.js b/src/components/RulesetFormSections/TemplateStringField/TemplateStringField.js
new file mode 100644
index 00000000..931aec95
--- /dev/null
+++ b/src/components/RulesetFormSections/TemplateStringField/TemplateStringField.js
@@ -0,0 +1,61 @@
+import { Field } from 'react-final-form';
+import { FormattedMessage } from 'react-intl';
+
+import {
+ Button,
+ Row,
+ Col,
+ TextArea,
+ InfoPopover,
+ Layout,
+} from '@folio/stripes/components';
+import { requiredValidator } from '@folio/stripes-erm-components';
+
+const TemplateStringField = () => {
+ const renderTemplateInfo = () => {
+ return (
+
+
+
+
+
+
+
+
+ }
+ />
+ );
+ };
+
+ return (
+
+
+
+
+ {renderTemplateInfo()}
+ >
+ }
+ name="templateConfig.templateString"
+ required
+ validate={requiredValidator}
+ />
+
+
+ );
+};
+
+export default TemplateStringField;
diff --git a/src/components/RulesetFormSections/TemplateStringField/index.js b/src/components/RulesetFormSections/TemplateStringField/index.js
new file mode 100644
index 00000000..524c2ebf
--- /dev/null
+++ b/src/components/RulesetFormSections/TemplateStringField/index.js
@@ -0,0 +1 @@
+export { default } from './TemplateStringField';
diff --git a/src/components/RulesetFormSections/index.js b/src/components/RulesetFormSections/index.js
index e4ff6ac3..32b1bc2e 100644
--- a/src/components/RulesetFormSections/index.js
+++ b/src/components/RulesetFormSections/index.js
@@ -1,4 +1,5 @@
export { default as RulesetInfoForm } from './RulesetInfoForm';
+export { default as ModelRulesetSelection } from './ModelRulesetSelection';
export { default as PatternTimePeriodForm } from './PatternTimePeriodForm';
export { default as IssuePublicationFieldArray } from './IssuePublicationFieldArray';
export { default as IssuePublicationField } from './IssuePublicationField';
@@ -6,10 +7,12 @@ export { default as OmissionField } from './OmissionField';
export { default as OmissionFieldArray } from './OmissionFieldArray';
export { default as CombinationField } from './CombinationField';
export { default as CombinationFieldArray } from './CombinationFieldArray';
-export { default as LabelFieldArray } from './LabelFieldArray';
-export { default as ModelRulesetSelection } from './ModelRulesetSelection';
+export { default as ChronologyFieldArray } from './ChronologyFieldArray';
export { default as ChronologyField } from './ChronologyField';
+export { default as EnumerationFieldArray } from './EnumerationFieldArray';
export { default as EnumerationNumericFieldArray } from './EnumerationNumericFieldArray';
export { default as EnumerationNumericField } from './EnumerationNumericField';
export { default as EnumerationTextualFieldArray } from './EnumerationTextualFieldArray';
export { default as EnumerationTextualField } from './EnumerationTextualField';
+export { default as TemplateStringField } from './TemplateStringField';
+
diff --git a/src/components/RulesetSections/ChronologyLabels/ChronologyLabels.js b/src/components/RulesetSections/ChronologyLabels/ChronologyLabels.js
index d9a87efc..32c4d7fe 100644
--- a/src/components/RulesetSections/ChronologyLabels/ChronologyLabels.js
+++ b/src/components/RulesetSections/ChronologyLabels/ChronologyLabels.js
@@ -18,11 +18,9 @@ const proptypes = {
const ChronologyLabels = ({ ruleset }) => {
const intl = useIntl();
- // The filterning of templateConfig rules will be irrelevant when enumeration and chronology have been seperated
+
const sortedLabels = getSortedItems(
- ruleset?.templateConfig?.rules?.filter(
- (e) => e?.templateMetadataRuleType?.value === 'chronology'
- ),
+ ruleset?.templateConfig?.chronologyRules,
null,
{
column: 'index',
@@ -36,12 +34,12 @@ const ChronologyLabels = ({ ruleset }) => {
.formatMessage({ id: 'ui-serials-management.ruleset.chronology' })
?.concat(' ', e?.index + 1);
},
- chronologyFormat: (e) => e?.ruleType?.templateMetadataRuleFormat?.label,
- weekdayFormat: (e) => e?.ruleType?.ruleFormat?.weekdayFormat?.label,
- monthdayFormat: (e) => e?.ruleType?.ruleFormat?.monthDayFormat?.label,
- monthFormat: (e) => e?.ruleType?.ruleFormat?.monthFormat?.label,
- yearFormat: (e) => e?.ruleType?.ruleFormat?.yearFormat?.label,
- locale: (e) => e?.ruleType?.ruleLocale,
+ chronologyFormat: (e) => e?.templateMetadataRuleFormat?.label,
+ weekdayFormat: (e) => e?.ruleFormat?.weekdayFormat?.label,
+ monthdayFormat: (e) => e?.ruleFormat?.monthDayFormat?.label,
+ monthFormat: (e) => e?.ruleFormat?.monthFormat?.label,
+ yearFormat: (e) => e?.ruleFormat?.yearFormat?.label,
+ locale: (e) => e?.ruleLocale,
};
const renderBadge = () => {
@@ -84,6 +82,7 @@ const ChronologyLabels = ({ ruleset }) => {
}}
contentData={sortedLabels}
formatter={formatter}
+ id="chronology-labels-list"
interactive={false}
visibleColumns={[
'label',
diff --git a/src/components/RulesetSections/ChronologyLabels/ChronologyLabels.test.js b/src/components/RulesetSections/ChronologyLabels/ChronologyLabels.test.js
new file mode 100644
index 00000000..56c90911
--- /dev/null
+++ b/src/components/RulesetSections/ChronologyLabels/ChronologyLabels.test.js
@@ -0,0 +1,83 @@
+import {
+ renderWithIntl,
+ Accordion,
+ MultiColumnList,
+ MultiColumnListCell,
+} from '@folio/stripes-erm-testing';
+import { MemoryRouter } from 'react-router-dom';
+import { translationsProperties } from '../../../../test/helpers';
+import ChronologyLabels from './ChronologyLabels';
+
+import ruleset from '../../../../test/resources/rulesets/ruleset';
+import { chronologyDate } from '../../../../test/resources/rulesetResources/chronologyRules';
+
+describe('ChronologyLabels', () => {
+ describe('with a ruleset', () => {
+ beforeEach(() => {
+ renderWithIntl(
+
+ {/* Here w're importing the ruleset object from resource but overwriting the chronology rules */}
+
+ ,
+ translationsProperties
+ );
+ });
+
+ test('renders the Accordion', async () => {
+ await Accordion('Chronology labels').exists();
+ });
+
+ test('renders the MCL', async () => {
+ await MultiColumnList('chronology-labels-list').exists();
+ });
+
+ test('renders expected column count', async () => {
+ await MultiColumnList({ columnCount: 7 }).exists();
+ });
+
+ test('renders expected columns', async () => {
+ await MultiColumnList({
+ columns: [
+ 'Labelling',
+ 'Chronology format',
+ 'Weekday format',
+ 'Month day format',
+ 'Month format',
+ 'Year format',
+ 'Locale',
+ ],
+ }).exists();
+ });
+
+ test('renders expected row count', async () => {
+ await MultiColumnList({
+ rowCount: ruleset.templateConfig.chronologyRules.length,
+ }).exists();
+ });
+
+ test.each([
+ { propertyName: 'Chronology idex', columnIndex: 0, content: 'Chronology 1' },
+ { propertyName: 'Chronology format', columnIndex: 1, content: 'Date' },
+ { propertyName: 'Weekday format', columnIndex: 2, content: 'Full Lower' },
+ { propertyName: 'Month day format', columnIndex: 3, content: 'Number' },
+ { propertyName: 'Month format', columnIndex: 4, content: 'Full' },
+ { propertyName: 'Year format', columnIndex: 5, content: 'Full' },
+ { propertyName: 'Locale', columnIndex: 6, content: 'en' },
+ ])(
+ 'renders expected $propertyName in the the first row, column index $columnIndex',
+ async ({ columnIndex, content }) => {
+ await MultiColumnListCell({ row: 0, columnIndex }).has({
+ content,
+ });
+ }
+ );
+ });
+});
diff --git a/src/components/RulesetSections/EnumerationLabels/EnumerationLabels.js b/src/components/RulesetSections/EnumerationLabels/EnumerationLabels.js
index 73c76c60..917e6cae 100644
--- a/src/components/RulesetSections/EnumerationLabels/EnumerationLabels.js
+++ b/src/components/RulesetSections/EnumerationLabels/EnumerationLabels.js
@@ -19,11 +19,9 @@ const proptypes = {
const EnumerationLabels = ({ ruleset }) => {
const intl = useIntl();
- // The filterning of templateConfig rules will be irrelevant when enumeration and chronology have been seperated
+
const sortedLabels = getSortedItems(
- ruleset?.templateConfig?.rules?.filter(
- (e) => e?.templateMetadataRuleType?.value === 'enumeration'
- ),
+ ruleset?.templateConfig?.enumerationRules,
null,
{
column: 'index',
@@ -36,9 +34,7 @@ const EnumerationLabels = ({ ruleset }) => {
);
};
@@ -70,6 +66,7 @@ const EnumerationLabels = ({ ruleset }) => {
}}
contentData={ruleFormat?.levels}
formatter={formatter}
+ id="enumeration-numeric-labels-list"
interactive={false}
visibleColumns={[
'level',
@@ -105,6 +102,7 @@ const EnumerationLabels = ({ ruleset }) => {
}}
contentData={ruleFormat?.levels}
formatter={formatter}
+ id="enumeration-textual-labels-list"
interactive={false}
visibleColumns={['order', 'issues', 'labelText', 'internalNote']}
/>
@@ -127,14 +125,14 @@ const EnumerationLabels = ({ ruleset }) => {
return (
<>
- {rule?.ruleType?.templateMetadataRuleFormat?.value ===
+ {rule?.templateMetadataRuleFormat?.value ===
'enumeration_numeric' ? (
<>
{renderEnumerationLabelName(rule, ruleIndex)}
- {renderEnumerationNumericMCL(rule?.ruleType?.ruleFormat)}
+ {renderEnumerationNumericMCL(rule?.ruleFormat)}
>
) : (
@@ -143,7 +141,7 @@ const EnumerationLabels = ({ ruleset }) => {
{renderEnumerationLabelName(rule, ruleIndex)}
- {renderEnumerationTextualMCL(rule?.ruleType?.ruleFormat)}
+ {renderEnumerationTextualMCL(rule?.ruleFormat)}
>
)}
diff --git a/src/components/RulesetSections/EnumerationLabels/EnumerationLabels.test.js b/src/components/RulesetSections/EnumerationLabels/EnumerationLabels.test.js
new file mode 100644
index 00000000..cfd9cf0a
--- /dev/null
+++ b/src/components/RulesetSections/EnumerationLabels/EnumerationLabels.test.js
@@ -0,0 +1,154 @@
+import {
+ renderWithIntl,
+ Accordion,
+ MultiColumnList,
+ MultiColumnListCell,
+} from '@folio/stripes-erm-testing';
+import { MemoryRouter } from 'react-router-dom';
+import { translationsProperties } from '../../../../test/helpers';
+import EnumerationLabels from './EnumerationLabels';
+
+import ruleset from '../../../../test/resources/rulesets/ruleset';
+import {
+ enumerationNumeric,
+ enumerationTextual,
+} from '../../../../test/resources/rulesetResources/enumerationRules';
+
+let renderComponent;
+
+describe('EnumerationLabels', () => {
+ describe('with a ruleset with an enumeration numeric rule', () => {
+ beforeEach(() => {
+ renderComponent = renderWithIntl(
+
+ {/* Here w're importing the ruleset object from resource but overwriting the enumeration rules */}
+
+ ,
+ translationsProperties
+ );
+ });
+
+ test('renders the Accordion', async () => {
+ await Accordion('Enumeration labels').exists();
+ });
+
+ test('renders the enumeration label name', () => {
+ const { getByText } = renderComponent;
+ expect(getByText('Enumeration 1: Numeric')).toBeInTheDocument();
+ });
+
+ test('renders the MCL', async () => {
+ await MultiColumnList('enumeration-numeric-labels-list').exists();
+ });
+
+ test('renders expected column count', async () => {
+ await MultiColumnList({ columnCount: 5 }).exists();
+ });
+
+ test('renders expected columns', async () => {
+ await MultiColumnList({
+ columns: [
+ 'Level',
+ 'No. of units',
+ 'Format',
+ 'Sequence',
+ 'Internal note',
+ ],
+ }).exists();
+ });
+
+ test('renders expected row count', async () => {
+ await MultiColumnList({
+ rowCount:
+ ruleset.templateConfig.enumerationRules[0].ruleFormat.levels.length,
+ }).exists();
+ });
+
+ test.each([
+ { propertyName: 'Level', columnIndex: 0, content: '1' },
+ { propertyName: 'No. of units', columnIndex: 1, content: '1' },
+ { propertyName: 'Format', columnIndex: 2, content: 'Number' },
+ { propertyName: 'Sequence', columnIndex: 3, content: 'Continuous' },
+ { propertyName: 'Internal note', columnIndex: 4, content: 'Level 1' },
+ ])(
+ 'renders expected $propertyName in the the first row, column index $columnIndex',
+ async ({ columnIndex, content }) => {
+ await MultiColumnListCell({ row: 0, columnIndex }).has({
+ content,
+ });
+ }
+ );
+ });
+
+ describe('with a ruleset with an enumeration textual rule', () => {
+ beforeEach(() => {
+ renderComponent = renderWithIntl(
+
+ {/* Here w're importing the ruleset object from resource but overwriting the enumeration rules */}
+
+ ,
+ translationsProperties
+ );
+ });
+
+ test('renders the Accordion', async () => {
+ await Accordion('Enumeration labels').exists();
+ });
+
+ test('renders the enumeration label name', () => {
+ const { getByText } = renderComponent;
+ expect(getByText('Enumeration 1: Textual')).toBeInTheDocument();
+ });
+
+ test('renders the MCL', async () => {
+ await MultiColumnList('enumeration-textual-labels-list').exists();
+ });
+
+ test('renders expected column count', async () => {
+ await MultiColumnList({ columnCount: 4 }).exists();
+ });
+
+ test('renders expected columns', async () => {
+ await MultiColumnList({
+ columns: ['Order', 'No. of issues', 'Label text', 'Internal note'],
+ }).exists();
+ });
+
+ test('renders expected row count', async () => {
+ await MultiColumnList({
+ rowCount:
+ ruleset.templateConfig.enumerationRules[0].ruleFormat.levels.length,
+ }).exists();
+ });
+
+ test.each([
+ { propertyName: 'Order', columnIndex: 0, content: '1' },
+ { propertyName: 'Issues', columnIndex: 1, content: '1' },
+ { propertyName: 'Label text', columnIndex: 2, content: 'Friday' },
+ { propertyName: 'Internal note', columnIndex: 3, content: 'Order 1' },
+ ])(
+ 'renders expected $propertyName in the the first row, column index $columnIndex',
+ async ({ columnIndex, content }) => {
+ await MultiColumnListCell({ row: 0, columnIndex }).has({
+ content,
+ });
+ }
+ );
+ });
+});
diff --git a/src/components/utils/getRulesetFormValues.js b/src/components/utils/getRulesetFormValues.js
index 72d0dc07..28cbe81d 100644
--- a/src/components/utils/getRulesetFormValues.js
+++ b/src/components/utils/getRulesetFormValues.js
@@ -29,13 +29,18 @@ const getRulesetFormValues = (ruleset) => {
}),
templateConfig: {
templateString: ruleset?.templateConfig?.templateString,
- rules: ruleset?.templateConfig?.rules?.map((rule) => ({
- templateMetadataRuleType: rule?.templateMetadataRuleType?.value,
- ruleType: {
- ...rule?.ruleType,
- templateMetadataRuleFormat: rule?.ruleType?.templateMetadataRuleFormat?.value,
- },
- })),
+ chronologyRules: ruleset?.templateConfig?.chronologyRules?.map(
+ (rule) => ({
+ ...rule,
+ templateMetadataRuleFormat: rule?.templateMetadataRuleFormat?.value,
+ })
+ ),
+ enumerationRules: ruleset?.templateConfig?.enumerationRules?.map(
+ (rule) => ({
+ ...rule,
+ templateMetadataRuleFormat: rule?.templateMetadataRuleFormat?.value,
+ })
+ ),
},
};
diff --git a/src/components/utils/rulesetSubmitValuesHandler.js b/src/components/utils/rulesetSubmitValuesHandler.js
index ef72386e..41170c83 100644
--- a/src/components/utils/rulesetSubmitValuesHandler.js
+++ b/src/components/utils/rulesetSubmitValuesHandler.js
@@ -24,15 +24,23 @@ const rulesetSubmitValuesHandler = (values) => {
}),
},
templateConfig: {
- ...returnValues?.templateConfig,
- rules: returnValues?.templateConfig?.rules?.map((rule, ruleIndex) => {
- rule.index = ruleIndex;
- rule?.ruleType?.ruleFormat?.levels?.forEach((level, levelIndex) => {
- level.index = levelIndex;
- return level;
- });
- return rule;
- }),
+ ...values?.templateConfig,
+ chronologyRules: values?.templateConfig?.chronologyRules?.map(
+ (chronologyRule, chronologyRuleIndex) => {
+ chronologyRule.index = chronologyRuleIndex;
+ return chronologyRule;
+ }
+ ),
+ enumerationRules: values?.templateConfig?.enumerationRules?.map(
+ (enumerationRule, enumerationRuleIndex) => {
+ enumerationRule.index = enumerationRuleIndex;
+ enumerationRule?.ruleFormat?.levels?.forEach((level, levelIndex) => {
+ level.index = levelIndex;
+ return level;
+ });
+ return enumerationRule;
+ }
+ ),
},
};
};
diff --git a/src/components/views/RulesetForm/RulesetForm.js b/src/components/views/RulesetForm/RulesetForm.js
index b914843d..b7440d9b 100644
--- a/src/components/views/RulesetForm/RulesetForm.js
+++ b/src/components/views/RulesetForm/RulesetForm.js
@@ -35,12 +35,14 @@ import { getRulesetFormValues, handleSaveKeyCommand } from '../../utils';
import {
RulesetInfoForm,
+ ModelRulesetSelection,
PatternTimePeriodForm,
IssuePublicationFieldArray,
OmissionFieldArray,
CombinationFieldArray,
- LabelFieldArray,
- ModelRulesetSelection,
+ ChronologyFieldArray,
+ EnumerationFieldArray,
+ TemplateStringField,
} from '../../RulesetFormSections';
import PiecesPreviewModal from '../../PiecesPreviewModal';
@@ -221,13 +223,21 @@ const RulesetForm = ({
+
+ }
+ >
+
+
+
}
>
-
+
+
() => (
jest.mock('../../RulesetFormSections/CombinationFieldArray', () => () => (
CombinationFieldArray
));
-jest.mock('../../RulesetFormSections/LabelFieldArray', () => () => (
- LabelFieldArray
+jest.mock('../../RulesetFormSections/EnumerationFieldArray', () => () => (
+ EnumerationFieldArray
+));
+jest.mock('../../RulesetFormSections/ChronologyFieldArray', () => () => (
+ ChronologyFieldArray
));
jest.mock('../../RulesetFormSections/ModelRulesetSelection', () => () => (
ModelRulesetSelection
@@ -76,9 +79,14 @@ describe('RulesetForm', () => {
expect(getByText('CombinationFieldArray')).toBeInTheDocument();
});
- test('renders LabelFieldArray Component', () => {
+ test('renders ChronologyFieldArray Component', () => {
+ const { getByText } = renderComponent;
+ expect(getByText('ChronologyFieldArray')).toBeInTheDocument();
+ });
+
+ test('renders EnumerationFieldArray Component', () => {
const { getByText } = renderComponent;
- expect(getByText('LabelFieldArray')).toBeInTheDocument();
+ expect(getByText('EnumerationFieldArray')).toBeInTheDocument();
});
test('renders the New publication patternPane', async () => {
@@ -101,8 +109,12 @@ describe('RulesetForm', () => {
await Accordion('Combination rules').exists();
});
- test('renders the Labelling Accordion', async () => {
- await Accordion('Labelling').exists();
+ test('renders the Chronology Accordion', async () => {
+ await Accordion('Chronology labels').exists();
+ });
+
+ test('renders the Enumeration Accordion', async () => {
+ await Accordion('Enumeration labels').exists();
});
test('renders the button', async () => {
diff --git a/src/components/views/RulesetView/RulesetView.js b/src/components/views/RulesetView/RulesetView.js
index 15624745..7036f813 100644
--- a/src/components/views/RulesetView/RulesetView.js
+++ b/src/components/views/RulesetView/RulesetView.js
@@ -134,19 +134,18 @@ const RulesetView = ({ serial, ruleset, pieceSets, onClose }) => {
/>
- {!!ruleset?.omission?.rules?.length && (
+ {ruleset?.omission?.rules?.length > 0 && (
)}
- {!!ruleset?.combination?.rules?.length && (
+ {ruleset?.combination?.rules?.length > 0 && (
)}
- {/* When chrnology and enumeration are seperated out, this conditional will need to be changed */}
- {ruleset?.templateConfig?.rules?.some(
- (e) => e?.templateMetadataRuleType?.value === 'chronology'
- ) && }
- {ruleset?.templateConfig?.rules?.some(
- (e) => e?.templateMetadataRuleType?.value === 'enumeration'
- ) && }
+ {ruleset?.templateConfig?.chronologyRules?.length > 0 && (
+
+ )}
+ {ruleset?.templateConfig?.enumerationRules?.length > 0 && (
+
+ )}
diff --git a/src/components/views/RulesetView/RulesetView.test.js b/src/components/views/RulesetView/RulesetView.test.js
new file mode 100644
index 00000000..1a85b384
--- /dev/null
+++ b/src/components/views/RulesetView/RulesetView.test.js
@@ -0,0 +1,106 @@
+import { renderWithIntl } from '@folio/stripes-erm-testing';
+import { waitFor } from '@folio/jest-config-stripes/testing-library/react';
+import { MemoryRouter } from 'react-router-dom';
+import { translationsProperties } from '../../../../test/helpers';
+import RulesetView from './RulesetView';
+
+// TODO Imports like this need to be sorted, this is messy
+import { handlers } from '../../../../test/resources';
+import ruleset from '../../../../test/resources/rulesets/ruleset';
+import { dayMonth } from '../../../../test/resources/rulesetResources/omissionsRules';
+import { issue } from '../../../../test/resources/rulesetResources/combinationRules';
+
+jest.mock('../../RulesetSections/RulesetInfo', () => () => (
+ RulesetInfo
+));
+jest.mock('../../RulesetSections/IssuePublication', () => () => (
+ IssuePublication
+));
+jest.mock('../../RulesetSections/OmissionRules', () => () => (
+ OmissionRules
+));
+jest.mock('../../RulesetSections/CombinationRules', () => () => (
+ CombinationRules
+));
+jest.mock('../../RulesetSections/ChronologyLabels', () => () => (
+ ChronologyLabels
+));
+jest.mock('../../RulesetSections/EnumerationLabels', () => () => (
+ EnumerationLabels
+));
+jest.mock('../../RulesetSections/DisplaySummaryTemplate', () => () => (
+ DisplaySummaryTemplate
+));
+
+jest.mock('@folio/stripes/components', () => ({
+ ...jest.requireActual('@folio/stripes/components'),
+ MetaSection: () => MetaSection
,
+}));
+
+describe('RulesetView', () => {
+ let renderComponent;
+
+ describe('with a ruleset which contains only recurrence rules', () => {
+ beforeEach(() => {
+ renderComponent = renderWithIntl(
+
+
+ ,
+ translationsProperties
+ );
+ });
+
+ test.each([
+ { componentName: 'RulesetInfo' },
+ { componentName: 'IssuePublication' },
+ { componentName: 'DisplaySummaryTemplate' },
+ ])('renders %componentName component', async ({ componentName }) => {
+ const { getByText } = renderComponent;
+ await waitFor(async () => {
+ expect(getByText(componentName)).toBeInTheDocument();
+ });
+ });
+ });
+
+ describe('with a ruleset which all potential rules (omssion, combination, enumeration and chronology) ', () => {
+ beforeEach(() => {
+ renderComponent = renderWithIntl(
+
+
+ ,
+ translationsProperties
+ );
+ });
+
+ test.each([
+ { componentName: 'OmissionRules' },
+ { componentName: 'CombinationRules' },
+ { componentName: 'ChronologyLabels' },
+ { componentName: 'EnumerationLabels' },
+ ])('renders %componentName component', async ({ componentName }) => {
+ const { getByText } = renderComponent;
+ await waitFor(async () => {
+ expect(getByText(componentName)).toBeInTheDocument();
+ });
+ });
+ });
+});
diff --git a/test/resources/rulesetResources/chronologyRules.js b/test/resources/rulesetResources/chronologyRules.js
index 229c2c34..dd1d03d5 100644
--- a/test/resources/rulesetResources/chronologyRules.js
+++ b/test/resources/rulesetResources/chronologyRules.js
@@ -1,68 +1,47 @@
import { findRefdataValue } from '../utils';
export const chronologyDate = {
- id: '5000849c-7745-4ec6-a583-04a5b31e209d',
+ id: 'a14ac8e2-d6ae-4887-aeb0-9343927e4dee',
index: 0,
- templateMetadataRuleType: findRefdataValue(
- 'TemplateMetadataRule.TemplateMetadataRuleType',
- 'chronology'
+ ruleLocale: 'en',
+ templateMetadataRuleFormat: findRefdataValue(
+ 'ChronologyTemplateMetadataRule.TemplateMetadataRuleFormat',
+ 'chronology_date'
),
- ruleType: {
- id: 'a14ac8e2-d6ae-4887-aeb0-9343927e4dee',
- ruleLocale: 'en',
- templateMetadataRuleFormat: findRefdataValue(
- 'ChronologyTemplateMetadataRule.TemplateMetadataRuleFormat',
- 'chronology_date'
- ),
- ruleFormat: {
- id: 'd85e7ab6-824e-43bc-88af-0152b8877d9f',
- yearFormat: findRefdataValue('Global.YearFormat', 'full'),
- monthFormat: findRefdataValue('Global.MonthFormat', 'full'),
- weekdayFormat: findRefdataValue('Global.WeekdayFormat', 'full_lower'),
- monthDayFormat: findRefdataValue('Global.MonthDayFormat', 'number'),
- },
+ ruleFormat: {
+ id: 'd85e7ab6-824e-43bc-88af-0152b8877d9f',
+ yearFormat: findRefdataValue('Global.YearFormat', 'full'),
+ monthFormat: findRefdataValue('Global.MonthFormat', 'full'),
+ weekdayFormat: findRefdataValue('Global.WeekdayFormat', 'full_lower'),
+ monthDayFormat: findRefdataValue('Global.MonthDayFormat', 'number'),
},
};
export const chronologyMonth = {
- id: '920623d1-de6a-4916-957b-a6a00a8b84ef',
+ id: 'f2f7ab49-bed0-49e2-ad14-e3d2d56e5bd6',
index: 1,
- templateMetadataRuleType: findRefdataValue(
- 'TemplateMetadataRule.TemplateMetadataRuleType',
- 'chronology'
+ ruleLocale: 'en',
+ templateMetadataRuleFormat: findRefdataValue(
+ 'ChronologyTemplateMetadataRule.TemplateMetadataRuleFormat',
+ 'chronology_month'
),
- ruleType: {
- id: 'f2f7ab49-bed0-49e2-ad14-e3d2d56e5bd6',
- ruleLocale: 'en',
- templateMetadataRuleFormat: findRefdataValue(
- 'ChronologyTemplateMetadataRule.TemplateMetadataRuleFormat',
- 'chronology_month'
- ),
- ruleFormat: {
- id: 'a252d854-5f73-4dcc-bf6e-c184543c1234',
- yearFormat: findRefdataValue('Global.YearFormat', 'full'),
- monthFormat: findRefdataValue('Global.MonthFormat', 'full'),
- },
+ ruleFormat: {
+ id: 'a252d854-5f73-4dcc-bf6e-c184543c1234',
+ yearFormat: findRefdataValue('Global.YearFormat', 'full'),
+ monthFormat: findRefdataValue('Global.MonthFormat', 'full'),
},
};
export const chronologyYear = {
- id: '6c14f945-ce66-4c30-aed7-fbb5a771a203',
+ id: 'f663fcd3-5cb5-4878-b9fe-0f5eee24aed8',
index: 2,
- templateMetadataRuleType: findRefdataValue(
- 'TemplateMetadataRule.TemplateMetadataRuleType',
- 'chronology'
+ ruleLocale: 'en',
+ templateMetadataRuleFormat: findRefdataValue(
+ 'ChronologyTemplateMetadataRule.TemplateMetadataRuleFormat',
+ 'chronology_year'
),
- ruleType: {
- id: 'f663fcd3-5cb5-4878-b9fe-0f5eee24aed8',
- ruleLocale: 'en',
- templateMetadataRuleFormat: findRefdataValue(
- 'ChronologyTemplateMetadataRule.TemplateMetadataRuleFormat',
- 'chronology_year'
- ),
- ruleFormat: {
- id: 'be3fca50-21c3-438c-8dc0-fbfff4ea2c64',
- yearFormat: findRefdataValue('Global.YearFormat', 'full'),
- },
+ ruleFormat: {
+ id: 'be3fca50-21c3-438c-8dc0-fbfff4ea2c64',
+ yearFormat: findRefdataValue('Global.YearFormat', 'full'),
},
};
diff --git a/test/resources/rulesetResources/enumerationRules.js b/test/resources/rulesetResources/enumerationRules.js
index 2d48c83b..33d7c7a2 100644
--- a/test/resources/rulesetResources/enumerationRules.js
+++ b/test/resources/rulesetResources/enumerationRules.js
@@ -1,85 +1,71 @@
import { findRefdataValue } from '../utils';
export const enumerationNumeric = {
- id: 'f9c26c17-6d69-4b05-9a94-8ac391f660ad',
- index: 3,
- templateMetadataRuleType: findRefdataValue(
- 'TemplateMetadataRule.TemplateMetadataRuleType',
- 'enumeration'
+ id: '6fb7e0db-90ff-4e9e-bf8c-9fa56271061a',
+ index: 0,
+ templateMetadataRuleFormat: findRefdataValue(
+ 'EnumerationTemplateMetadataRule.TemplateMetadataRuleFormat',
+ 'enumeration_numeric'
),
- ruleType: {
- id: '6fb7e0db-90ff-4e9e-bf8c-9fa56271061a',
- templateMetadataRuleFormat: findRefdataValue(
- 'EnumerationTemplateMetadataRule.TemplateMetadataRuleFormat',
- 'enumeration_numeric'
- ),
- ruleFormat: {
- id: 'ba34e745-c626-4908-b17a-cd79366cb2b9',
- levels: [
- {
- id: '8b9dc71f-e0c4-4ee9-ac06-feff8747f953',
- index: 0,
- internalNote: 'Level 1',
- units: 1,
- sequence: findRefdataValue(
- 'EnumerationNumericLevelTMRF.Sequence',
- 'continuous'
- ),
- format: findRefdataValue(
- 'EnumerationNumericLevelTMRF.Format',
- 'number'
- ),
- },
- {
- id: 'bf774633-3bb2-4a0d-813e-6bd16a8ea9f7',
- index: 1,
- internalNote: 'Level 2',
- units: 5,
- sequence: findRefdataValue(
- 'EnumerationNumericLevelTMRF.Sequence',
- 'reset'
- ),
- format: findRefdataValue(
- 'EnumerationNumericLevelTMRF.Format',
- 'ordinal'
- ),
- },
- ],
- },
+ ruleFormat: {
+ id: 'ba34e745-c626-4908-b17a-cd79366cb2b9',
+ levels: [
+ {
+ id: '8b9dc71f-e0c4-4ee9-ac06-feff8747f953',
+ index: 0,
+ internalNote: 'Level 1',
+ units: 1,
+ sequence: findRefdataValue(
+ 'EnumerationNumericLevelTMRF.Sequence',
+ 'continuous'
+ ),
+ format: findRefdataValue(
+ 'EnumerationNumericLevelTMRF.Format',
+ 'number'
+ ),
+ },
+ {
+ id: 'bf774633-3bb2-4a0d-813e-6bd16a8ea9f7',
+ index: 1,
+ internalNote: 'Level 2',
+ units: 5,
+ sequence: findRefdataValue(
+ 'EnumerationNumericLevelTMRF.Sequence',
+ 'reset'
+ ),
+ format: findRefdataValue(
+ 'EnumerationNumericLevelTMRF.Format',
+ 'ordinal'
+ ),
+ },
+ ],
},
};
export const enumerationTextual = {
- id: '94118695-3d28-4696-9732-ccb2e68158bb',
- index: 0,
- templateMetadataRuleType: findRefdataValue(
- 'TemplateMetadataRule.TemplateMetadataRuleType',
- 'enumeration'
+ id: '216ee06c-0117-4713-9c25-398b9f4137e9',
+ index: 1,
+ templateMetadataRuleFormat: findRefdataValue(
+ 'EnumerationTemplateMetadataRule.TemplateMetadataRuleFormat',
+ 'enumeration_textual'
),
- ruleType: {
- id: '216ee06c-0117-4713-9c25-398b9f4137e9',
- templateMetadataRuleFormat: findRefdataValue(
- 'EnumerationTemplateMetadataRule.TemplateMetadataRuleFormat',
- 'enumeration_textual'
- ),
- ruleFormat: {
- id: '18b9bb72-aeef-43d3-9e83-b7e6df3b3eb9',
- levels: [
- {
- id: 'ac83f615-cad8-46be-9ea4-10c6d6a75f07',
- index: 0,
- internalNote: 'Order 1',
- units: 1,
- value: 'Friday',
- },
- {
- id: '01530c47-4a46-42e6-974f-12a08036c9f6',
- index: 1,
- internalNote: 'Order 2',
- units: 2,
- value: 'Monday',
- },
- ],
- },
+ ruleFormat: {
+ id: '18b9bb72-aeef-43d3-9e83-b7e6df3b3eb9',
+ levels: [
+ {
+ id: 'ac83f615-cad8-46be-9ea4-10c6d6a75f07',
+ index: 0,
+ internalNote: 'Order 1',
+ units: 1,
+ value: 'Friday',
+ },
+ {
+ id: '01530c47-4a46-42e6-974f-12a08036c9f6',
+ index: 1,
+ internalNote: 'Order 2',
+ units: 2,
+ value: 'Monday',
+ },
+ ],
},
};
diff --git a/test/resources/rulesets/combinationRuleset.js b/test/resources/rulesets/combinationRuleset.js
index d8d63240..3ae9f4f0 100644
--- a/test/resources/rulesets/combinationRuleset.js
+++ b/test/resources/rulesets/combinationRuleset.js
@@ -19,7 +19,7 @@ const combinationRuleset = {
rulesetNumber: '5',
templateConfig: {
id: '28cb5cab-ce30-4b48-8d1b-2c7f86b2232e',
- rules: [chronologyDate],
+ chronologyRules: [chronologyDate],
templateString:
'{{chronology1.weekday}} {{chronology1.monthDay}} {{chronology1.month}} {{chronology1.year}}',
},
diff --git a/test/resources/rulesets/omissionRuleset.js b/test/resources/rulesets/omissionRuleset.js
index 604a5eb7..d4d38a61 100644
--- a/test/resources/rulesets/omissionRuleset.js
+++ b/test/resources/rulesets/omissionRuleset.js
@@ -19,7 +19,7 @@ const omissionRuleset = {
},
templateConfig: {
id: '154f5edc-883e-4066-b0c4-ba7b91497ed7',
- rules: [chronologyDate],
+ chronologyRules: [chronologyDate],
templateString:
'{{chronology1.weekday}} {{chronology1.monthDay}} {{chronology1.month}} {{chronology1.year}}',
},
diff --git a/test/resources/rulesets/ruleset.js b/test/resources/rulesets/ruleset.js
index e134e20e..67adf5d9 100644
--- a/test/resources/rulesets/ruleset.js
+++ b/test/resources/rulesets/ruleset.js
@@ -16,9 +16,11 @@ const ruleset = {
},
templateConfig: {
id: 'e6f9dad2-88f0-429e-8686-beddf4c8088a',
- rules: [
+ chronologyRules: [
{ ...chronologyYear, index: 0 },
- { ...enumerationNumeric, index: 1 },
+ ],
+ enumerationRules: [
+ { ...enumerationNumeric, index: 0 },
],
templateString:
'Vol:{{enumeration1.level1}} Issue:{{enumeration1.level2}}, {{chronology1.year}}',
diff --git a/test/resources/utils/findRefdataCategory.js b/test/resources/utils/findRefdataCategory.js
new file mode 100644
index 00000000..8dccb73e
--- /dev/null
+++ b/test/resources/utils/findRefdataCategory.js
@@ -0,0 +1,15 @@
+import refdata from '../refdata';
+
+// TODO This can be added into a single util function with findRefdataValue
+const findRefdataCategory = (category) => {
+ const refdataCategory = refdata?.find((rdc) => rdc.desc === category);
+
+ if (!refdataCategory) {
+ throw new Error(`Refdata value not found for category: ${category}`);
+ }
+
+ return refdataCategory;
+};
+
+export default findRefdataCategory;
+
diff --git a/test/resources/utils/index.js b/test/resources/utils/index.js
index 1cca3c8b..17247a17 100644
--- a/test/resources/utils/index.js
+++ b/test/resources/utils/index.js
@@ -1 +1,2 @@
export { default as findRefdataValue } from './findRefdataValue';
+export { default as findRefdataCategory } from './findRefdataCategory';
diff --git a/translations/ui-serials-management/en.json b/translations/ui-serials-management/en.json
index 19bc6aa4..1e749e04 100644
--- a/translations/ui-serials-management/en.json
+++ b/translations/ui-serials-management/en.json
@@ -179,10 +179,18 @@
"ruleset.labelling": "Labelling",
"ruleset.removeLabel": "Remove label {index}",
+ "ruleset.removeChronologyLabelIndex": "Remove chronology label {index}",
+ "ruleset.removeEnumerationLabelIndex": "Remove enumeration label {index}",
"ruleset.labelIndex": "Label {index}",
+ "ruleset.chronologyLabelIndex": "Chronology label {index}",
+ "ruleset.enumerationLabelIndex": "Enumeration label {index}",
"ruleset.labelStyle": "Label style",
"ruleset.noLabels": "No labels for this publication pattern",
+ "ruleset.noChronologyLabels": "No chronology labels for this publication pattern",
+ "ruleset.noEnumerationLabels": "No enumeration labels for this publication pattern",
"ruleset.addLabel": "Add label",
+ "ruleset.addChronologyLabel": "Add chronology label",
+ "ruleset.addEnumerationLabel": "Add enumeration label",
"ruleset.chronology": "Chronology",
"ruleset.chronologyFormat": "Chronology format",
"ruleset.enumerationFormat": "Enumeration format",