@lookiero/checkout 6.6.0 → 7.0.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. package/dist/index.d.ts +0 -8
  2. package/dist/index.js +0 -3
  3. package/dist/public/public/assets/adaptive-icon.png +0 -0
  4. package/dist/public/public/assets/favicon.png +0 -0
  5. package/dist/public/public/assets/icon.png +0 -0
  6. package/dist/public/public/assets/splash.png +0 -0
  7. package/dist/public/public/images/not-found.png +0 -0
  8. package/dist/src/Expo.js +0 -2
  9. package/dist/src/ExpoRoot.js +8 -1
  10. package/dist/src/infrastructure/ab-testing/kameleoonEnvironment.d.ts +6 -2
  11. package/dist/src/infrastructure/delivery/baseBootstrap.js +0 -2
  12. package/dist/src/infrastructure/ui/components/layouts/layout/Layout.d.ts +21 -0
  13. package/dist/src/infrastructure/ui/components/layouts/layout/Layout.js +1 -0
  14. package/dist/src/infrastructure/ui/components/layouts/layout/components/footer/Footer.d.ts +6 -0
  15. package/dist/src/infrastructure/ui/components/layouts/layout/components/footer/Footer.js +4 -0
  16. package/dist/src/infrastructure/ui/components/layouts/layout/components/header/Header.d.ts +6 -0
  17. package/dist/src/infrastructure/ui/components/layouts/layout/components/header/Header.js +5 -0
  18. package/dist/src/infrastructure/ui/components/layouts/layout/components/header/Header.style.d.ts +4 -0
  19. package/dist/src/infrastructure/ui/components/layouts/layout/components/header/Header.style.js +19 -0
  20. package/dist/src/infrastructure/ui/components/layouts/layout/dummyLayout/DummyLayout.d.ts +3 -0
  21. package/dist/src/infrastructure/ui/components/layouts/layout/dummyLayout/DummyLayout.js +18 -0
  22. package/dist/src/infrastructure/ui/components/layouts/layout/dummyLayout/DummyLayout.style.d.ts +12 -0
  23. package/dist/src/infrastructure/ui/components/layouts/layout/dummyLayout/DummyLayout.style.js +13 -0
  24. package/dist/src/infrastructure/ui/components/organisms/returnQuestions/components/hostDefaultReturnQuestionItem/HostDefaultReturnQuestionItem.js +10 -1
  25. package/dist/src/infrastructure/ui/components/organisms/returnQuestions/components/hostDefaultReturnQuestionItem/HostDefaultReturnQuestionItem.style.d.ts +7 -1
  26. package/dist/src/infrastructure/ui/components/organisms/returnQuestions/components/hostDefaultReturnQuestionItem/HostDefaultReturnQuestionItem.style.js +7 -1
  27. package/dist/src/infrastructure/ui/components/organisms/returnQuestions/components/textareaReturnQuestionItem/TextareaReturnQuestionItem.js +7 -2
  28. package/dist/src/infrastructure/ui/components/templates/header/defaultHeader/DefaultHeader.d.ts +6 -0
  29. package/dist/src/infrastructure/ui/components/templates/header/defaultHeader/DefaultHeader.js +11 -0
  30. package/dist/src/infrastructure/ui/components/templates/header/defaultHeader/DefaultHeader.style.d.ts +8 -0
  31. package/dist/src/infrastructure/ui/components/templates/header/defaultHeader/DefaultHeader.style.js +11 -0
  32. package/dist/src/infrastructure/ui/hooks/useNewFeedbackExperiment.d.ts +11 -0
  33. package/dist/src/infrastructure/ui/hooks/useNewFeedbackExperiment.js +49 -0
  34. package/dist/src/infrastructure/ui/routing/Routing.js +13 -13
  35. package/dist/src/infrastructure/ui/views/checkout/Checkout.js +4 -4
  36. package/dist/src/infrastructure/ui/views/feedback/Feedback.d.ts +2 -2
  37. package/dist/src/infrastructure/ui/views/feedback/components/checkoutQuestionsForm/CheckoutQuestionsForm.style.d.ts +7 -0
  38. package/dist/src/infrastructure/ui/views/feedback/components/checkoutQuestionsForm/CheckoutQuestionsForm.style.js +10 -0
  39. package/dist/src/infrastructure/ui/views/item/Item.js +33 -4
  40. package/dist/src/infrastructure/ui/views/item/components/returnQuestionsForm/ReturnQuestionsForm.d.ts +11 -0
  41. package/dist/src/infrastructure/ui/views/item/components/returnQuestionsForm/ReturnQuestionsForm.js +40 -0
  42. package/dist/src/infrastructure/ui/views/item/components/returnQuestionsForm/ReturnQuestionsForm.style.d.ts +12 -0
  43. package/dist/src/infrastructure/ui/views/item/components/returnQuestionsForm/ReturnQuestionsForm.style.js +15 -0
  44. package/dist/src/infrastructure/ui/views/return/Return.js +127 -8
  45. package/dist/src/infrastructure/ui/views/return/components/productVariantPreview/ProductVariantPreview.js +7 -5
  46. package/dist/src/infrastructure/ui/views/summary/Summary.js +4 -4
  47. package/dist/src/infrastructure/ui/views/summary/components/stickyPricing/StickyPricing.d.ts +13 -0
  48. package/dist/src/infrastructure/ui/views/summary/components/stickyPricing/StickyPricing.js +9 -0
  49. package/dist/src/infrastructure/ui/views/summary/components/stickyPricing/StickyPricing.style.d.ts +7 -0
  50. package/dist/src/infrastructure/ui/views/summary/components/stickyPricing/StickyPricing.style.js +10 -0
  51. package/dist/src/version.d.ts +1 -1
  52. package/dist/src/version.js +1 -1
  53. package/index.ts +0 -17
  54. package/package.json +1 -3
  55. package/src/Expo.tsx +0 -3
  56. package/src/ExpoRoot.tsx +8 -1
  57. package/src/infrastructure/ab-testing/kameleoonEnvironment.ts +7 -3
  58. package/src/infrastructure/delivery/baseBootstrap.ts +0 -5
  59. package/src/infrastructure/ui/components/organisms/returnQuestions/components/hostDefaultReturnQuestionItem/HostDefaultReturnQuestionItem.style.ts +7 -1
  60. package/src/infrastructure/ui/components/organisms/returnQuestions/components/hostDefaultReturnQuestionItem/HostDefaultReturnQuestionItem.test.tsx +5 -0
  61. package/src/infrastructure/ui/components/organisms/returnQuestions/components/hostDefaultReturnQuestionItem/HostDefaultReturnQuestionItem.tsx +17 -2
  62. package/src/infrastructure/ui/components/organisms/returnQuestions/components/textareaReturnQuestionItem/TextareaReturnQuestionItem.test.tsx +5 -0
  63. package/src/infrastructure/ui/components/organisms/returnQuestions/components/textareaReturnQuestionItem/TextareaReturnQuestionItem.tsx +20 -11
  64. package/src/infrastructure/ui/hooks/useNewFeedbackExperiment.test.tsx +84 -0
  65. package/src/infrastructure/ui/hooks/useNewFeedbackExperiment.tsx +82 -0
  66. package/src/infrastructure/ui/routing/Routing.tsx +18 -21
  67. package/src/infrastructure/ui/views/checkout/Checkout.tsx +6 -6
  68. package/src/infrastructure/ui/views/feedback/Feedback.tsx +2 -2
  69. package/src/infrastructure/ui/views/item/Item.test.tsx +62 -6
  70. package/src/infrastructure/ui/views/item/Item.tsx +48 -5
  71. package/src/infrastructure/ui/views/item/components/returnQuestionsForm/ReturnQuestionsForm.style.ts +18 -0
  72. package/src/infrastructure/ui/views/item/components/returnQuestionsForm/ReturnQuestionsForm.tsx +79 -0
  73. package/src/infrastructure/ui/views/return/Return.tsx +200 -12
  74. package/src/infrastructure/ui/views/return/components/productVariantPreview/ProductVariantPreview.tsx +7 -12
  75. package/src/infrastructure/ui/views/summary/Summary.tsx +6 -6
  76. package/dist/src/infrastructure/ui/views/return/components/returnQuestionsForm/ReturnQuestionsForm.d.ts +0 -15
  77. package/dist/src/infrastructure/ui/views/return/components/returnQuestionsForm/ReturnQuestionsForm.js +0 -112
  78. package/src/infrastructure/projection/checkout/react/useViewIsCheckoutAccessibleByCustomerId.test.ts +0 -45
  79. package/src/infrastructure/projection/checkout/react/useViewIsCheckoutAccessibleByCustomerId.ts +0 -33
  80. package/src/infrastructure/ui/routing/CheckoutAccessibilityMiddleware.test.tsx +0 -74
  81. package/src/infrastructure/ui/routing/CheckoutAccessibilityMiddleware.tsx +0 -39
  82. package/src/infrastructure/ui/views/return/Return.test.tsx +0 -54
  83. package/src/infrastructure/ui/views/return/components/productVariantPreview/ProductVariantPreview.test.tsx +0 -32
  84. package/src/infrastructure/ui/views/return/components/productVariantPreview/__snapshots__/ProductVariantPreview.test.tsx.snap +0 -221
  85. package/src/infrastructure/ui/views/return/components/returnQuestionsForm/ReturnQuestionsForm.test.tsx +0 -95
  86. package/src/infrastructure/ui/views/return/components/returnQuestionsForm/ReturnQuestionsForm.tsx +0 -184
  87. package/src/projection/checkout/viewIsCheckoutAccessibleByCustomerId.test.ts +0 -54
  88. package/src/projection/checkout/viewIsCheckoutAccessibleByCustomerId.ts +0 -46
  89. /package/dist/src/infrastructure/ui/views/return/{components/returnQuestionsForm/ReturnQuestionsForm.style.d.ts → Return.style.d.ts} +0 -0
  90. /package/dist/src/infrastructure/ui/views/return/{components/returnQuestionsForm/ReturnQuestionsForm.style.js → Return.style.js} +0 -0
  91. /package/src/infrastructure/ui/views/return/{components/returnQuestionsForm/ReturnQuestionsForm.style.ts → Return.style.ts} +0 -0
