Minor improvements (#1924)

* Add basic tests

* Test if qs is preserved

* Preserve querystring

* Improve import performance
This commit is contained in:
Dominik Żegleń 2022-04-27 14:57:10 +02:00 committed by GitHub
parent fbf57bbbb1
commit 3e180c8d17
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 50 additions and 31 deletions

View file

@ -14,6 +14,7 @@ export interface ExitFormDialogData {
shouldBlockNavigation: () => boolean; shouldBlockNavigation: () => boolean;
setIsSubmitting: (value: boolean) => void; setIsSubmitting: (value: boolean) => void;
submit: () => SubmitPromise; submit: () => SubmitPromise;
leave: () => void;
setIsSubmitDisabled: (value: boolean) => void; setIsSubmitDisabled: (value: boolean) => void;
} }
@ -41,6 +42,7 @@ export const ExitFormDialogContext = React.createContext<ExitFormDialogData>({
shouldBlockNavigation: () => false, shouldBlockNavigation: () => false,
setIsSubmitting: () => undefined, setIsSubmitting: () => undefined,
submit: () => Promise.resolve([]), submit: () => Promise.resolve([]),
leave: () => undefined,
setIsSubmitDisabled: () => undefined setIsSubmitDisabled: () => undefined
}); });
@ -69,9 +71,9 @@ export function useExitFormDialogProvider() {
const isSubmitting = useRef(defaultValues.isSubmitting); const isSubmitting = useRef(defaultValues.isSubmitting);
const formsData = useRef<FormsData>({}); const formsData = useRef<FormsData>({});
const blockNav = useRef(defaultValues.blockNav); const blockNav = useRef(defaultValues.blockNav);
const navAction = useRef(defaultValues.navAction); const navAction = useRef<typeof history.location>(defaultValues.navAction);
const enableExitDialog = useRef(defaultValues.enableExitDialog); const enableExitDialog = useRef(defaultValues.enableExitDialog);
const currentPath = useRef(window.location.pathname); const currentLocation = useRef(history.location);
const setIsSubmitting = (value: boolean) => { const setIsSubmitting = (value: boolean) => {
setEnableExitDialog(!value); setEnableExitDialog(!value);
@ -91,8 +93,8 @@ export function useExitFormDialogProvider() {
formsData.current = defaultValues.formsData; formsData.current = defaultValues.formsData;
}; };
const setCurrentPath = (newPath: string) => { const setCurrentLocation = (newLocation: typeof history.location) => {
currentPath.current = newPath; currentLocation.current = newLocation;
}; };
const setFormData = (id: symbol, newData: Partial<FormData>) => { const setFormData = (id: symbol, newData: Partial<FormData>) => {
@ -156,10 +158,10 @@ export function useExitFormDialogProvider() {
return blockNav.current; return blockNav.current;
}; };
const isOnlyQuerying = transition => const isOnlyQuerying = (transition: typeof history.location) =>
// wee need to compare to current path and not window location // We need to compare to current path and not window location
// so it works with browser back button as well // so it works with browser back button as well
transition.pathname === currentPath.current; transition.pathname === currentLocation.current.pathname;
const handleNavigationBlock = () => { const handleNavigationBlock = () => {
const unblock = history.block(transition => { const unblock = history.block(transition => {
@ -179,7 +181,7 @@ export function useExitFormDialogProvider() {
} }
setStateDefaultValues(); setStateDefaultValues();
setCurrentPath(transition.pathname); setCurrentLocation(transition);
return null; return null;
}); });
@ -192,10 +194,10 @@ export function useExitFormDialogProvider() {
setBlockNav(false); setBlockNav(false);
setDefaultFormsData(); setDefaultFormsData();
setCurrentPath(navAction.current.pathname); setCurrentLocation(navAction.current);
// because our useNavigator navigate action may be blocked // because our useNavigator navigate action may be blocked
// by exit dialog we want to avoid using it doing this transition // by exit dialog we want to avoid using it doing this transition
routerHistory.push(navAction.current.pathname); routerHistory.push(navAction.current.pathname + navAction.current.search);
setStateDefaultValues(); setStateDefaultValues();
}; };
@ -250,7 +252,8 @@ export function useExitFormDialogProvider() {
setExitDialogSubmitRef: setSubmitRef, setExitDialogSubmitRef: setSubmitRef,
setIsSubmitting, setIsSubmitting,
submit: handleSubmit, submit: handleSubmit,
setIsSubmitDisabled setIsSubmitDisabled,
leave: handleLeave
}; };
return { return {

View file

@ -150,4 +150,27 @@ describe("useExitFormDialog", () => {
expect(result.current.exit.shouldBlockNavigation()).toBe(true); expect(result.current.exit.shouldBlockNavigation()).toBe(true);
expect(result.current.history.location.pathname).toBe(initialPath); expect(result.current.history.location.pathname).toBe(initialPath);
}); });
it("navigates to full url with querystring", async () => {
// Given
const submitFn = jest.fn(() => Promise.resolve([]));
const { result } = setup(submitFn);
const qs = "?param=value";
const targetPathWithQs = targetPath + qs;
// When
act(() => {
result.current.form.change({
target: { name: "field", value: "something" }
});
});
act(() => {
result.current.history.push(targetPathWithQs);
result.current.exit.leave();
});
// Then
expect(result.current.history.location.pathname).toBe(targetPath);
expect(result.current.history.location.search).toBe(qs);
});
}); });

