@salesforce/retail-react-app 1.0.0-preview.0 → 1.0.0-preview.2

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.
@@ -11,8 +11,7 @@ import {screen, waitFor, within} from '@testing-library/react'
11
11
  import {rest} from 'msw'
12
12
  import {
13
13
  renderWithProviders,
14
- createPathWithDefaults,
15
- registerUserToken
14
+ createPathWithDefaults
16
15
  } from '@salesforce/retail-react-app/app/utils/test-utils'
17
16
  import {
18
17
  scapiBasketWithItem,
@@ -21,7 +20,6 @@ import {
21
20
  mockedCustomerProductLists
22
21
  } from '@salesforce/retail-react-app/app/mocks/mock-data'
23
22
  import mockConfig from '@salesforce/retail-react-app/config/mocks/default'
24
- import userEvent from '@testing-library/user-event'
25
23
 
26
24
  jest.setTimeout(30000)
27
25
 
@@ -72,6 +70,111 @@ beforeEach(() => {
72
70
  return res(ctx.delay(0), ctx.json(mockShippingMethods))
73
71
  })
74
72
  )
73
+
74
+ let currentBasket = JSON.parse(JSON.stringify(scapiBasketWithItem))
75
+ // Set up additional requests for intercepting/mocking for just this test.
76
+ global.server.use(
77
+ // mock adding guest email to basket
78
+ rest.put('*/baskets/:basketId/customer', (req, res, ctx) => {
79
+ currentBasket.customerInfo.email = 'customer@test.com'
80
+ return res(ctx.json(currentBasket))
81
+ }),
82
+
83
+ // mock fetch product lists
84
+ rest.get('*/customers/:customerId/product-lists', (req, res, ctx) => {
85
+ return res(ctx.json(mockedCustomerProductLists))
86
+ }),
87
+
88
+ // mock add shipping and billing address to basket
89
+ rest.put('*/shipping-address', (req, res, ctx) => {
90
+ const shippingBillingAddress = {
91
+ address1: req.body.address1,
92
+ city: 'Tampa',
93
+ countryCode: 'US',
94
+ firstName: 'Test',
95
+ fullName: 'Test McTester',
96
+ id: '047b18d4aaaf4138f693a4b931',
97
+ lastName: 'McTester',
98
+ phone: '(727) 555-1234',
99
+ postalCode: '33712',
100
+ stateCode: 'FL'
101
+ }
102
+ currentBasket.shipments[0].shippingAddress = shippingBillingAddress
103
+ currentBasket.billingAddress = shippingBillingAddress
104
+ return res(ctx.json(currentBasket))
105
+ }),
106
+
107
+ // mock add billing address to basket
108
+ rest.put('*/billing-address', (req, res, ctx) => {
109
+ const shippingBillingAddress = {
110
+ address1: '123 Main St',
111
+ city: 'Tampa',
112
+ countryCode: 'US',
113
+ firstName: 'Test',
114
+ fullName: 'Test McTester',
115
+ id: '047b18d4aaaf4138f693a4b931',
116
+ lastName: 'McTester',
117
+ phone: '(727) 555-1234',
118
+ postalCode: '33712',
119
+ stateCode: 'FL',
120
+ _type: 'orderAddress'
121
+ }
122
+ currentBasket.shipments[0].shippingAddress = shippingBillingAddress
123
+ currentBasket.billingAddress = shippingBillingAddress
124
+ return res(ctx.json(currentBasket))
125
+ }),
126
+
127
+ // mock add shipping method
128
+ rest.put('*/shipments/me/shipping-method', (req, res, ctx) => {
129
+ currentBasket.shipments[0].shippingMethod = defaultShippingMethod
130
+ return res(ctx.json(currentBasket))
131
+ }),
132
+
133
+ // mock add payment instrument
134
+ rest.post('*/baskets/:basketId/payment-instruments', (req, res, ctx) => {
135
+ currentBasket.paymentInstruments = [
136
+ {
137
+ amount: 0,
138
+ paymentCard: {
139
+ cardType: 'Master Card',
140
+ creditCardExpired: false,
141
+ expirationMonth: 1,
142
+ expirationYear: 2030,
143
+ holder: 'Test McTester',
144
+ maskedNumber: '************5454',
145
+ numberLastDigits: '5454',
146
+ validFromMonth: 1,
147
+ validFromYear: 2020
148
+ },
149
+ paymentInstrumentId: 'testcard1',
150
+ paymentMethodId: 'CREDIT_CARD'
151
+ }
152
+ ]
153
+ return res(ctx.json(currentBasket))
154
+ }),
155
+
156
+ // mock update address
157
+ rest.patch('*/addresses/savedaddress1', (req, res, ctx) => {
158
+ return res(ctx.json(mockedRegisteredCustomer.addresses[0]))
159
+ }),
160
+
161
+ // mock place order
162
+ rest.post('*/orders', (req, res, ctx) => {
163
+ currentBasket = {
164
+ ...scapiOrderResponse,
165
+ customerInfo: {...scapiOrderResponse.customerInfo, email: 'customer@test.com'}
166
+ }
167
+ return res(ctx.json(currentBasket))
168
+ }),
169
+
170
+ rest.get('*/baskets', (req, res, ctx) => {
171
+ const baskets = {
172
+ baskets: [currentBasket],
173
+ total: 1
174
+ }
175
+ return res(ctx.json(baskets))
176
+ })
177
+ )
75
178
  })