@@ -1,6 +1,10 @@
1
1
  import React from "react";
2
2
  import { Text, View } from "@lookiero/aurora";
3
3
  import { useI18nMessage } from "@lookiero/i18n-react";
4
+ import {
5
+ NewFeedbackExperimentVariation,
6
+ useNewFeedbackExperiment,
7
+ } from "../../../../../hooks/useNewFeedbackExperiment";
4
8
  import { I18nMessages } from "../../../../../i18n/i18n";
5
9
  import { ReturnQuestionItem, ReturnQuestionItemProps } from "../ReturnQuestionItem";
6
10
  import { style } from "./HostDefaultReturnQuestionItem.style";
@@ -9,10 +13,21 @@ const HostDefaultReturnQuestionItem: ReturnQuestionItem = ({ returnQuestion, chi
9
13
  const titleText = useI18nMessage({ id: returnQuestion.name });
10
14
  const isAllOptions = returnQuestion.name === I18nMessages.RETURN_QUESTION_MAIN_ALL_OPINION;
11
15
 
16
+ /* Kameleoon experiment */
17
+ const newFeedbackVariation = useNewFeedbackExperiment();
18
+ const isReturnPage = newFeedbackVariation === NewFeedbackExperimentVariation.RETURN_PAGE;
19
+ /* Kameleoon experiment */
20
+
12
21
  return (
13
22
  <>
14
- {titleText && titleText !== " " && !isAllOptions ? (
15
- <View style={style.title}>
23
+ {titleText && titleText !== " " ? (
24
+ <View
25
+ style={[
26
+ style.title,
27
+ isAllOptions ? style.allOptionsTitle : undefined,
28
+ isReturnPage ? style.formTitle : undefined,
29
+ ]}
30
+ >
16
31
  <Text level={3} action>
17
32
  {titleText}
18
33
  </Text>
@@ -12,6 +12,11 @@ jest.mock("../../behaviors/useReturnQuestionFeedback", () => ({
12
12
  useReturnQuestionFeedbackForReturnQuestion: () => ({ feedback: "", onChange: mockOnChange }),
13
13
  }));
14
14
 
15
+ jest.mock("../../../../../hooks/useNewFeedbackExperiment", () => ({
16
+ ...jest.requireActual("../../../../../hooks/useNewFeedbackExperiment"),
17
+ useNewFeedbackExperiment: () => "control",
18
+ }));
19
+
15
20
  const returnQuestionParent = {
16
21
  id: "0ad1dba8-b02c-4121-a1e3-981f1c30800d",
17
22
  } as ReturnQuestionProjection;
@@ -2,6 +2,10 @@ import React, { useCallback, useMemo } from "react";
2
2
  import { View } from "@lookiero/aurora";
3
3
  import { useIntl } from "@lookiero/i18n-react";
4
4
  import { InputField } from "../../../../../../../shared/ui/components/molecules/inputField/InputField";
5
+ import {
6
+ NewFeedbackExperimentVariation,
7
+ useNewFeedbackExperiment,
8
+ } from "../../../../../hooks/useNewFeedbackExperiment";
5
9
  import { useReturnQuestionFeedbackForReturnQuestion } from "../../behaviors/useReturnQuestionFeedback";
6
10
  import { ReturnQuestionItem, ReturnQuestionItemProps } from "../ReturnQuestionItem";
7
11
  import { style } from "./TextareaReturnQuestionItem.style";
@@ -13,6 +17,11 @@ const TextareaReturnQuestionItem: ReturnQuestionItem = ({
13
17
  }: ReturnQuestionItemProps) => {
14
18
  const { formatMessage } = useIntl();
15
19
 
20
+ /* Kameleoon experiment */
21
+ const newFeedbackVariation = useNewFeedbackExperiment();
22
+ const isReturnPage = newFeedbackVariation === NewFeedbackExperimentVariation.RETURN_PAGE;
23
+ /* Kameleoon experiment */
24
+
16
25
  const placeholderText = useMemo(
17
26
  () => (returnQuestion.placeholder ? formatMessage({ id: returnQuestion.placeholder }) : ""),
18
27
  [formatMessage, returnQuestion.placeholder],
@@ -24,18 +33,18 @@ const TextareaReturnQuestionItem: ReturnQuestionItem = ({
24
33
  [onChange, returnQuestionParent.id],
25
34
  );
26
35
 
27
- return (
28
- <View style={style.wrapper}>
29
- <InputField
30
- label={placeholderText}
31
- placeholder={placeholderText}
32
- testID={testID}
33
- value={feedback}
34
- multiline
35
- onChange={handleOnChange}
36
- />
37
- </View>
36
+ const fieldComponent = (
37
+ <InputField
38
+ label={placeholderText}
39
+ placeholder={placeholderText}
40
+ testID={testID}
41
+ value={feedback}
42
+ multiline
43
+ onChange={handleOnChange}
44
+ />
38
45
  );
46
+
47
+ return isReturnPage ? <View style={style.wrapper}>{fieldComponent}</View> : fieldComponent;
39
48
  };
40
49
 
41
50
  export { TextareaReturnQuestionItem };
@@ -0,0 +1,84 @@
1
+ import { renderHook, waitFor } from "@testing-library/react-native";
2
+ import React, { FC } from "react";
3
+ import { Variation, useAssignedVariationByExperimentId } from "@lookiero/sty-psp-ab-testing";
4
+ import { Segment } from "@lookiero/sty-psp-segment";
5
+ import { CheckoutProjection } from "../../../projection/checkout/checkout";
6
+ import { Country } from "../../../projection/shared/country";
7
+ import { KameleoonEnvironment } from "../../ab-testing/kameleoonEnvironment";
8
+ import {
9
+ NewFeedbackExperimentProvider,
10
+ NewFeedbackExperimentVariation,
11
+ useNewFeedbackExperiment as sut,
12
+ } from "./useNewFeedbackExperiment";
13
+
14
+ const mockKameleoon: KameleoonEnvironment = {
15
+ siteCode: "aplm4v3ckn",
16
+ experiments: {
17
+ newFeedback: {
18
+ id: "245000",
19
+ variations: {
20
+ v1: "964072",
21
+ },
22
+ },
23
+ },
24
+ };
25
+
26
+ const country = Country.ES;
27
+ const segment = Segment.WOMEN;
28
+ const customerId = "1f410890-b3e1-49d2-9950-2ff89182cb79";
29
+ const mockTrackAssignedVariation = jest.fn();
30
+ // useStaticInfo
31
+
32
+ jest.mock("../../tracking/useTrackAssignedVariationByExperiment", () => ({
33
+ useTrackAssignedVariationByExperiment: () => mockTrackAssignedVariation,
34
+ }));
35
+
36
+ jest.mock("@lookiero/sty-psp-ab-testing");
37
+
38
+ jest.mock("./useStaticInfo", () => ({
39
+ useStaticInfo: () => ({ kameleoon: mockKameleoon, customer: { customerId, country, segment } }),
40
+ }));
41
+
42
+ jest.mock("../../projection/checkout/react/useViewFirstAvailableCheckoutByCustomerId", () => ({
43
+ useViewFirstAvailableCheckoutByCustomerId: () => [
44
+ { id: "3db6984e-c8d2-4242-a795-ab5babb25e8c" } as CheckoutProjection,
45
+ ],
46
+ }));
47
+
48
+ interface WrapperProps {
49
+ readonly children: JSX.Element;
50
+ }
51
+
52
+ const Wrapper: FC<WrapperProps> = ({ children }) => (
53
+ <NewFeedbackExperimentProvider>{children}</NewFeedbackExperimentProvider>
54
+ );
55
+
56
+ beforeEach(() => {
57
+ mockTrackAssignedVariation.mockClear();
58
+ });
59
+
60
+ describe("useNewFeedbackExperiment hook", () => {
61
+ it("returns 'control' as variation", async () => {
62
+ const assignedVariation: Variation = { id: 0, name: "Control" };
63
+ (useAssignedVariationByExperimentId as jest.Mock).mockReturnValue({ assignedVariation });
64
+
65
+ const { result } = renderHook(() => sut(), { wrapper: Wrapper });
66
+
67
+ await waitFor(() => expect(result.current).toBe(NewFeedbackExperimentVariation.CONTROL));
68
+ await waitFor(() => {
69
+ expect(mockTrackAssignedVariation).toHaveBeenCalledWith({ assignedVariation });
70
+ });
71
+ });
72
+
73
+ it("returns 'return_page' as variation", async () => {
74
+ const assignedVariation: Variation = { id: 964072, name: "Variation 1" };
75
+ (useAssignedVariationByExperimentId as jest.Mock).mockReturnValue({ assignedVariation });
76
+
77
+ const { result } = renderHook(() => sut(), { wrapper: Wrapper });
78
+
79
+ await waitFor(() => expect(result.current).toBe(NewFeedbackExperimentVariation.RETURN_PAGE));
80
+ await waitFor(() => {
81
+ expect(mockTrackAssignedVariation).toHaveBeenCalledWith({ assignedVariation });
82
+ });
83
+ });
84
+ });
@@ -0,0 +1,82 @@
1
+ import React, { createContext, FC, ReactNode, useContext, useEffect, useMemo, useRef } from "react";
2
+ import invariant from "tiny-invariant";
3
+ import { Spinner } from "@lookiero/aurora";
4
+ import { useAssignedVariationByExperimentId } from "@lookiero/sty-psp-ab-testing";
5
+ import { useViewFirstAvailableCheckoutByCustomerId } from "../../projection/checkout/react/useViewFirstAvailableCheckoutByCustomerId";
6
+ import { useTrackAssignedVariationByExperiment } from "../../tracking/useTrackAssignedVariationByExperiment";
7
+ import { useStaticInfo } from "./useStaticInfo";
8
+
9
+ enum NewFeedbackExperimentVariation {
10
+ CONTROL = "control",
11
+ RETURN_PAGE = "return_page",
12
+ }
13
+
14
+ interface NewFeedbackExperiment {
15
+ readonly variation: NewFeedbackExperimentVariation;
16
+ }
17
+
18
+ const NewFeedbackExperimentContext = createContext<NewFeedbackExperiment>(null as unknown as NewFeedbackExperiment);
19
+
20
+ interface NewFeedbackExperimentProviderProps {
21
+ readonly children: ReactNode;
22
+ }
23
+
24
+ const NewFeedbackExperimentProvider: FC<NewFeedbackExperimentProviderProps> = ({ children }) => {
25
+ const {
26
+ kameleoon: {
27
+ experiments: {
28
+ newFeedback: { id: newFeedbackId, variations },
29
+ },
30
+ },
31
+ customer: { customerId, country, segment },
32
+ } = useStaticInfo();
33
+ const [checkout] = useViewFirstAvailableCheckoutByCustomerId({ customerId });
34
+ const { assignedVariation: newFeedbackVariation } = useAssignedVariationByExperimentId({
35
+ experimentId: newFeedbackId,
36
+ });
37
+ const trackAssignedVariation = useTrackAssignedVariationByExperiment({
38
+ checkoutId: checkout?.id,
39
+ country,
40
+ segment,
41
+ experimentId: newFeedbackId,
42
+ });
43
+
44
+ const value = useMemo(
45
+ () => ({
46
+ variation:
47
+ newFeedbackVariation?.id === Number(variations.v1)
48
+ ? NewFeedbackExperimentVariation.RETURN_PAGE
49
+ : NewFeedbackExperimentVariation.CONTROL,
50
+ }),
51
+ [newFeedbackVariation?.id, variations.v1],
52
+ );
53
+
54
+ const assignedVariantTracked = useRef(false);
55
+ useEffect(() => {
56
+ if (assignedVariantTracked.current || !newFeedbackVariation || !checkout?.id) {
57
+ return;
58
+ }
59
+
60
+ trackAssignedVariation({ assignedVariation: newFeedbackVariation });
61
+ assignedVariantTracked.current = true;
62
+ }, [checkout?.id, newFeedbackVariation, trackAssignedVariation]);
63
+
64
+ if (!checkout) {
65
+ return <Spinner />;
66
+ }
67
+
68
+ return <NewFeedbackExperimentContext.Provider value={value}>{children}</NewFeedbackExperimentContext.Provider>;
69
+ };
70
+
71
+ const useNewFeedbackExperiment = () => {
72
+ const newFeedbackExperiment = useContext(NewFeedbackExperimentContext);
73
+
74
+ invariant(
75
+ newFeedbackExperiment,
76
+ "Your are trying to use the useNewFeedbackExperiment hook without wrapping your app with the <NewFeedbackExperimentProvider>.",
77
+ );
78
+
79
+ return newFeedbackExperiment.variation;
80
+ };
81
+
82
+ export { useNewFeedbackExperiment, NewFeedbackExperimentProvider, NewFeedbackExperimentVariation };
@@ -1,4 +1,4 @@
1
- import React, { FC, lazy, memo, Suspense } from "react";
1
+ import React, { FC, memo, Suspense } from "react";
2
2
  import { Navigate, Outlet, useRoutes as reactRouterUseRoutes } from "react-router-native";
3
3
  import { Spinner } from "@lookiero/aurora";
4
4
  import { I18n } from "@lookiero/i18n-react";
@@ -8,23 +8,20 @@ import { Customer } from "../../../projection/shared/customer";
8
8
  import { Order } from "../../../projection/shared/order";
9
9
  import { Subscription } from "../../../projection/shared/subscription";
10
10
  import { KameleoonEnvironment } from "../../ab-testing/kameleoonEnvironment";
11
+ import { NewFeedbackExperimentProvider } from "../hooks/useNewFeedbackExperiment";
11
12
  import { StaticInfoProvider } from "../hooks/useStaticInfo";
12
13
  import { App } from "../views/App";
14
+ import { Checkout } from "../views/checkout/Checkout";
13
15
  import { CheckoutPaymentModal } from "../views/checkout/components/checkoutPaymentModal/CheckoutPaymentModal";
14
- import { CheckoutAccessibilityMiddleware } from "./CheckoutAccessibilityMiddleware";
16
+ import { Feedback } from "../views/feedback/Feedback";
17
+ import { Item } from "../views/item/Item";
18
+ import { Return } from "../views/return/Return";
19
+ import { Summary } from "../views/summary/Summary";
20
+ import { SummaryTabs } from "../views/summaryTabs/SummaryTabs";
15
21
  import { CheckoutMiddleware } from "./CheckoutMiddleware";
16
22
  import { Routes } from "./routes";
17
23
  import { BasePathProvider } from "./useBasePath";
18
24
 
19
- const Item = lazy(() => import("../views/item/Item").then((module) => ({ default: module.Item })));
20
- const Summary = lazy(() => import("../views/summary/Summary").then((module) => ({ default: module.Summary })));
21
- const SummaryTabs = lazy(() =>
22
- import("../views/summaryTabs/SummaryTabs").then((module) => ({ default: module.SummaryTabs })),
23
- );
24
- const Checkout = lazy(() => import("../views/checkout/Checkout").then((module) => ({ default: module.Checkout })));
25
- const Feedback = lazy(() => import("../views/feedback/Feedback").then((module) => ({ default: module.Feedback })));
26
- const Return = lazy(() => import("../views/return/Return").then((module) => ({ default: module.Return })));
27
-
28
25
  interface RoutingProps {
29
26
  readonly basePath?: string;
30
27
  readonly customer: Customer;
@@ -63,19 +60,19 @@ const Routing: FC<RoutingProps> = ({
63
60
  path: "",
64
61
  element: (
65
62
  <BasePathProvider basePath={basePath}>
66
- <CheckoutAccessibilityMiddleware customerId={customer?.customerId} onNotAccessible={onNotAccessible}>
67
- <StaticInfoProvider customer={customer} kameleoon={kameleoon}>
68
- <I18n loader={<Spinner />} locale={locale} onError={onI18nError}>
69
- <Kameleoon loader={<Spinner />} siteCode={kameleoon.siteCode}>
70
- <CheckoutMiddleware customerId={customer?.customerId as string} onNotAccessible={onNotAccessible}>
63
+ <StaticInfoProvider customer={customer} kameleoon={kameleoon}>
64
+ <I18n loader={<Spinner />} locale={locale} onError={onI18nError}>
65
+ <Kameleoon loader={<Spinner />} siteCode={kameleoon.siteCode}>
66
+ <CheckoutMiddleware customerId={customer?.customerId as string} onNotAccessible={onNotAccessible}>
67
+ <NewFeedbackExperimentProvider>
71
68
  <App>
72
69
  <Outlet />
73
70
  </App>
74
- </CheckoutMiddleware>
75
- </Kameleoon>
76
- </I18n>
77
- </StaticInfoProvider>
78
- </CheckoutAccessibilityMiddleware>
71
+ </NewFeedbackExperimentProvider>
72
+ </CheckoutMiddleware>
73
+ </Kameleoon>
74
+ </I18n>
75
+ </StaticInfoProvider>
79
76
  </BasePathProvider>
80
77
  ),
81
78
  children: [
@@ -1,7 +1,7 @@
1
1
  import React, { FC, ReactNode, useCallback, useMemo, useState } from "react";
2
2
  import { LayoutRectangle, Platform, ScrollView, View } from "react-native";
3
3
  import { useNavigate } from "react-router-native";
4
- import { Box, Button, Layout as AuroraLayout, Spinner, Text, useDevice } from "@lookiero/aurora";
4
+ import { Box, Button, Layout, Spinner, Text, useDevice } from "@lookiero/aurora";
5
5
  import { useI18nMessage } from "@lookiero/i18n-react";
6
6
  import { QueryStatus } from "@lookiero/messaging-react";
7
7
  import { Layout as UiLayout, Sticky } from "@lookiero/sty-psp-ui";
@@ -30,7 +30,7 @@ interface CheckoutProps {
30
30
  readonly useRedirect: () => Record<string, string>;
31
31
  }
32
32
 
33
- const Checkout: FC<CheckoutProps> = ({ children, layout: Layout, useRedirect }) => {
33
+ const Checkout: FC<CheckoutProps> = ({ children, layout: UiLayout, useRedirect }) => {
34
34
  const {
35
35
  customer: { customerId, country, segment },
36
36
  } = useStaticInfo();
@@ -99,7 +99,7 @@ const Checkout: FC<CheckoutProps> = ({ children, layout: Layout, useRedirect })
99
99
  }
100
100
 
101
101
  return (
102
- <Layout
102
+ <UiLayout
103
103
  header={<CheckoutHeader onBack={handleOnBack} />}
104
104
  scrollEnabled={false}
105
105
  style={{
@@ -110,7 +110,7 @@ const Checkout: FC<CheckoutProps> = ({ children, layout: Layout, useRedirect })
110
110
  <ScrollView showsVerticalScrollIndicator={false}>
111
111
  {hasReplacedCheckoutItem && <DeliveryBanner />}
112
112
 
113
- <AuroraLayout
113
+ <Layout
114
114
  fullWidth={!screen.L}
115
115
  style={[screen.L && style.desktopLayoutSpacing, !screen.L && { paddingBottom: pricingHeight }]}
116
116
  >
@@ -158,7 +158,7 @@ const Checkout: FC<CheckoutProps> = ({ children, layout: Layout, useRedirect })
158
158
  </View>
159
159
  ) : null}
160
160
  </Box>
161
- </AuroraLayout>
161
+ </Layout>
162
162
  </ScrollView>
163
163
 
164
164
  {pricing && !screen.L ? (
@@ -172,7 +172,7 @@ const Checkout: FC<CheckoutProps> = ({ children, layout: Layout, useRedirect })
172
172
  ) : null}
173
173
 
174
174
  {children}
175
- </Layout>
175
+ </UiLayout>
176
176
  );
177
177
  };
178
178
 
@@ -2,7 +2,7 @@ import React, { FC, useCallback, useEffect, useRef } from "react";
2
2
  import { Spinner } from "@lookiero/aurora";
3
3
  import { CommandStatus, QueryStatus } from "@lookiero/messaging-react";
4
4
  import { useLogger } from "@lookiero/sty-psp-logging";
5
- import { Layout as UiLayout, useScreenSize } from "@lookiero/sty-psp-ui";
5
+ import { Layout, useScreenSize } from "@lookiero/sty-psp-ui";
6
6
  import { CheckoutFeedbackProjection } from "../../../../projection/checkoutFeedback/checkoutFeedback";
7
7
  import { CheckoutQuestionType } from "../../../../projection/checkoutQuestion/checkoutQuestion";
8
8
  import { useGiveCheckoutFeedback } from "../../../domain/checkoutFeedback/react/useGiveCheckoutFeedback";
@@ -28,7 +28,7 @@ interface HandleOnChangedFeedbackFunction {
28
28
  }
29
29
 
30
30
  interface FeedbackProps {
31
- readonly layout: UiLayout;
31
+ readonly layout: Layout;
32
32
  }
33
33
 
34
34
  const Feedback: FC<FeedbackProps> = ({ layout: Layout }) => {
@@ -1,4 +1,4 @@
1
- import { fireEvent, RenderAPI, waitFor, screen } from "@testing-library/react-native";
1
+ import { fireEvent, RenderAPI, waitFor, screen, within } from "@testing-library/react-native";
2
2
  import React from "react";
3
3
  import { CommandStatus, QueryStatus } from "@lookiero/messaging-react";
4
4
  import { Segment } from "@lookiero/sty-psp-segment";
@@ -9,6 +9,7 @@ import { useBookCheckoutBookingForCheckoutItem } from "../../../domain/checkoutB
9
9
  import { useKeepCheckoutItem } from "../../../domain/checkoutItem/react/useKeepCheckoutItem";
10
10
  import { useReplaceCheckoutItem } from "../../../domain/checkoutItem/react/useReplaceCheckoutItem";
11
11
  import { useResetCheckoutItem } from "../../../domain/checkoutItem/react/useResetCheckoutItem";
12
+ import { useReturnCheckoutItem } from "../../../domain/checkoutItem/react/useReturnCheckoutItem";
12
13
  import { bookedProductsVariants as mockBookedProductsVariants } from "../../../projection/bookedProductsVariants/bookedProductsVariants.mock";
13
14
  import { useViewBookedProductsVariantsForCheckoutItem } from "../../../projection/bookedProductsVariants/react/useViewBookedProductsVariantsForCheckoutItem";
14
15
  import { checkout } from "../../../projection/checkout/checkout.mock";
@@ -31,11 +32,10 @@ jest.mock("../../hooks/useStaticInfo", () => ({
31
32
  useStaticInfo: () => ({ customer: { customerId, country, segment } }),
32
33
  }));
33
34
 
34
- const mockNavigate = jest.fn();
35
35
  jest.mock("react-router-native", () => ({
36
36
  ...jest.requireActual("react-router-native"),
37
37
  useLocation: () => jest.fn(),
38
- useNavigate: () => mockNavigate,
38
+ useNavigate: () => jest.fn(),
39
39
  useMatch: () => false,
40
40
  useParams: () => ({ id: mockFirstCheckoutItemId }),
41
41
  }));
@@ -45,6 +45,7 @@ jest.mock("../../../projection/checkout/react/useViewIsSizeChangeEnabledByChecko
45
45
  jest.mock("../../../projection/returnQuestion/react/useListReturnQuestionsByCheckoutItemId");
46
46
  jest.mock("../../../projection/bookedProductsVariants/react/useViewBookedProductsVariantsForCheckoutItem");
47
47
  jest.mock("../../../domain/checkoutBooking/react/useBookCheckoutBookingForCheckoutItem");
48
+ jest.mock("../../../domain/checkoutItem/react/useReturnCheckoutItem");
48
49
  jest.mock("../../../domain/checkoutItem/react/useKeepCheckoutItem");
49
50
  jest.mock("../../../domain/checkoutItem/react/useReplaceCheckoutItem");
50
51
  jest.mock("../../../domain/checkoutItem/react/useResetCheckoutItem");
@@ -59,8 +60,17 @@ jest.mock("../../../tracking/useTrackKeepItem", () => ({
59
60
  jest.mock("../../../tracking/useTrackReplaceItem", () => ({
60
61
  useTrackReplaceItem: () => jest.fn(),
61
62
  }));
63
+ const mockTrackReturnItem = jest.fn();
64
+ jest.mock("../../../tracking/useTrackReturnItem", () => ({
65
+ useTrackReturnItem: () => mockTrackReturnItem,
66
+ }));
62
67
  jest.mock("../../../tracking/useTrackItemPageView");
63
68
 
69
+ jest.mock("../../hooks/useNewFeedbackExperiment", () => ({
70
+ ...jest.requireActual("../../hooks/useNewFeedbackExperiment"),
71
+ useNewFeedbackExperiment: () => "control",
72
+ }));
73
+
64
74
  const mockCheckout = checkout({
65
75
  items: [
66
76
  { id: mockFirstCheckoutItemId, status: CheckoutItemStatus.INITIAL },
@@ -77,6 +87,8 @@ interface RenderItemFunction {
77
87
 
78
88
  const renderItem: RenderItemFunction = () => render(<Item layout={DummyLayout} />);
79
89
 
90
+ beforeEach(() => mockTrackReturnItem.mockClear());
91
+
80
92
  beforeAll(() => {
81
93
  jest.useFakeTimers();
82
94
  });
@@ -98,6 +110,8 @@ describe("Item view", () => {
98
110
  ]);
99
111
  const mockBookCheckoutBookingForCheckoutItem = jest.fn();
100
112
  (useBookCheckoutBookingForCheckoutItem as jest.Mock).mockReturnValue([mockBookCheckoutBookingForCheckoutItem]);
113
+ const mockReturnCheckoutItem = jest.fn();
114
+ (useReturnCheckoutItem as jest.Mock).mockReturnValue([mockReturnCheckoutItem, CommandStatus.IDLE]);
101
115
  (useKeepCheckoutItem as jest.Mock).mockReturnValue([jest.fn(), CommandStatus.IDLE]);
102
116
  (useReplaceCheckoutItem as jest.Mock).mockReturnValue([jest.fn(), CommandStatus.IDLE]);
103
117
  (useResetCheckoutItem as jest.Mock).mockReturnValue([jest.fn(), CommandStatus.IDLE]);
@@ -119,6 +133,8 @@ describe("Item view", () => {
119
133
  ]);
120
134
  const mockBookCheckoutBookingForCheckoutItem = jest.fn();
121
135
  (useBookCheckoutBookingForCheckoutItem as jest.Mock).mockReturnValue([mockBookCheckoutBookingForCheckoutItem]);
136
+ const mockReturnCheckoutItem = jest.fn();
137
+ (useReturnCheckoutItem as jest.Mock).mockReturnValue([mockReturnCheckoutItem, CommandStatus.IDLE]);
122
138
  (useKeepCheckoutItem as jest.Mock).mockReturnValue([jest.fn(), CommandStatus.IDLE]);
123
139
  (useReplaceCheckoutItem as jest.Mock).mockReturnValue([jest.fn(), CommandStatus.IDLE]);
124
140
  (useResetCheckoutItem as jest.Mock).mockReturnValue([jest.fn(), CommandStatus.IDLE]);
@@ -140,6 +156,31 @@ describe("Item view", () => {
140
156
  ]);
141
157
  const mockBookCheckoutBookingForCheckoutItem = jest.fn();
142
158
  (useBookCheckoutBookingForCheckoutItem as jest.Mock).mockReturnValue([mockBookCheckoutBookingForCheckoutItem]);
159
+ const mockReturnCheckoutItem = jest.fn();
160
+ (useReturnCheckoutItem as jest.Mock).mockReturnValue([mockReturnCheckoutItem, CommandStatus.IDLE]);
161
+ (useKeepCheckoutItem as jest.Mock).mockReturnValue([jest.fn(), CommandStatus.IDLE]);
162
+ (useReplaceCheckoutItem as jest.Mock).mockReturnValue([jest.fn(), CommandStatus.IDLE]);
163
+ (useResetCheckoutItem as jest.Mock).mockReturnValue([jest.fn(), CommandStatus.IDLE]);
164
+
165
+ const { findByTestId } = renderItem();
166
+ const spinner = await findByTestId("spinner");
167
+
168
+ expect(spinner).toBeDefined();
169
+ });
170
+
171
+ it("renders a Spinner while 'returning' the item", async () => {
172
+ (useViewFiveItemsDiscountByCustomerId as jest.Mock).mockReturnValue([5, QueryStatus.SUCCESS]);
173
+ (useViewFirstAvailableCheckoutByCustomerId as jest.Mock).mockReturnValue([mockCheckout, QueryStatus.SUCCESS]);
174
+ (useViewIsSizeChangeEnabledByCheckoutId as jest.Mock).mockReturnValue([true, QueryStatus.SUCCESS]);
175
+ (useListReturnQuestionsByCheckoutItemId as jest.Mock).mockReturnValue([mockReturnQuestions, QueryStatus.SUCCESS]);
176
+ (useViewBookedProductsVariantsForCheckoutItem as jest.Mock).mockReturnValue([
177
+ mockBookedProductsVariants,
178
+ QueryStatus.SUCCESS,
179
+ ]);
180
+ const mockBookCheckoutBookingForCheckoutItem = jest.fn();
181
+ (useBookCheckoutBookingForCheckoutItem as jest.Mock).mockReturnValue([mockBookCheckoutBookingForCheckoutItem]);
182
+ const mockReturnCheckoutItem = jest.fn();
183
+ (useReturnCheckoutItem as jest.Mock).mockReturnValue([mockReturnCheckoutItem, CommandStatus.LOADING]);
143
184
  (useKeepCheckoutItem as jest.Mock).mockReturnValue([jest.fn(), CommandStatus.IDLE]);
144
185
  (useReplaceCheckoutItem as jest.Mock).mockReturnValue([jest.fn(), CommandStatus.IDLE]);
145
186
  (useResetCheckoutItem as jest.Mock).mockReturnValue([jest.fn(), CommandStatus.IDLE]);
@@ -161,6 +202,8 @@ describe("Item view", () => {
161
202
  ]);
162
203
  const mockBookCheckoutBookingForCheckoutItem = jest.fn();
163
204
  (useBookCheckoutBookingForCheckoutItem as jest.Mock).mockReturnValue([mockBookCheckoutBookingForCheckoutItem]);
205
+ const mockReturnCheckoutItem = jest.fn();
206
+ (useReturnCheckoutItem as jest.Mock).mockReturnValue([mockReturnCheckoutItem, CommandStatus.IDLE]);
164
207
  (useKeepCheckoutItem as jest.Mock).mockReturnValue([jest.fn(), CommandStatus.IDLE]);
165
208
  (useReplaceCheckoutItem as jest.Mock).mockReturnValue([jest.fn(), CommandStatus.IDLE]);
166
209
  (useResetCheckoutItem as jest.Mock).mockReturnValue([jest.fn(), CommandStatus.IDLE]);
@@ -182,6 +225,8 @@ describe("Item view", () => {
182
225
  (useViewBookedProductsVariantsForCheckoutItem as jest.Mock).mockReturnValue([null, QueryStatus.SUCCESS]);
183
226
  const mockBookCheckoutBookingForCheckoutItem = jest.fn();
184
227
  (useBookCheckoutBookingForCheckoutItem as jest.Mock).mockReturnValue([mockBookCheckoutBookingForCheckoutItem]);
228
+ const mockReturnCheckoutItem = jest.fn();
229
+ (useReturnCheckoutItem as jest.Mock).mockReturnValue([mockReturnCheckoutItem, CommandStatus.IDLE]);
185
230
  (useKeepCheckoutItem as jest.Mock).mockReturnValue([jest.fn(), CommandStatus.IDLE]);
186
231
  (useReplaceCheckoutItem as jest.Mock).mockReturnValue([jest.fn(), CommandStatus.IDLE]);
187
232
  (useResetCheckoutItem as jest.Mock).mockReturnValue([jest.fn(), CommandStatus.IDLE]);
@@ -202,6 +247,8 @@ describe("Item view", () => {
202
247
  ]);
203
248
  const mockBookCheckoutBookingForCheckoutItem = jest.fn();
204
249
  (useBookCheckoutBookingForCheckoutItem as jest.Mock).mockReturnValue([mockBookCheckoutBookingForCheckoutItem]);
250
+ const mockReturnCheckoutItem = jest.fn();
251
+ (useReturnCheckoutItem as jest.Mock).mockReturnValue([mockReturnCheckoutItem, CommandStatus.IDLE]);
205
252
  (useKeepCheckoutItem as jest.Mock).mockReturnValue([jest.fn(), CommandStatus.IDLE]);
206
253
  (useReplaceCheckoutItem as jest.Mock).mockReturnValue([jest.fn(), CommandStatus.IDLE]);
207
254
  (useResetCheckoutItem as jest.Mock).mockReturnValue([jest.fn(), CommandStatus.IDLE]);
@@ -211,7 +258,7 @@ describe("Item view", () => {
211
258
  expect(mockBookCheckoutBookingForCheckoutItem).not.toHaveBeenCalled();
212
259
  });
213
260
 
214
- it("calls navigate to return page when pressing the return-button", async () => {
261
+ it("calls returnCheckoutItem and trackReturnCheckoutItem when pressing the return-button", async () => {
215
262
  (useViewFiveItemsDiscountByCustomerId as jest.Mock).mockReturnValue([5, QueryStatus.SUCCESS]);
216
263
  (useViewFirstAvailableCheckoutByCustomerId as jest.Mock).mockReturnValue([mockCheckout, QueryStatus.SUCCESS]);
217
264
  (useViewIsSizeChangeEnabledByCheckoutId as jest.Mock).mockReturnValue([true, QueryStatus.SUCCESS]);
@@ -222,17 +269,26 @@ describe("Item view", () => {
222
269
  ]);
223
270
  const mockBookCheckoutBookingForCheckoutItem = jest.fn();
224
271
  (useBookCheckoutBookingForCheckoutItem as jest.Mock).mockReturnValue([mockBookCheckoutBookingForCheckoutItem]);
272
+ const mockReturnCheckoutItem = jest.fn();
273
+ (useReturnCheckoutItem as jest.Mock).mockReturnValue([mockReturnCheckoutItem, CommandStatus.IDLE]);
225
274
  (useKeepCheckoutItem as jest.Mock).mockReturnValue([jest.fn(), CommandStatus.IDLE]);
226
275
  (useReplaceCheckoutItem as jest.Mock).mockReturnValue([jest.fn(), CommandStatus.IDLE]);
227
276
  (useResetCheckoutItem as jest.Mock).mockReturnValue([jest.fn(), CommandStatus.IDLE]);
228
277
 
229
- const { findByText } = renderItem();
278
+ const { findByText, findByTestId } = renderItem();
230
279
 
231
280
  const returnButton = await findByText(I18nMessages.ITEM_RETURN_BUTTON);
232
281
 
233
282
  fireEvent.press(returnButton);
234
283
 
235
- expect(mockNavigate).toHaveBeenCalled();
284
+ const modal = await findByTestId("return-questions-form-modal");
285
+
286
+ const submitButton = await within(modal).findByText(I18nMessages.RETURN_QUESTIONS_SUBMIT_BUTTON);
287
+
288
+ fireEvent.press(submitButton);
289
+
290
+ expect(mockReturnCheckoutItem).toHaveBeenCalled();
291
+ expect(mockTrackReturnItem).toHaveBeenCalled();
236
292
  });
237
293
 
238
294
  it("shows discount banner when the user have purchased items", async () => {