View file

@ -8,14 +8,7 @@ import {
} from "./ExitFormDialogProvider"; } from "./ExitFormDialogProvider";
export interface UseExitFormDialogResult export interface UseExitFormDialogResult
extends Pick< extends Omit<ExitFormDialogData, "setIsDirty" | "setExitDialogSubmitRef">,
ExitFormDialogData,
| "setEnableExitDialog"
| "shouldBlockNavigation"
| "setIsSubmitting"
| "setIsSubmitDisabled"
| "submit"
>,
WithFormId { WithFormId {
setIsDirty: (isDirty: boolean) => void; setIsDirty: (isDirty: boolean) => void;
setExitDialogSubmitRef: (submitFn: SubmitFn) => void; setExitDialogSubmitRef: (submitFn: SubmitFn) => void;

View file

@ -13,7 +13,6 @@ import { IntlShape } from "react-intl";
import { MultiAutocompleteChoiceType } from "./components/MultiAutocompleteSelectField"; import { MultiAutocompleteChoiceType } from "./components/MultiAutocompleteSelectField";
import { AddressType, AddressTypeInput } from "./customers/types"; import { AddressType, AddressTypeInput } from "./customers/types";
import { AddressFragment } from "./graphql";
import { import {
commonStatusMessages, commonStatusMessages,
errorMessages, errorMessages,
@ -397,16 +396,6 @@ export function findInEnum<TEnum extends {}>(needle: string, haystack: TEnum) {
throw new Error(`Key ${needle} not found in enum`); throw new Error(`Key ${needle} not found in enum`);
} }
export function addressToAddressInput<T>(
address: T & AddressFragment
): AddressInput {
const { id, __typename, ...rest } = address;
return {
...rest,
country: findInEnum(address.country.code, CountryCode)
};
}
export function findValueInEnum<TEnum extends {}>( export function findValueInEnum<TEnum extends {}>(
needle: string, needle: string,
haystack: TEnum haystack: TEnum

View file

@ -1,5 +1,6 @@
import { IMoney, subtractMoney } from "@saleor/components/Money"; import { IMoney, subtractMoney } from "@saleor/components/Money";
import { import {
AddressFragment,
AddressInput, AddressInput,
CountryCode, CountryCode,
FulfillmentStatus, FulfillmentStatus,
@ -12,7 +13,7 @@ import {
WarehouseFragment WarehouseFragment
} from "@saleor/graphql"; } from "@saleor/graphql";
import { FormsetData } from "@saleor/hooks/useFormset"; import { FormsetData } from "@saleor/hooks/useFormset";
import { addressToAddressInput } from "@saleor/misc"; import { findInEnum } from "@saleor/misc";
import { import {
LineItemData, LineItemData,
@ -300,6 +301,16 @@ export const isStockError = (
return isQuantityLargerThanAvailable || isError; return isQuantityLargerThanAvailable || isError;
}; };
export function addressToAddressInput<T>(
address: T & AddressFragment
): AddressInput {
const { id, __typename, ...rest } = address;
return {
...rest,
country: findInEnum(address.country.code, CountryCode)
};
}
export const getVariantSearchAddress = ( export const getVariantSearchAddress = (
order: OrderDetailsFragment order: OrderDetailsFragment
): AddressInput => { ): AddressInput => {