76
179
  afterEach(() => {
77
180
  jest.resetModules()
@@ -291,11 +394,23 @@ test('Can proceed through checkout steps as guest', async () => {
291
394
  })
292
395
 
293
396
  test('Can proceed through checkout as registered customer', async () => {
294
- const user = userEvent.setup()
295
- await logInDuringCheckout()
397
+ // Set the initial browser router path and render our component tree.
398
+ window.history.pushState({}, 'Checkout', createPathWithDefaults('/checkout'))
399
+ const {user} = renderWithProviders(<WrappedCheckout history={history} />, {
400
+ wrapperProps: {
401
+ // Not bypassing auth as usual, so we can test the guest-to-registered flow
402
+ bypassAuth: true,
403
+ isGuest: false,
404
+ siteAlias: 'uk',
405
+ locale: {id: 'en-GB'},
406
+ appConfig: mockConfig.app
407
+ }
408
+ })
296
409
 
297
410
  // Email should be displayed in previous step summary
298
- expect(screen.getByText('customer@test.com')).toBeInTheDocument()
411
+ await waitFor(() => {
412
+ expect(screen.getByText('customer@test.com')).toBeInTheDocument()
413
+ })
299
414
 
300
415
  // Select a saved address and continue
301
416
  await user.click(screen.getByDisplayValue('savedaddress1'))
@@ -362,12 +477,26 @@ test('Can proceed through checkout as registered customer', async () => {
362
477
 
363
478
  // Should now be on our mocked confirmation route/page
364
479
  expect(await screen.findByText(/success/i)).toBeInTheDocument()
480
+ document.cookie = ''
365
481
  })
366
482
 
367
483
  test('Can edit address during checkout as a registered customer', async () => {
368
- const user = userEvent.setup()
484
+ // Set the initial browser router path and render our component tree.
485
+ window.history.pushState({}, 'Checkout', createPathWithDefaults('/checkout'))
486
+ const {user} = renderWithProviders(<WrappedCheckout history={history} />, {
487
+ wrapperProps: {
488
+ // Not bypassing auth as usual, so we can test the guest-to-registered flow
489
+ bypassAuth: true,
490
+ isGuest: false,
491
+ siteAlias: 'uk',
492
+ locale: {id: 'en-GB'},
493
+ appConfig: mockConfig.app
494
+ }
495
+ })
369
496
 
370
- await logInDuringCheckout()
497
+ await waitFor(() => {
498
+ expect(screen.getByTestId('sf-checkout-shipping-address-0')).toBeInTheDocument()
499
+ })
371
500
 
372
501
  const firstAddress = screen.getByTestId('sf-checkout-shipping-address-0')
373
502
  await user.click(within(firstAddress).getByText(/edit/i))
@@ -393,8 +522,18 @@ test('Can edit address during checkout as a registered customer', async () => {
393
522
  })
394
523
 
395
524
  test('Can add address during checkout as a registered customer', async () => {
396
- const user = userEvent.setup()
397
- await logInDuringCheckout()
525
+ // Set the initial browser router path and render our component tree.
526
+ window.history.pushState({}, 'Checkout', createPathWithDefaults('/checkout'))
527
+ const {user} = renderWithProviders(<WrappedCheckout history={history} />, {
528
+ wrapperProps: {
529
+ // Not bypassing auth as usual, so we can test the guest-to-registered flow
530
+ bypassAuth: true,
531
+ isGuest: false,
532
+ siteAlias: 'uk',
533
+ locale: {id: 'en-GB'},
534
+ appConfig: mockConfig.app
535
+ }
536
+ })
398
537
 
399
538
  global.server.use(
400
539
  rest.post('*/customers/:customerId/addresses', (req, res, ctx) => {
@@ -402,6 +541,9 @@ test('Can add address during checkout as a registered customer', async () => {
402
541
  })
403
542
  )
404
543
 
544
+ await waitFor(() => {
545
+ expect(screen.getByText(/add new address/i)).toBeInTheDocument()
546
+ })
405
547
  // Add address
406
548
  await user.click(screen.getByText(/add new address/i))
407
549
 
@@ -422,161 +564,3 @@ test('Can add address during checkout as a registered customer', async () => {
422
564
  expect(screen.getByTestId('sf-toggle-card-step-2-content')).not.toBeEmptyDOMElement()
423
565
  })
424
566
  })
425
-
426
- const logInDuringCheckout = async () => {
427
- // Keep a *deep* of the initial mocked basket. Our mocked fetch responses will continuously
428
- // update this object, which essentially mimics a saved basket on the backend.
429
- let currentBasket = JSON.parse(JSON.stringify(scapiBasketWithItem))
430
-
431
- // Set up additional requests for intercepting/mocking for just this test.
432
- global.server.use(
433
- // mock adding guest email to basket
434
- rest.put('*/baskets/:basketId/customer', (req, res, ctx) => {
435
- currentBasket.customerInfo.email = 'customer@test.com'
436
- return res(ctx.json(currentBasket))
437
- }),
438
-
439
- // mock fetch product lists
440
- rest.get('*/customers/:customerId/product-lists', (req, res, ctx) => {
441
- return res(ctx.json(mockedCustomerProductLists))
442
- }),
443
-
444
- // mock add shipping and billing address to basket
445
- rest.put('*/shipping-address', (req, res, ctx) => {
446
- const shippingBillingAddress = {
447
- address1: req.body.address1,
448
- city: 'Tampa',
449
- countryCode: 'US',
450
- firstName: 'Test',
451
- fullName: 'Test McTester',
452
- id: '047b18d4aaaf4138f693a4b931',
453
- lastName: 'McTester',
454
- phone: '(727) 555-1234',
455
- postalCode: '33712',
456
- stateCode: 'FL'
457
- }
458
- currentBasket.shipments[0].shippingAddress = shippingBillingAddress
459
- currentBasket.billingAddress = shippingBillingAddress
460
- return res(ctx.json(currentBasket))
461
- }),
462
-
463
- // mock add billing address to basket
464
- rest.put('*/billing-address', (req, res, ctx) => {
465
- const shippingBillingAddress = {
466
- address1: '123 Main St',
467
- city: 'Tampa',
468
- countryCode: 'US',
469
- firstName: 'Test',
470
- fullName: 'Test McTester',
471
- id: '047b18d4aaaf4138f693a4b931',
472
- lastName: 'McTester',
473
- phone: '(727) 555-1234',
474
- postalCode: '33712',
475
- stateCode: 'FL',
476
- _type: 'orderAddress'
477
- }
478
- currentBasket.shipments[0].shippingAddress = shippingBillingAddress
479
- currentBasket.billingAddress = shippingBillingAddress
480
- return res(ctx.json(currentBasket))
481
- }),
482
-
483
- // mock add shipping method
484
- rest.put('*/shipments/me/shipping-method', (req, res, ctx) => {
485
- currentBasket.shipments[0].shippingMethod = defaultShippingMethod
486
- return res(ctx.json(currentBasket))
487
- }),
488
-
489
- // mock add payment instrument
490
- rest.post('*/baskets/:basketId/payment-instruments', (req, res, ctx) => {
491
- currentBasket.paymentInstruments = [
492
- {
493
- amount: 0,
494
- paymentCard: {
495
- cardType: 'Master Card',
496
- creditCardExpired: false,
497
- expirationMonth: 1,
498
- expirationYear: 2030,
499
- holder: 'Test McTester',
500
- maskedNumber: '************5454',
501
- numberLastDigits: '5454',
502
- validFromMonth: 1,
503
- validFromYear: 2020
504
- },
505
- paymentInstrumentId: 'testcard1',
506
- paymentMethodId: 'CREDIT_CARD'
507
- }
508
- ]
509
- return res(ctx.json(currentBasket))
510
- }),
511
-
512
- // mock update address
513
- rest.patch('*/addresses/savedaddress1', (req, res, ctx) => {
514
- return res(ctx.json(mockedRegisteredCustomer.addresses[0]))
515
- }),
516
-
517
- // mock place order
518
- rest.post('*/orders', (req, res, ctx) => {
519
- currentBasket = {
520
- ...scapiOrderResponse,
521
- customerInfo: {...scapiOrderResponse.customerInfo, email: 'customer@test.com'}
522
- }
523
- return res(ctx.json(currentBasket))
524
- }),
525
-
526
- rest.get('*/baskets', (req, res, ctx) => {
527
- const baskets = {
528
- baskets: [currentBasket],
529
- total: 1
530
- }
531
- return res(ctx.json(baskets))
532
- })
533
- )
534
-
535
- // Set the initial browser router path and render our component tree.
536
- window.history.pushState({}, 'Checkout', createPathWithDefaults('/checkout'))
537
- const {user} = renderWithProviders(<WrappedCheckout history={history} />, {
538
- wrapperProps: {
539
- // Not bypassing auth as usual, so we can test the guest-to-registered flow
540
- bypassAuth: false,
541
- siteAlias: 'uk',
542
- locale: {id: 'en-GB'},
543
- appConfig: mockConfig.app
544
- }
545
- })
546
-
547
- // Switch to login
548
- const haveAccountButton = await screen.findByText(/already have an account/i)
549
- await user.click(haveAccountButton)
550
-
551
- // Wait for checkout to load and display first step
552
- const loginBtn = await screen.findByText(/log in/i)
553
-
554
- // Planning to log in
555
- global.server.use(
556
- rest.post('*/oauth2/token', (req, res, ctx) => {
557
- return res(
558
- ctx.delay(0),
559
- ctx.json({
560
- customer_id: 'customerid_1',
561
- access_token: registerUserToken,
562
- refresh_token: 'testrefeshtoken_1',
563
- usid: 'testusid_1',
564
- enc_user_id: 'testEncUserId_1',
565
- id_token: 'testIdToken_1'
566
- })
567
- )
568
- })
569
- )
570
-
571
- // Provide customer email and submit
572
- const emailInput = screen.getByLabelText('Email')
573
- const pwInput = screen.getByLabelText('Password')
574
- await user.type(emailInput, 'customer@test.com')
575
- await user.type(pwInput, 'Password!1')
576
- await user.click(loginBtn)
577
-
578
- // Wait for next step to render
579
- await waitFor(() =>
580
- expect(screen.getByTestId('sf-toggle-card-step-1-content')).not.toBeEmptyDOMElement()
581
- )
582
- }
package/app/routes.jsx CHANGED
@@ -25,16 +25,24 @@ const fallback = <Skeleton height="75vh" width="100%" />
25
25
  // Pages
26
26
  const Home = loadable(() => import('./pages/home'), {fallback})
27
27
  const Login = loadable(() => import('./pages/login'), {fallback})
28
- const Registration = loadable(() => import('./pages/registration'), {fallback})
28
+ const Registration = loadable(() => import('./pages/registration'), {
29
+ fallback
30
+ })
29
31
  const ResetPassword = loadable(() => import('./pages/reset-password'), {fallback})
30
32
  const Account = loadable(() => import('./pages/account'), {fallback})
31
33
  const Cart = loadable(() => import('./pages/cart'), {fallback})
32
- const Checkout = loadable(() => import('./pages/checkout'), {fallback})
34
+ const Checkout = loadable(() => import('./pages/checkout'), {
35
+ fallback
36
+ })
33
37
  const CheckoutConfirmation = loadable(() => import('./pages/checkout/confirmation'), {fallback})
34
38
  const LoginRedirect = loadable(() => import('./pages/login-redirect'), {fallback})
35
39
  const ProductDetail = loadable(() => import('./pages/product-detail'), {fallback})
36
- const ProductList = loadable(() => import('./pages/product-list'), {fallback})
37
- const Wishlist = loadable(() => import('./pages/account/wishlist'), {fallback})
40
+ const ProductList = loadable(() => import('./pages/product-list'), {
41
+ fallback
42
+ })
43
+ const Wishlist = loadable(() => import('./pages/account/wishlist'), {
44
+ fallback
45
+ })
38
46
  const PageNotFound = loadable(() => import('./pages/page-not-found'))
39
47
 
40
48
  export const routes = [
package/jest-setup.js CHANGED
@@ -21,6 +21,9 @@ const {
21
21
  mockCustomerBaskets
22
22
  } = require('./app/mocks/mock-data')
23
23
 
24
+ // set jsdom in https context to allow read/write secure cookies
25
+ global.jsdom.reconfigure({url: 'https://www.domain.com'})
26
+
24
27
  configureTestingLibrary({
25
28
  // Increase to: 6 x default timeout of 1 second
26
29
  ...(process.env.CI ? {asyncUtilTimeout: 6000} : {})
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salesforce/retail-react-app",
3
- "version": "1.0.0-preview.0",
3
+ "version": "1.0.0-preview.2",
4
4
  "license": "See license in LICENSE",
5
5
  "author": "cc-pwa-kit@salesforce.com",
6
6
  "ccExtensibility": {
@@ -44,11 +44,11 @@
44
44
  "@lhci/cli": "^0.11.0",
45
45
  "@loadable/component": "^5.15.3",
46
46
  "@peculiar/webcrypto": "^1.4.2",
47
- "@salesforce/commerce-sdk-react": "1.0.0-preview.0",
48
- "@salesforce/pwa-kit-dev": "3.0.0-preview.0",
49
- "@salesforce/pwa-kit-react-sdk": "3.0.0-preview.0",
50
- "@salesforce/pwa-kit-runtime": "3.0.0-preview.0",
51
- "@tanstack/react-query": "^4.0.10",
47
+ "@salesforce/commerce-sdk-react": "1.0.0-preview.2",
48
+ "@salesforce/pwa-kit-dev": "3.0.0-preview.2",
49
+ "@salesforce/pwa-kit-react-sdk": "3.0.0-preview.2",
50
+ "@salesforce/pwa-kit-runtime": "3.0.0-preview.2",
51
+ "@tanstack/react-query": "^4.28.0",
52
52
  "@tanstack/react-query-devtools": "^4.29.1",
53
53
  "@testing-library/dom": "^9.0.1",
54
54
  "@testing-library/jest-dom": "^5.16.5",
@@ -101,5 +101,5 @@
101
101
  "overrides": {
102
102
  "nwsapi": "2.2.2"
103
103
  },
104
- "gitHead": "a9f820893b7714244a0af509a5aefecc1344153c"
104
+ "gitHead": "a2476c090ce48fd09e9116437aedc6cc45ae60bd"
105
105
  }