Skip to content
65 changes: 32 additions & 33 deletions src/actions/badge-actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -504,11 +504,10 @@ export const getViewTypes =

export const getViewType = (viewTypeId) => async (dispatch, getState) => {
const { currentSummitState } = getState();
dispatch(startLoading());
const accessToken = await getAccessTokenSafely();
const { currentSummit } = currentSummitState;

dispatch(startLoading());

const params = {
access_token: accessToken
};
Expand All @@ -520,9 +519,7 @@ export const getViewType = (viewTypeId) => async (dispatch, getState) => {
snackbarErrorHandler
)(params)(dispatch)
.catch(() => {})
.finally(() => {
dispatch(stopLoading());
});
.finally(() => dispatch(stopLoading()));
};

export const resetViewTypeForm = () => (dispatch) => {
Expand All @@ -531,54 +528,56 @@ export const resetViewTypeForm = () => (dispatch) => {

export const saveViewType = (entity) => async (dispatch, getState) => {
const { currentSummitState } = getState();
dispatch(startLoading());
const accessToken = await getAccessTokenSafely();
Comment thread
tomrndom marked this conversation as resolved.
Resolved
const { currentSummit } = currentSummitState;

const params = {
access_token: accessToken
};

dispatch(startLoading());

const normalizedEntity = normalizeViewType(entity);

if (entity.id) {
putRequest(
return putRequest(
createAction(UPDATE_VIEW_TYPE),
createAction(VIEW_TYPE_UPDATED),
`${window.API_BASE_URL}/api/v1/summits/${currentSummit.id}/badge-view-types/${entity.id}`,
normalizedEntity,
snackbarErrorHandler,
entity
)(params)(dispatch).then(() => {
dispatch(
showSuccessMessage(T.translate("edit_view_type.view_type_saved"))
);
});
} else {
const success_message = {
title: T.translate("general.done"),
html: T.translate("edit_view_type.view_type_created"),
type: "success"
};
)(params)(dispatch)
.then(() => {
dispatch(
snackbarSuccessHandler({
html: T.translate("edit_view_type.view_type_saved")
})
);
})
.catch(() => {})
.finally(() => dispatch(stopLoading()));
}

postRequest(
createAction(UPDATE_VIEW_TYPE),
createAction(VIEW_TYPE_ADDED),
`${window.API_BASE_URL}/api/v1/summits/${currentSummit.id}/badge-view-types`,
normalizedEntity,
snackbarErrorHandler,
entity
)(params)(dispatch).then((payload) => {
return postRequest(
createAction(UPDATE_VIEW_TYPE),
createAction(VIEW_TYPE_ADDED),
`${window.API_BASE_URL}/api/v1/summits/${currentSummit.id}/badge-view-types`,
normalizedEntity,
snackbarErrorHandler,
entity
)(params)(dispatch)
.then((payload) => {
dispatch(
showMessage(success_message, () => {
history.push(
`/app/summits/${currentSummit.id}/view-types/${payload.response.id}`
);
snackbarSuccessHandler({
html: T.translate("edit_view_type.view_type_created")
})
);
});
}
history.push(
`/app/summits/${currentSummit.id}/view-types/${payload.response.id}`
);
})
.catch(() => {})
.finally(() => dispatch(stopLoading()));
};

export const deleteViewType = (viewTypeId) => async (dispatch, getState) => {
Expand Down
93 changes: 93 additions & 0 deletions src/components/forms/__tests__/view-type-form.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import React from "react";
import { render, screen, waitFor } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import "@testing-library/jest-dom";
import ViewTypeForm from "../view-type-form";

jest.mock("i18n-react/dist/i18n-react", () => ({
__esModule: true,
default: { translate: (key) => key }
}));

jest.mock(
"openstack-uicore-foundation/lib/components/mui/formik-inputs/texteditor",
() => ({
__esModule: true,
default: ({ name }) => {
// eslint-disable-next-line global-require
const { useFormikContext } = require("formik");
return useFormikContext().errors[name] ?? null;
}
})
);

jest.mock("../../../hooks/useScrollToError", () => ({
__esModule: true,
default: jest.fn()
}));

const ENTITY = { id: 3, name: "Card", description: "", is_default: null };

describe("ViewTypeForm", () => {
it("shows server errors and submits the edited entity once while saving", async () => {
const onSubmit = jest.fn(() => new Promise(() => {}));
render(
<ViewTypeForm
entity={ENTITY}
errors={{ name: "name taken" }}
onSubmit={onSubmit}
/>
);

expect(await screen.findByText("name taken")).toBeInTheDocument();

await userEvent.type(
screen.getByRole("textbox", { name: /edit_view_type.name/ }),
"Print"
);
await userEvent.click(screen.getByRole("checkbox"));
await userEvent.click(screen.getByRole("button", { name: "general.save" }));

await waitFor(() =>
expect(onSubmit).toHaveBeenCalledWith({
...ENTITY,
name: "CardPrint",
is_default: true
})
);
expect(screen.getByRole("button", { name: "general.save" })).toBeDisabled();
expect(onSubmit).toHaveBeenCalledTimes(1);
});

it("blocks submit on values the API rejects", async () => {
const onSubmit = jest.fn();
const { rerender } = render(
<ViewTypeForm
entity={{ ...ENTITY, name: "Card Print" }}
onSubmit={onSubmit}
/>
);

await userEvent.click(screen.getByRole("button", { name: "general.save" }));
expect(
await screen.findByText("validation.single_word")
).toBeInTheDocument();

rerender(<ViewTypeForm entity={{ name: "Card" }} onSubmit={onSubmit} />);
await userEvent.click(screen.getByRole("button", { name: "general.save" }));
expect(await screen.findByText("validation.required")).toBeInTheDocument();

rerender(
<ViewTypeForm
entity={{ ...ENTITY, description: `<p>${"a".repeat(250)}</p>` }}
onSubmit={onSubmit}
/>
);
await userEvent.click(screen.getByRole("button", { name: "general.save" }));
expect(
await screen.findByText("validation.max_length")
).toBeInTheDocument();

expect(onSubmit).not.toHaveBeenCalled();
});
});
Loading
Loading