mirror of
https://github.com/LaCasemate/fab-manager.git
synced 2024-11-28 09:24:24 +01:00
(test) tiptap & file uploads
This commit is contained in:
parent
7a3ab98b10
commit
c1638ab54d
@ -70,6 +70,10 @@
|
|||||||
"env": {
|
"env": {
|
||||||
"jest/globals": true
|
"jest/globals": true
|
||||||
},
|
},
|
||||||
|
"globals": {
|
||||||
|
"Range": true,
|
||||||
|
"Document": true
|
||||||
|
},
|
||||||
"parserOptions": {
|
"parserOptions": {
|
||||||
"project": "./test/frontend/tsconfig.json"
|
"project": "./test/frontend/tsconfig.json"
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ interface FabTextEditorProps {
|
|||||||
placeholder?: string,
|
placeholder?: string,
|
||||||
error?: string,
|
error?: string,
|
||||||
disabled?: boolean
|
disabled?: boolean
|
||||||
editorId?: string,
|
ariaLabel?: string,
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface FabTextEditorRef {
|
export interface FabTextEditorRef {
|
||||||
@ -35,7 +35,7 @@ export interface FabTextEditorRef {
|
|||||||
/**
|
/**
|
||||||
* This component is a WYSIWYG text editor
|
* This component is a WYSIWYG text editor
|
||||||
*/
|
*/
|
||||||
const FabTextEditor: React.ForwardRefRenderFunction<FabTextEditorRef, FabTextEditorProps> = ({ heading, bulletList, blockquote, content, limit = 400, video, image, link, onChange, placeholder, error, disabled = false, editorId }, ref: RefObject<FabTextEditorRef>) => {
|
const FabTextEditor: React.ForwardRefRenderFunction<FabTextEditorRef, FabTextEditorProps> = ({ heading, bulletList, blockquote, content, limit = 400, video, image, link, onChange, placeholder, error, disabled = false, ariaLabel }, ref: RefObject<FabTextEditorRef>) => {
|
||||||
const { t } = useTranslation('shared');
|
const { t } = useTranslation('shared');
|
||||||
const placeholderText = placeholder || t('app.shared.text_editor.fab_text_editor.text_placeholder');
|
const placeholderText = placeholder || t('app.shared.text_editor.fab_text_editor.text_placeholder');
|
||||||
// TODO: Add ctrl+click on link to visit
|
// TODO: Add ctrl+click on link to visit
|
||||||
@ -77,7 +77,8 @@ const FabTextEditor: React.ForwardRefRenderFunction<FabTextEditorRef, FabTextEdi
|
|||||||
],
|
],
|
||||||
editorProps: {
|
editorProps: {
|
||||||
attributes: {
|
attributes: {
|
||||||
id: editorId
|
'aria-label': ariaLabel,
|
||||||
|
role: 'textbox'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
content,
|
content,
|
||||||
|
@ -7,8 +7,6 @@ import { get as _get } from 'lodash';
|
|||||||
export interface AbstractFormItemProps<TFieldValues> extends PropsWithChildren<AbstractFormComponent<TFieldValues>> {
|
export interface AbstractFormItemProps<TFieldValues> extends PropsWithChildren<AbstractFormComponent<TFieldValues>> {
|
||||||
id: string,
|
id: string,
|
||||||
label?: string|ReactNode,
|
label?: string|ReactNode,
|
||||||
ariaLabel?: string,
|
|
||||||
ariaLabelledBy?: string,
|
|
||||||
tooltip?: ReactNode,
|
tooltip?: ReactNode,
|
||||||
className?: string,
|
className?: string,
|
||||||
disabled?: boolean|((id: string) => boolean),
|
disabled?: boolean|((id: string) => boolean),
|
||||||
@ -21,7 +19,7 @@ export interface AbstractFormItemProps<TFieldValues> extends PropsWithChildren<A
|
|||||||
* This abstract component should not be used directly.
|
* This abstract component should not be used directly.
|
||||||
* Other forms components that are intended to be used with react-hook-form must extend this component.
|
* Other forms components that are intended to be used with react-hook-form must extend this component.
|
||||||
*/
|
*/
|
||||||
export const AbstractFormItem = <TFieldValues extends FieldValues>({ id, label, ariaLabel, ariaLabelledBy, tooltip, className, disabled, error, warning, rules, formState, onLabelClick, inLine, containerType, children }: AbstractFormItemProps<TFieldValues>) => {
|
export const AbstractFormItem = <TFieldValues extends FieldValues>({ id, label, tooltip, className, disabled, error, warning, rules, formState, onLabelClick, inLine, containerType, children }: AbstractFormItemProps<TFieldValues>) => {
|
||||||
const [isDirty, setIsDirty] = useState<boolean>(false);
|
const [isDirty, setIsDirty] = useState<boolean>(false);
|
||||||
const [fieldError, setFieldError] = useState<{ message: string }>(error);
|
const [fieldError, setFieldError] = useState<{ message: string }>(error);
|
||||||
const [isDisabled, setIsDisabled] = useState<boolean>(false);
|
const [isDisabled, setIsDisabled] = useState<boolean>(false);
|
||||||
@ -72,7 +70,7 @@ export const AbstractFormItem = <TFieldValues extends FieldValues>({ id, label,
|
|||||||
</div>}
|
</div>}
|
||||||
</div>}
|
</div>}
|
||||||
|
|
||||||
<div className='form-item-field' aria-label={ariaLabel} aria-labelledby={ariaLabelledBy}>
|
<div className='form-item-field'>
|
||||||
{inLine && <div className='form-item-header'><p>{label}</p>
|
{inLine && <div className='form-item-header'><p>{label}</p>
|
||||||
{tooltip && <div className="fab-tooltip">
|
{tooltip && <div className="fab-tooltip">
|
||||||
<span className="trigger"><i className="fa fa-question-circle" /></span>
|
<span className="trigger"><i className="fa fa-question-circle" /></span>
|
||||||
|
@ -87,18 +87,19 @@ export const FormFileUpload = <TFieldValues extends FieldValues>({ id, label, re
|
|||||||
</a>
|
</a>
|
||||||
)}
|
)}
|
||||||
<FormInput type="file"
|
<FormInput type="file"
|
||||||
className="image-file-input"
|
ariaLabel={label as string}
|
||||||
accept={accept}
|
className="image-file-input"
|
||||||
register={register}
|
accept={accept}
|
||||||
label={label}
|
register={register}
|
||||||
formState={formState}
|
label={label}
|
||||||
rules={rules}
|
formState={formState}
|
||||||
disabled={disabled}
|
rules={rules}
|
||||||
error={error}
|
disabled={disabled}
|
||||||
warning={warning}
|
error={error}
|
||||||
id={`${id}[attachment_files]`}
|
warning={warning}
|
||||||
onChange={onFileSelected}
|
id={`${id}[attachment_files]`}
|
||||||
placeholder={placeholder()}/>
|
onChange={onFileSelected}
|
||||||
|
placeholder={placeholder()}/>
|
||||||
{hasFile() &&
|
{hasFile() &&
|
||||||
<FabButton onClick={onRemoveFile} icon={<Trash size={20} weight="fill" />} className="is-main" />
|
<FabButton onClick={onRemoveFile} icon={<Trash size={20} weight="fill" />} className="is-main" />
|
||||||
}
|
}
|
||||||
|
@ -19,13 +19,14 @@ interface FormInputProps<TFieldValues, TInputType> extends FormComponent<TFieldV
|
|||||||
placeholder?: string,
|
placeholder?: string,
|
||||||
step?: number | 'any',
|
step?: number | 'any',
|
||||||
onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void,
|
onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void,
|
||||||
nullable?: boolean
|
nullable?: boolean,
|
||||||
|
ariaLabel?: string,
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This component is a template for an input component to use within React Hook Form
|
* This component is a template for an input component to use within React Hook Form
|
||||||
*/
|
*/
|
||||||
export const FormInput = <TFieldValues extends FieldValues, TInputType>({ id, register, label, tooltip, defaultValue, icon, className, rules, disabled, type, addOn, addOnAction, addOnClassName, placeholder, error, warning, formState, step, onChange, debounce, accept, nullable = false }: FormInputProps<TFieldValues, TInputType>) => {
|
export const FormInput = <TFieldValues extends FieldValues, TInputType>({ id, register, label, tooltip, defaultValue, icon, className, rules, disabled, type, addOn, addOnAction, addOnClassName, placeholder, error, warning, formState, step, onChange, debounce, accept, nullable = false, ariaLabel }: FormInputProps<TFieldValues, TInputType>) => {
|
||||||
/**
|
/**
|
||||||
* Debounced (ie. temporised) version of the 'on change' callback.
|
* Debounced (ie. temporised) version of the 'on change' callback.
|
||||||
*/
|
*/
|
||||||
@ -56,7 +57,7 @@ export const FormInput = <TFieldValues extends FieldValues, TInputType>({ id, re
|
|||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
rules={rules} error={error} warning={warning}>
|
rules={rules} error={error} warning={warning}>
|
||||||
{icon && <span className="icon">{icon}</span>}
|
{icon && <span className="icon">{icon}</span>}
|
||||||
<input id={id}
|
<input id={id} aria-label={ariaLabel}
|
||||||
{...register(id as FieldPath<TFieldValues>, {
|
{...register(id as FieldPath<TFieldValues>, {
|
||||||
...rules,
|
...rules,
|
||||||
valueAsDate: type === 'date',
|
valueAsDate: type === 'date',
|
||||||
|
@ -46,8 +46,6 @@ export const FormRichText = <TFieldValues extends FieldValues, TContext extends
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<AbstractFormItem id={id} label={label} tooltip={tooltip}
|
<AbstractFormItem id={id} label={label} tooltip={tooltip}
|
||||||
ariaLabel={label as string}
|
|
||||||
ariaLabelledBy={id}
|
|
||||||
containerType={'div'}
|
containerType={'div'}
|
||||||
className={`form-rich-text ${className || ''}`}
|
className={`form-rich-text ${className || ''}`}
|
||||||
error={error} warning={warning} rules={rules}
|
error={error} warning={warning} rules={rules}
|
||||||
@ -68,7 +66,7 @@ export const FormRichText = <TFieldValues extends FieldValues, TContext extends
|
|||||||
link={link}
|
link={link}
|
||||||
disabled={isDisabled}
|
disabled={isDisabled}
|
||||||
ref={textEditorRef}
|
ref={textEditorRef}
|
||||||
editorId={id} />
|
ariaLabel={label as string}/>
|
||||||
} />
|
} />
|
||||||
</AbstractFormItem>
|
</AbstractFormItem>
|
||||||
);
|
);
|
||||||
|
@ -207,6 +207,7 @@ export const PlanForm: React.FC<PlanFormProps> = ({ action, plan, onError, onSuc
|
|||||||
<FormSwitch control={control}
|
<FormSwitch control={control}
|
||||||
formState={formState}
|
formState={formState}
|
||||||
id="disabled"
|
id="disabled"
|
||||||
|
defaultValue={false}
|
||||||
label={t('app.admin.plan_form.disabled')}
|
label={t('app.admin.plan_form.disabled')}
|
||||||
tooltip={t('app.admin.plan_form.disabled_help')} />
|
tooltip={t('app.admin.plan_form.disabled_help')} />
|
||||||
<h4>{t('app.admin.plan_form.duration')}</h4>
|
<h4>{t('app.admin.plan_form.duration')}</h4>
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { Price } from './price';
|
import { Price } from './price';
|
||||||
import { FileType } from './file';
|
import { FileType } from './file';
|
||||||
|
import { AdvancedAccounting } from './advanced-accounting';
|
||||||
|
|
||||||
export type Interval = 'year' | 'month' | 'week';
|
export type Interval = 'year' | 'month' | 'week';
|
||||||
|
|
||||||
@ -12,26 +13,29 @@ export interface Partner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface Plan {
|
export interface Plan {
|
||||||
id: number,
|
id?: number,
|
||||||
base_name: string,
|
base_name: string,
|
||||||
name: string,
|
name?: string,
|
||||||
interval: Interval,
|
interval: Interval,
|
||||||
interval_count: number,
|
interval_count: number,
|
||||||
|
all_groups?: boolean,
|
||||||
group_id: number|'all',
|
group_id: number|'all',
|
||||||
plan_category_id: number,
|
plan_category_id?: number,
|
||||||
training_credit_nb: number,
|
training_credit_nb?: number,
|
||||||
is_rolling: boolean,
|
is_rolling: boolean,
|
||||||
description: string,
|
description?: string,
|
||||||
type: PlanType,
|
type: PlanType,
|
||||||
ui_weight: number,
|
ui_weight: number,
|
||||||
disabled: boolean,
|
disabled?: boolean,
|
||||||
monthly_payment: boolean
|
monthly_payment: boolean
|
||||||
amount: number
|
amount: number
|
||||||
prices_attributes: Array<Price>,
|
prices_attributes?: Array<Price>,
|
||||||
plan_file_attributes: FileType,
|
plan_file_attributes?: FileType,
|
||||||
plan_file_url?: string,
|
plan_file_url?: string,
|
||||||
partner_id?: number,
|
partner_id?: number,
|
||||||
partners?: Array<Partner>
|
partnership?: boolean,
|
||||||
|
partners?: Array<Partner>,
|
||||||
|
advanced_accounting_attributes?: AdvancedAccounting
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PlansDuration {
|
export interface PlansDuration {
|
||||||
|
@ -140,7 +140,8 @@ module.exports = {
|
|||||||
// A list of paths to modules that run some code to configure or set up the testing framework before each test
|
// A list of paths to modules that run some code to configure or set up the testing framework before each test
|
||||||
setupFilesAfterEnv: [
|
setupFilesAfterEnv: [
|
||||||
'<rootDir>/test/frontend/__setup__/mocks.js',
|
'<rootDir>/test/frontend/__setup__/mocks.js',
|
||||||
'<rootDir>/test/frontend/__setup__/server.js'
|
'<rootDir>/test/frontend/__setup__/server.js',
|
||||||
|
'<rootDir>/test/frontend/__setup__/rects.js'
|
||||||
],
|
],
|
||||||
|
|
||||||
// The number of seconds after which a test is considered as slow and reported as such in the results.
|
// The number of seconds after which a test is considered as slow and reported as such in the results.
|
||||||
|
16
test/frontend/__lib__/tiptap.ts
Normal file
16
test/frontend/__lib__/tiptap.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import { act, waitFor } from '@testing-library/react';
|
||||||
|
|
||||||
|
interface TipTapEvent {
|
||||||
|
type: (element: Element, content: string) => Promise<void>
|
||||||
|
}
|
||||||
|
|
||||||
|
export const tiptapEvent: TipTapEvent = {
|
||||||
|
type: async (element, content) => {
|
||||||
|
await act(async () => {
|
||||||
|
element.innerHTML = content;
|
||||||
|
await waitFor(() => {
|
||||||
|
expect(element.innerHTML).toBe(content);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
16
test/frontend/__setup__/rects.js
Normal file
16
test/frontend/__setup__/rects.js
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
// the following workarounds are necessary to test with tiptap editor
|
||||||
|
|
||||||
|
Range.prototype.getBoundingClientRect = () => ({
|
||||||
|
bottom: 0,
|
||||||
|
height: 0,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
top: 0,
|
||||||
|
width: 0
|
||||||
|
});
|
||||||
|
Range.prototype.getClientRects = () => ({
|
||||||
|
item: () => null,
|
||||||
|
length: 0,
|
||||||
|
[Symbol.iterator]: jest.fn()
|
||||||
|
});
|
||||||
|
Document.prototype.elementFromPoint = jest.fn();
|
@ -1,9 +1,11 @@
|
|||||||
import { render, fireEvent, waitFor, screen } from '@testing-library/react';
|
import { render, fireEvent, waitFor, screen } from '@testing-library/react';
|
||||||
import '@testing-library/jest-dom';
|
import '@testing-library/jest-dom';
|
||||||
import { PlanForm } from 'components/plans/plan-form';
|
import { PlanForm } from 'components/plans/plan-form';
|
||||||
|
import { Plan } from 'models/plan';
|
||||||
import selectEvent from 'react-select-event';
|
import selectEvent from 'react-select-event';
|
||||||
import userEvent from '@testing-library/user-event';
|
import userEvent from '@testing-library/user-event';
|
||||||
import plans from '../../__fixtures__/plans';
|
import plans from '../../__fixtures__/plans';
|
||||||
|
import { tiptapEvent } from '../../__lib__/tiptap';
|
||||||
|
|
||||||
describe('PlanForm', () => {
|
describe('PlanForm', () => {
|
||||||
const onError = jest.fn();
|
const onError = jest.fn();
|
||||||
@ -11,9 +13,8 @@ describe('PlanForm', () => {
|
|||||||
const beforeSubmit = jest.fn();
|
const beforeSubmit = jest.fn();
|
||||||
|
|
||||||
test('render create PlanForm', async () => {
|
test('render create PlanForm', async () => {
|
||||||
render(<PlanForm action="create" onError={onError} onSuccess={onSuccess} beforeSubmit={beforeSubmit} />);
|
render(<PlanForm action="create" onError={onError} onSuccess={onSuccess} />);
|
||||||
await waitFor(() => screen.getByRole('combobox', { name: /app.admin.plan_form.group/ }));
|
await waitFor(() => screen.getByRole('combobox', { name: /app.admin.plan_form.group/ }));
|
||||||
// check inputs
|
|
||||||
expect(screen.getByLabelText(/app.admin.plan_form.name/)).toBeInTheDocument();
|
expect(screen.getByLabelText(/app.admin.plan_form.name/)).toBeInTheDocument();
|
||||||
expect(screen.getByLabelText(/app.admin.plan_form.transversal/)).toBeInTheDocument();
|
expect(screen.getByLabelText(/app.admin.plan_form.transversal/)).toBeInTheDocument();
|
||||||
expect(screen.getByLabelText(/app.admin.plan_form.group/)).toBeInTheDocument();
|
expect(screen.getByLabelText(/app.admin.plan_form.group/)).toBeInTheDocument();
|
||||||
@ -30,23 +31,67 @@ describe('PlanForm', () => {
|
|||||||
expect(screen.getByLabelText(/app.admin.plan_form.partner_plan/)).toBeInTheDocument();
|
expect(screen.getByLabelText(/app.admin.plan_form.partner_plan/)).toBeInTheDocument();
|
||||||
expect(screen.queryByTestId('plan-pricing-form')).toBeNull();
|
expect(screen.queryByTestId('plan-pricing-form')).toBeNull();
|
||||||
expect(screen.getByRole('button', { name: /app.admin.plan_form.ACTION_plan/ })).toBeInTheDocument();
|
expect(screen.getByRole('button', { name: /app.admin.plan_form.ACTION_plan/ })).toBeInTheDocument();
|
||||||
// input values
|
});
|
||||||
|
|
||||||
|
test('create new plan', async () => {
|
||||||
|
render(<PlanForm action="create" onError={onError} onSuccess={onSuccess} beforeSubmit={beforeSubmit} />);
|
||||||
|
await waitFor(() => screen.getByRole('combobox', { name: /app.admin.plan_form.group/ }));
|
||||||
const user = userEvent.setup();
|
const user = userEvent.setup();
|
||||||
|
// base_name
|
||||||
fireEvent.change(screen.getByLabelText(/app.admin.plan_form.name/), { target: { value: 'Test Plan' } });
|
fireEvent.change(screen.getByLabelText(/app.admin.plan_form.name/), { target: { value: 'Test Plan' } });
|
||||||
|
// group_id = 1
|
||||||
await selectEvent.select(screen.getByLabelText(/app.admin.plan_form.group/), 'Standard');
|
await selectEvent.select(screen.getByLabelText(/app.admin.plan_form.group/), 'Standard');
|
||||||
|
// plan_category_id = 1
|
||||||
await selectEvent.select(screen.getByLabelText(/app.admin.plan_form.category/), 'beginners');
|
await selectEvent.select(screen.getByLabelText(/app.admin.plan_form.category/), 'beginners');
|
||||||
|
// amount
|
||||||
fireEvent.change(screen.getByLabelText(/app.admin.plan_form.subscription_price/), { target: { value: 25.21 } });
|
fireEvent.change(screen.getByLabelText(/app.admin.plan_form.subscription_price/), { target: { value: 25.21 } });
|
||||||
|
// ui_weight
|
||||||
fireEvent.change(screen.getByLabelText(/app.admin.plan_form.visual_prominence/), { target: { value: 10 } });
|
fireEvent.change(screen.getByLabelText(/app.admin.plan_form.visual_prominence/), { target: { value: 10 } });
|
||||||
fireEvent.change(screen.getByLabelText(/app.admin.plan_form.rolling_subscription/), { target: { value: true } });
|
// is_rolling
|
||||||
fireEvent.change(screen.getByLabelText(/app.admin.plan_form.monthly_payment/), { target: { value: true } });
|
await user.click(screen.getByLabelText(/app.admin.plan_form.rolling_subscription/));
|
||||||
await user.click(screen.getByLabelText(/app.admin.plan_form.description/));
|
// monthly_payment
|
||||||
await user.keyboard('Lorem ipsum dolor sit amet');
|
await user.click(screen.getByLabelText(/app.admin.plan_form.monthly_payment/));
|
||||||
|
// description
|
||||||
|
await tiptapEvent.type(screen.getByLabelText(/app.admin.plan_form.description/), 'Lorem ipsum dolor sit amet');
|
||||||
|
// plan_file_attributes.attachment_files
|
||||||
|
const file = new File(['(⌐□_□)'], 'document.pdf', { type: 'application/pdf' });
|
||||||
|
await user.upload(screen.getByLabelText(/app.admin.plan_form.information_sheet/), file);
|
||||||
|
// interval_count
|
||||||
fireEvent.change(screen.getByLabelText(/app.admin.plan_form.number_of_periods/), { target: { value: 6 } });
|
fireEvent.change(screen.getByLabelText(/app.admin.plan_form.number_of_periods/), { target: { value: 6 } });
|
||||||
|
// interval
|
||||||
await selectEvent.select(screen.getByLabelText(/app.admin.plan_form.period/), 'app.admin.plan_form.month');
|
await selectEvent.select(screen.getByLabelText(/app.admin.plan_form.period/), 'app.admin.plan_form.month');
|
||||||
|
// advanced_accounting_attributes.code
|
||||||
|
fireEvent.change(screen.getByLabelText(/app.admin.advanced_accounting_form.code/), { target: { value: '705200' } });
|
||||||
|
// advanced_accounting_attributes.analytical_section
|
||||||
|
fireEvent.change(screen.getByLabelText(/app.admin.advanced_accounting_form.analytical_section/), { target: { value: '9B20A' } });
|
||||||
// send the form
|
// send the form
|
||||||
fireEvent.click(screen.getByRole('button', { name: /app.admin.plan_form.ACTION_plan/ }));
|
fireEvent.click(screen.getByRole('button', { name: /app.admin.plan_form.ACTION_plan/ }));
|
||||||
await waitFor(() => {
|
await waitFor(() => {
|
||||||
expect(beforeSubmit).toHaveBeenCalled();
|
const expected: Plan = {
|
||||||
|
base_name: 'Test Plan',
|
||||||
|
type: 'Plan',
|
||||||
|
group_id: 1,
|
||||||
|
plan_category_id: 1,
|
||||||
|
amount: 25.21,
|
||||||
|
ui_weight: 10,
|
||||||
|
is_rolling: true,
|
||||||
|
monthly_payment: true,
|
||||||
|
description: '<p>Lorem ipsum dolor sit amet</p>',
|
||||||
|
interval: 'month',
|
||||||
|
interval_count: 6,
|
||||||
|
all_groups: false,
|
||||||
|
partnership: false,
|
||||||
|
disabled: false,
|
||||||
|
advanced_accounting_attributes: {
|
||||||
|
analytical_section: '9B20A',
|
||||||
|
code: '705200'
|
||||||
|
},
|
||||||
|
plan_file_attributes: {
|
||||||
|
_destroy: false,
|
||||||
|
attachment_files: expect.any(FileList)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
expect(beforeSubmit).toHaveBeenCalledWith(expect.objectContaining(expected));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -2,10 +2,10 @@
|
|||||||
"references": [
|
"references": [
|
||||||
{ "path": "../../" }
|
{ "path": "../../" }
|
||||||
],
|
],
|
||||||
"include": ["components/**/*", "__fixtures__/**/*"],
|
"include": ["components/**/*", "__fixtures__/**/*", "__lib__/**/*"],
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"jsx": "react-jsx",
|
"jsx": "react-jsx",
|
||||||
"target": "es2015",
|
"target": "ES2015",
|
||||||
"module": "ES2020",
|
"module": "ES2020",
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node",
|
||||||
"baseUrl": "../../app/frontend/src/javascript"
|
"baseUrl": "../../app/frontend/src/javascript"
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
"module": "ES2020",
|
"module": "ES2020",
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node",
|
||||||
"sourceMap": true,
|
"sourceMap": true,
|
||||||
"target": "es2015",
|
"target": "ES2015",
|
||||||
"jsx": "react-jsx",
|
"jsx": "react-jsx",
|
||||||
"noEmit": true,
|
"noEmit": true,
|
||||||
"allowSyntheticDefaultImports": true,
|
"allowSyntheticDefaultImports": true,
|
||||||
|
Loading…
Reference in New Issue
Block a user