@vtex/faststore-plugin-buyer-portal 1.1.92 → 1.1.94

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 (62) hide show
  1. package/cypress/constants.ts +4 -9
  2. package/cypress/integration/addresses.test.ts +39 -55
  3. package/cypress/integration/budgets.test.ts +130 -100
  4. package/cypress/integration/buying-policies.test.ts +66 -96
  5. package/cypress/integration/collections.test.ts +192 -172
  6. package/cypress/integration/credit-cards.test.ts +1 -1
  7. package/cypress/integration/locations.test.ts +39 -43
  8. package/cypress/integration/organizational-units.test.ts +70 -33
  9. package/cypress/integration/recipients.test.ts +34 -46
  10. package/cypress/integration/users.test.ts +83 -136
  11. package/cypress/shared.ts +32 -2
  12. package/cypress/support/addressHelper.tsx +17 -6
  13. package/package.json +1 -1
  14. package/public/buyer-portal-icons.svg +1 -1
  15. package/src/features/addresses/components/DeleteRecipientAddressDrawer/DeleteRecipientAddressDrawer.tsx +1 -1
  16. package/src/features/addresses/services/get-addresses-by-unit-id.service.ts +13 -1
  17. package/src/features/addresses/services/get-addresses.service.ts +15 -2
  18. package/src/features/buying-policies/services/get-buying-policies.service.ts +19 -21
  19. package/src/features/contracts/services/get-contract-details.service.ts +13 -1
  20. package/src/features/contracts/services/get-contracts-org-by-unit-id.service.ts +18 -11
  21. package/src/features/contracts/services/update-contract-status.service.ts +18 -11
  22. package/src/features/profile/layouts/ProfileLayout/profile-layout.scss +1 -0
  23. package/src/features/shared/clients/Client.ts +84 -8
  24. package/src/features/shared/components/BuyerPortalProvider/BuyerPortalProvider.tsx +4 -1
  25. package/src/features/shared/components/Error/Error.tsx +31 -0
  26. package/src/features/shared/components/Error/error.scss +71 -0
  27. package/src/features/shared/components/ErrorBoundary/ErrorBoundary.tsx +63 -0
  28. package/src/features/shared/components/ErrorBoundary/types.ts +14 -0
  29. package/src/features/shared/components/index.ts +3 -0
  30. package/src/features/shared/components/withErrorBoundary/withErrorBoundary.tsx +35 -0
  31. package/src/features/shared/layouts/BaseTabsLayout/SidebarMenu.tsx +9 -2
  32. package/src/features/shared/layouts/ContractTabsLayout/ContractTabsLayout.tsx +4 -2
  33. package/src/features/shared/layouts/ErrorTabsLayout/ErrorTabsLayout.tsx +119 -0
  34. package/src/features/shared/layouts/ErrorTabsLayout/error-tabs-layout.scss +1 -0
  35. package/src/features/shared/utils/constants.ts +1 -1
  36. package/src/features/shared/utils/environment.ts +41 -0
  37. package/src/features/shared/utils/extractErrorMessage.ts +22 -0
  38. package/src/features/shared/utils/getHome.tsx +5 -0
  39. package/src/features/shared/utils/index.ts +2 -0
  40. package/src/features/shared/utils/withClientErrorBoundary.ts +61 -0
  41. package/src/features/shared/utils/withLoaderErrorBoundary.ts +46 -0
  42. package/src/features/users/clients/UsersClient.ts +0 -1
  43. package/src/pages/address-details.tsx +38 -11
  44. package/src/pages/addresses.tsx +35 -6
  45. package/src/pages/budgets-details.tsx +38 -8
  46. package/src/pages/budgets.tsx +33 -8
  47. package/src/pages/buying-policies.tsx +36 -12
  48. package/src/pages/buying-policy-details.tsx +38 -8
  49. package/src/pages/collections.tsx +36 -12
  50. package/src/pages/cost-centers.tsx +38 -8
  51. package/src/pages/credit-cards.tsx +38 -8
  52. package/src/pages/home.tsx +22 -5
  53. package/src/pages/org-unit-details.tsx +43 -7
  54. package/src/pages/org-units.tsx +39 -8
  55. package/src/pages/payment-methods.tsx +38 -8
  56. package/src/pages/po-numbers.tsx +38 -8
  57. package/src/pages/profile.tsx +31 -6
  58. package/src/pages/releases.tsx +33 -8
  59. package/src/pages/role-details.tsx +39 -7
  60. package/src/pages/roles.tsx +28 -7
  61. package/src/pages/user-details.tsx +39 -8
  62. package/src/pages/users.tsx +25 -7
@@ -1,4 +1,5 @@
1
1
  import { TEST_CONFIG, TEST_DATA } from "../constants";
2
+ import { generateRandomString, useInternalSearch } from "../shared";
2
3
 
3
4
  const navigateToUsers = () => {
4
5
  cy.visit(TEST_CONFIG.ROUTES.BUYER_PORTAL);
@@ -15,7 +16,6 @@ const verifyUserState = (
15
16
  ) => {
16
17
  const verifyAndRetry = (currentRetry = 0) => {
17
18
  cy.get("[data-fs-users-section]").should("exist");
18
- cy.get("[data-fs-bp-base-tabs-layout-content]").scrollTo("bottom");
19
19
 
20
20
  cy.get("body").then(($body) => {
21
21
  const exists = $body.text().includes(userName);
@@ -117,7 +117,14 @@ const confirmDeletion = (userName: string) => {
117
117
  tryDelete();
118
118
  };
119
119
 
120
- describe("Users", () => {
120
+ let USER_NAME: string;
121
+ let USER_EMAIL: string;
122
+
123
+ describe("Users", { retries: 2 }, () => {
124
+ before(() => {
125
+ USER_NAME = `${TEST_DATA.USERS.NEW_USER.NAME} ${generateRandomString()}`;
126
+ USER_EMAIL = `${generateRandomString()}${TEST_DATA.USERS.NEW_USER.EMAIL}`;
127
+ });
121
128
  beforeEach(() => {
122
129
  cy.login();
123
130
  });
@@ -130,6 +137,8 @@ describe("Users", () => {
130
137
  cy.contains("Role").should("be.visible");
131
138
 
132
139
  // Check that the expected users are present in the table
140
+ useInternalSearch(TEST_DATA.USERS.USER_ORG_UNIT_ADMIN.NAME);
141
+
133
142
  cy.contains(TEST_DATA.USERS.USER_ORG_UNIT_ADMIN.NAME)
134
143
  .scrollIntoView()
135
144
  .should("be.visible")
@@ -155,6 +164,8 @@ describe("Users", () => {
155
164
  navigateToUsers();
156
165
 
157
166
  // Click on User Test 1 to go to details page
167
+ useInternalSearch(TEST_DATA.USERS.USER_ORG_UNIT_ADMIN.NAME);
168
+
158
169
  cy.contains(TEST_DATA.USERS.USER_ORG_UNIT_ADMIN.NAME)
159
170
  .scrollIntoView()
160
171
  .should("be.visible")
@@ -193,7 +204,11 @@ describe("Users", () => {
193
204
  cy.get("[data-fs-header-inside-button]").should("be.visible").click();
194
205
 
195
206
  // Fill user form
196
- fillUserForm(TEST_DATA.USERS.NEW_USER);
207
+ fillUserForm({
208
+ ...TEST_DATA.USERS.NEW_USER,
209
+ EMAIL: USER_EMAIL,
210
+ NAME: USER_NAME,
211
+ });
197
212
 
198
213
  // Submit form
199
214
  cy.contains("button", "Add").click();
@@ -201,8 +216,9 @@ describe("Users", () => {
201
216
  // Verify success message
202
217
  cy.contains("User successfully added").should("be.visible");
203
218
 
219
+ useInternalSearch(USER_NAME);
204
220
  // Reload and verify user was created
205
- verifyUserState(TEST_DATA.USERS.NEW_USER.NAME, true);
221
+ verifyUserState(USER_NAME, true);
206
222
  });
207
223
 
208
224
  it("Should view and edit the newly created user", () => {
@@ -212,7 +228,9 @@ describe("Users", () => {
212
228
  cy.log("=== Viewing user details ===");
213
229
  cy.get("[data-fs-bp-base-tabs-layout-content]").scrollTo("bottom");
214
230
 
215
- cy.contains(TEST_DATA.USERS.NEW_USER.NAME)
231
+ useInternalSearch(USER_NAME);
232
+
233
+ cy.contains(USER_NAME)
216
234
  .should("be.visible")
217
235
  .parents("[data-fs-bp-table-row]")
218
236
  .click();
@@ -230,7 +248,8 @@ describe("Users", () => {
230
248
  // === EDIT USER ===
231
249
  cy.log("=== Editing user ===");
232
250
 
233
- openUserDropdown(TEST_DATA.USERS.NEW_USER.NAME);
251
+ useInternalSearch(USER_NAME);
252
+ openUserDropdown(USER_NAME);
234
253
  cy.contains("Edit details").click();
235
254
 
236
255
  // Verify edit drawer is open
@@ -240,8 +259,8 @@ describe("Users", () => {
240
259
 
241
260
  // Update user information
242
261
  const updatedUserData = {
243
- NAME: `${TEST_DATA.USERS.NEW_USER.NAME} Updated`,
244
- EMAIL: TEST_DATA.USERS.NEW_USER.EMAIL,
262
+ NAME: `${USER_NAME} Updated`,
263
+ EMAIL: USER_EMAIL,
245
264
  ROLE: TEST_DATA.USERS.NEW_USER.ROLE,
246
265
  };
247
266
 
@@ -250,6 +269,9 @@ describe("Users", () => {
250
269
  // Save changes
251
270
  cy.contains("button", "Save").click();
252
271
 
272
+ cy.wait(TEST_CONFIG.TIMEOUTS.PAGE_LOAD);
273
+
274
+ useInternalSearch(updatedUserData.NAME);
253
275
  // Verify update
254
276
  verifyUserState(updatedUserData.NAME, true);
255
277
  });
@@ -259,14 +281,15 @@ describe("Users", () => {
259
281
 
260
282
  // === DELETE USER ===
261
283
  cy.log("=== Deleting user ===");
262
- cy.get("[data-fs-bp-base-tabs-layout-content]").scrollTo("bottom");
263
284
 
264
285
  const updatedUserData = {
265
- NAME: `${TEST_DATA.USERS.NEW_USER.NAME} Updated`,
266
- EMAIL: TEST_DATA.USERS.NEW_USER.EMAIL,
286
+ NAME: `${USER_NAME} Updated`,
287
+ EMAIL: USER_EMAIL,
267
288
  ROLE: TEST_DATA.USERS.NEW_USER.ROLE,
268
289
  };
269
290
 
291
+ useInternalSearch(updatedUserData.NAME);
292
+
270
293
  openUserDropdown(updatedUserData.NAME);
271
294
  cy.contains("Delete").click();
272
295
 
@@ -276,8 +299,8 @@ describe("Users", () => {
276
299
  confirmDeletion(userNameText);
277
300
  });
278
301
 
279
- // Verify if the user was deleted
280
- verifyUserState(updatedUserData.NAME, false);
302
+ useInternalSearch(updatedUserData.NAME);
303
+ cy.contains(updatedUserData.NAME).should("not.exist");
281
304
  });
282
305
 
283
306
  it("Should not allow adding a user already in another org unit", () => {
@@ -306,40 +329,21 @@ describe("Users", () => {
306
329
  });
307
330
 
308
331
  it("Should create a new user add, edit and remove roles", () => {
309
- // Visit the buyer portal home page
310
- cy.visit(TEST_CONFIG.ROUTES.BUYER_PORTAL);
311
-
312
- // Click on the "Users" link in the sidebar menu
313
- cy.get("a[data-fs-vertical-nav-menu-link]").contains("Users").click();
314
-
315
- // Check that the Users page is rendered
316
- cy.get('h1[data-fs-bp-header-inside-title="true"]').should(
317
- "contain",
318
- "Users"
319
- );
332
+ const ROLE_USER_NAME = `${
333
+ TEST_DATA.USERS.USER_NAME_FOR_ROLES
334
+ } ${generateRandomString()}`;
335
+ const ROLE_EMAIL = `${generateRandomString()}userfortestroles@vtex.com`;
320
336
 
321
- // Check that at least one user row exists
322
- cy.get('a[data-fs-bp-table-row-link="true"]').should("exist");
337
+ navigateToUsers();
323
338
 
324
339
  // Click the add user button at the top
325
340
  cy.get('button[data-fs-header-inside-button="true"]').click();
326
341
 
327
- // Check that the user creation modal is open
328
- cy.get(
329
- 'div[data-fs-modal-content="true"][data-fs-bp-create-user-drawer="true"]'
330
- ).should("be.visible");
331
- cy.get('h2[data-fs-bp-basic-drawer-heading-title="true"]').should(
332
- "contain",
333
- "Add User"
334
- );
335
-
336
342
  // Fill out the user creation form
337
343
  cy.get('input[data-fs-bp-input-text-input="true"]')
338
344
  .first()
339
- .type(TEST_DATA.USERS.USER_NAME_FOR_ROLES); // Full Name
340
- cy.get('input[data-fs-bp-input-text-input="true"]')
341
- .eq(1)
342
- .type("userfortestroles@vtex.com"); // Email
345
+ .type(ROLE_USER_NAME); // Full Name
346
+ cy.get('input[data-fs-bp-input-text-input="true"]').eq(1).type(ROLE_EMAIL); // Email
343
347
  cy.get('input[type="checkbox"][value="Buyer"]').check(); // Assign Buyer role
344
348
 
345
349
  // Click the "Add" button to submit the form
@@ -349,44 +353,22 @@ describe("Users", () => {
349
353
  .should("not.be.disabled")
350
354
  .click();
351
355
 
352
- cy.wait(3000);
353
-
354
- // Retry logic to check if user appears in the list
355
- const checkUserExists = (attempt = 1) => {
356
- cy.reload();
357
- cy.get("body").then(($body) => {
358
- if ($body.text().includes(TEST_DATA.USERS.USER_NAME_FOR_ROLES)) {
359
- // User found, verify it exists
360
- cy.contains("td", TEST_DATA.USERS.USER_NAME_FOR_ROLES).should(
361
- "exist"
362
- );
363
- } else if (attempt < 3) {
364
- cy.log(`User not found, retry attempt ${attempt + 1} of 3`);
365
- cy.wait(2000);
366
- checkUserExists(attempt + 1);
367
- } else {
368
- throw new Error(
369
- `User ${TEST_DATA.USERS.USER_NAME_FOR_ROLES} not found after 3 attempts`
370
- );
371
- }
372
- });
373
- };
356
+ cy.wait(TEST_CONFIG.TIMEOUTS.PAGE_LOAD);
374
357
 
375
- checkUserExists();
358
+ // Verify success message
359
+ cy.contains("User successfully added").should("be.visible");
376
360
 
377
- // Check that the 'Buyer' badge is present in the same row
378
- cy.contains(
379
- 'tr[data-fs-bp-table-row="true"]',
380
- TEST_DATA.USERS.USER_NAME_FOR_ROLES
381
- )
361
+ useInternalSearch(ROLE_USER_NAME);
362
+ // Reload and verify user was created
363
+ verifyUserState(ROLE_USER_NAME, true);
364
+
365
+ // Check that it has roles badges
366
+ cy.contains('tr[data-fs-bp-table-row="true"]', ROLE_USER_NAME)
382
367
  .find('span[data-fs-tag="true"]')
383
- .should("contain.text", "Buyer");
368
+ .should("exist");
384
369
 
385
370
  // --- Edit user roles: add Organizational Unit Admin ---
386
- cy.contains(
387
- 'tr[data-fs-bp-table-row="true"]',
388
- TEST_DATA.USERS.USER_NAME_FOR_ROLES
389
- )
371
+ cy.contains('tr[data-fs-bp-table-row="true"]', ROLE_USER_NAME)
390
372
  .find('button[data-fs-bp-basic-dropdown-menu-trigger="true"]')
391
373
  .click();
392
374
  cy.get(
@@ -397,10 +379,7 @@ describe("Users", () => {
397
379
  cy.get(
398
380
  'div[data-fs-modal-content="true"][data-fs-bp-update-user-drawer="true"]'
399
381
  ).should("be.visible");
400
- cy.get('h2[data-fs-bp-basic-drawer-heading-title="true"]').should(
401
- "contain",
402
- "Edit user details"
403
- );
382
+
404
383
  cy.get("input#role-organizational-unit\\ admin").check({ force: true });
405
384
  cy.get(
406
385
  'button[data-fs-bp-basic-drawer-button="true"][data-fs-bp-basic-drawer-button-variant="confirm"]'
@@ -410,18 +389,11 @@ describe("Users", () => {
410
389
 
411
390
  cy.wait(1000);
412
391
  cy.reload();
413
- cy.contains(
414
- 'tr[data-fs-bp-table-row="true"]',
415
- TEST_DATA.USERS.USER_NAME_FOR_ROLES
416
- )
417
- .find('span[data-fs-tag="true"]')
418
- .should("contain.text", "Organizational Unit Admin");
392
+
393
+ useInternalSearch(ROLE_USER_NAME);
419
394
 
420
395
  // --- Edit user roles: remove Organizational Unit Admin ---
421
- cy.contains(
422
- 'tr[data-fs-bp-table-row="true"]',
423
- TEST_DATA.USERS.USER_NAME_FOR_ROLES
424
- )
396
+ cy.contains('tr[data-fs-bp-table-row="true"]', ROLE_USER_NAME)
425
397
  .find('button[data-fs-bp-basic-dropdown-menu-trigger="true"]')
426
398
  .click();
427
399
  cy.get(
@@ -439,91 +411,65 @@ describe("Users", () => {
439
411
  .should("not.be.disabled")
440
412
  .click();
441
413
 
442
- cy.wait(1000);
443
- cy.reload();
444
- cy.contains(
445
- 'tr[data-fs-bp-table-row="true"]',
446
- TEST_DATA.USERS.USER_NAME_FOR_ROLES
447
- )
448
- .find('span[data-fs-tag="true"]')
449
- .should("not.contain.text", "Organizational Unit Admin");
414
+ cy.wait(TEST_CONFIG.TIMEOUTS.PAGE_LOAD);
450
415
 
451
- // Open the dropdown menu (three dots) for the created user
452
- cy.contains(
453
- 'tr[data-fs-bp-table-row="true"]',
454
- TEST_DATA.USERS.USER_NAME_FOR_ROLES
455
- )
456
- .find('button[data-fs-bp-basic-dropdown-menu-trigger="true"]')
457
- .click();
416
+ openUserDropdown(ROLE_USER_NAME);
458
417
 
459
- // Click the "Delete" option in the dropdown menu
460
- cy.get(
461
- 'div[data-fs-dropdown-menu="true"] button[data-fs-dropdown-item="true"]'
462
- )
463
- .contains("Delete")
464
- .click();
465
-
466
- // Check that the delete user modal is open
467
- cy.get(
468
- 'div[data-fs-modal-content="true"][data-fs-bp-delete-user-drawer="true"]'
469
- ).should("be.visible");
470
- cy.get('h2[data-fs-bp-basic-drawer-heading-title="true"]').should(
471
- "contain",
472
- "Delete user"
473
- );
418
+ cy.contains("Delete").click();
474
419
 
475
420
  // Type the user name to confirm deletion
476
- cy.get('input[data-fs-bp-input-text-input="true"]').type(
477
- TEST_DATA.USERS.USER_NAME_FOR_ROLES
478
- );
479
-
480
- cy.wait(1000);
421
+ cy.get('input[data-fs-bp-input-text-input="true"]').type(ROLE_USER_NAME);
481
422
 
482
423
  // Click the "Delete" button to confirm
483
424
  cy.get(
484
425
  'button[data-fs-bp-basic-drawer-button="true"][data-fs-bp-basic-drawer-button-variant="danger"]'
485
- )
486
- .should("not.be.disabled")
487
- .click();
426
+ ).click();
488
427
 
489
- cy.wait(1000);
428
+ cy.wait(TEST_CONFIG.TIMEOUTS.PAGE_LOAD);
490
429
  // Reload the users page
491
430
  cy.reload();
492
431
 
493
432
  // Check that the user no longer exists in the list
494
- cy.contains("td", TEST_DATA.USERS.USER_NAME_FOR_ROLES).should("not.exist");
433
+ cy.contains("td", ROLE_USER_NAME).should("not.exist");
495
434
  });
496
435
 
497
436
  it("Should allow changing the organizational unit from the list dropdown menu", () => {
498
437
  navigateToUsers();
499
438
 
439
+ USER_NAME = `${TEST_DATA.USERS.NEW_USER.NAME} ${generateRandomString()}`;
440
+ USER_EMAIL = `${generateRandomString()}${TEST_DATA.USERS.NEW_USER.EMAIL}`;
441
+
500
442
  // Open dropdown for the test user
501
443
  cy.get("[data-fs-header-inside-button]").should("be.visible").click();
502
- fillUserForm(TEST_DATA.USERS.NEW_USER);
444
+ fillUserForm({
445
+ ...TEST_DATA.USERS.NEW_USER,
446
+ EMAIL: USER_EMAIL,
447
+ NAME: USER_NAME,
448
+ });
503
449
 
504
450
  cy.contains("button", "Add").click();
505
451
  cy.wait(TEST_CONFIG.TIMEOUTS.PAGE_LOAD);
506
452
 
507
- verifyUserState(TEST_DATA.USERS.NEW_USER.NAME, true);
453
+ useInternalSearch(USER_NAME);
508
454
 
509
- openUserDropdown(TEST_DATA.USERS.NEW_USER.NAME);
455
+ verifyUserState(USER_NAME, true);
456
+
457
+ openUserDropdown(USER_NAME);
510
458
  cy.contains("Change organizational unit").click();
511
459
 
512
460
  // Verify change org unit modal/drawer is open
513
461
  cy.contains("Change user organizational unit").should("be.visible");
514
462
  cy.contains(
515
- `Users can belong to only one Organizational Unit. Search and select a new unit for ${TEST_DATA.USERS.NEW_USER.NAME}`
463
+ `Users can belong to only one Organizational Unit. Search and select a new unit for ${USER_NAME}`
516
464
  ).should("be.visible");
517
465
 
518
466
  cy.get('[data-fs-bp-input-text="true"]')
519
467
  .should("be.visible")
520
- .type(TEST_DATA.ORG_UNITS.ROOT, { delay: 1000 });
521
-
522
- cy.wait(0);
468
+ .type(TEST_DATA.ORG_UNITS.ROOT, { delay: 500 });
523
469
 
524
470
  // Wait for and click on the option in the dropdown
525
- cy.get('[data-fs-bp-autocomplete-dropdown-menu="true"]')
526
- .contains(TEST_DATA.ORG_UNITS.CHILD_2, { timeout: 10000 })
471
+ cy.get("[data-fs-bp-autocomplete-dropdown-menu]")
472
+ .contains(TEST_DATA.ORG_UNITS.CHILD_2, { timeout: 500 })
527
473
  .should("exist")
528
474
  .click();
529
475
 
@@ -534,7 +480,8 @@ describe("Users", () => {
534
480
  cy.reload();
535
481
 
536
482
  // Check if the user is not on the same org unit
537
- verifyUserState(TEST_DATA.USERS.NEW_USER.NAME, false);
483
+ useInternalSearch(USER_NAME);
484
+ cy.contains(USER_NAME).should("not.exist");
538
485
  });
539
486
 
540
487
  it.skip("Should not allow deleting the last admin user", () => {
package/cypress/shared.ts CHANGED
@@ -1,3 +1,33 @@
1
- export function clickConfirmButton() {
2
- cy.get('[data-fs-bp-basic-drawer-button-variant="confirm"]').click();
1
+ import { TEST_CONFIG } from "./constants";
2
+
3
+ export function clickConfirmButton(alias?: string) {
4
+ const selector = '[data-fs-bp-basic-drawer-button-variant="confirm"]';
5
+
6
+ if (alias) {
7
+ cy.get(`@${alias}`).find(selector).click();
8
+ } else {
9
+ cy.get(selector).click();
10
+ }
11
+ }
12
+
13
+ export function generateRandomString(length = 8) {
14
+ let result = "";
15
+ const characters =
16
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
17
+ const charactersLength = characters.length;
18
+ for (let i = 0; i < length; i++) {
19
+ result += characters.charAt(Math.floor(Math.random() * charactersLength));
20
+ }
21
+ return result;
22
+ }
23
+
24
+ // By using the internal search we can avoid complications with pagination
25
+ export function useInternalSearch(searchTerm: string) {
26
+ cy.get("[data-fs-buyer-portal-internal-search-input]")
27
+ .clear()
28
+ .lazyType(searchTerm);
29
+
30
+ cy.get("[data-fs-bp-table-row-loading]", {
31
+ timeout: TEST_CONFIG.TIMEOUTS.LONG_DELAY,
32
+ }).should("not.exist");
3
33
  }
@@ -1,3 +1,5 @@
1
+ import { useInternalSearch } from "../shared";
2
+
1
3
  export function clickAddressTab(tabName: string) {
2
4
  cy.get("[data-fs-bp-tab-option]").contains(tabName).click();
3
5
  }
@@ -6,11 +8,8 @@ export function goToAddressPage(contractName: string) {
6
8
  // Navigate to Addresses page
7
9
  cy.contains("Addresses").click();
8
10
 
9
- // Address Page is loading slowly, custom wait untill we get the request optimized
10
- cy.wait(10000);
11
-
12
11
  // Check to see if the address section loaded
13
- cy.get("[data-fs-addresses-section]", { timeout: 100000 }).should("exist");
12
+ cy.get("[data-fs-addresses-section]", { timeout: 8000 }).should("exist");
14
13
 
15
14
  // Check to see if contract details loaded correctly
16
15
  cy.get("[data-fs-bp-header-inside]").should("exist");
@@ -18,11 +17,20 @@ export function goToAddressPage(contractName: string) {
18
17
  }
19
18
 
20
19
  export function navigateToAddressByName(addressName: string) {
20
+ useInternalSearch(addressName);
21
+
21
22
  cy.get("[data-fs-addresses-table]").within(() => {
22
- cy.contains(addressName).should("be.visible").parent().parent().click();
23
+ cy.contains(addressName)
24
+ .should("be.visible")
25
+ .parent()
26
+ .parent()
27
+ .parent()
28
+ .click();
23
29
  });
24
30
 
25
- cy.wait(8000);
31
+ cy.get("[data-fs-address-details-section]", { timeout: 10000 }).should(
32
+ "exist"
33
+ );
26
34
  }
27
35
 
28
36
  export function openCreateAddressDrawer() {
@@ -34,10 +42,13 @@ export function openCreateAddressDrawer() {
34
42
  }
35
43
 
36
44
  export function openAddressActionsDropdown(addressName: string) {
45
+ useInternalSearch(addressName);
46
+
37
47
  cy.get("[data-fs-addresses-table]")
38
48
  .contains(addressName)
39
49
  .parent()
40
50
  .parent()
51
+ .parent()
41
52
  .find("[data-fs-bp-basic-dropdown-menu-trigger]")
42
53
  .click();
43
54
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vtex/faststore-plugin-buyer-portal",
3
- "version": "1.1.92",
3
+ "version": "1.1.94",
4
4
  "description": "A plugin for faststore with buyer portal",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -537,4 +537,4 @@
537
537
  fill="currentColor"
538
538
  />
539
539
  </symbol>
540
- </svg>
540
+ </svg>
@@ -73,7 +73,7 @@ export const DeleteRecipientAddressDrawer = ({
73
73
  <BasicDrawer data-fs-bp-remove-address-drawer close={close} {...props}>
74
74
  <BasicDrawer.Heading title="Delete recipient" onClose={close} />
75
75
  <BasicDrawer.Body>
76
- <div>
76
+ <div data-fs-bp-remove-recipient-form>
77
77
  <p>
78
78
  Permanently delete{" "}
79
79
  <span data-fs-bp-drawer-label>{recipientAddressName}</span>?
@@ -1,4 +1,8 @@
1
1
  import { compareItems, statusFilters } from "../../shared/utils";
2
+ import {
3
+ handleUnauthorizedRedirect,
4
+ withClientErrorBoundary,
5
+ } from "../../shared/utils/withClientErrorBoundary";
2
6
  import { addressesClient } from "../clients/AddressesClient";
3
7
 
4
8
  export type GetAddressesByUnitIdServiceProps = Partial<{
@@ -13,7 +17,7 @@ export type GetAddressesByUnitIdServiceProps = Partial<{
13
17
  cookie: string;
14
18
  };
15
19
 
16
- export const getAddressesByUnitIdService = async ({
20
+ export const getAddressesByUnitIdServiceFn = async ({
17
21
  orgUnitId,
18
22
  status,
19
23
  type,
@@ -46,3 +50,11 @@ export const getAddressesByUnitIdService = async ({
46
50
 
47
51
  return { data: formattedAddress, total };
48
52
  };
53
+
54
+ export const getAddressesByUnitIdService = withClientErrorBoundary(
55
+ getAddressesByUnitIdServiceFn,
56
+ {
57
+ componentName: "AddressesByUnitId",
58
+ onError: handleUnauthorizedRedirect,
59
+ }
60
+ );
@@ -1,4 +1,9 @@
1
- import { compareItems, statusFilters } from "../../shared/utils";
1
+ import {
2
+ compareItems,
3
+ statusFilters,
4
+ withClientErrorBoundary,
5
+ } from "../../shared/utils";
6
+ import { handleUnauthorizedRedirect } from "../../shared/utils/withClientErrorBoundary";
2
7
  import { addressesClient } from "../clients/AddressesClient";
3
8
 
4
9
  import type { AddressData } from "../types/AddressData";
@@ -15,7 +20,7 @@ export type GetAddressesServiceProps = Partial<{
15
20
  };
16
21
 
17
22
  //TODO: Check if deprecated so we can remove this
18
- export const getAddressesService = async ({
23
+ export const getAddressesServiceFn = async ({
19
24
  search = "",
20
25
  customerId,
21
26
  unitId,
@@ -54,3 +59,11 @@ export const getAddressesService = async ({
54
59
  })
55
60
  .sort((a, b) => compareItems(a, b, sort));
56
61
  };
62
+
63
+ export const getAddressesService = withClientErrorBoundary(
64
+ getAddressesServiceFn,
65
+ {
66
+ componentName: "AddressesService",
67
+ onError: handleUnauthorizedRedirect,
68
+ }
69
+ );
@@ -1,3 +1,7 @@
1
+ import {
2
+ withClientErrorBoundary,
3
+ handleUnauthorizedRedirect,
4
+ } from "../../shared/utils/withClientErrorBoundary";
1
5
  import { buyingPoliciesClient } from "../clients/BuyingPoliciesClient";
2
6
  import { BuyingPolicy } from "../types";
3
7
 
@@ -9,7 +13,7 @@ export type GetBuyingPoliciesServiceProps = {
9
13
  page?: number;
10
14
  };
11
15
 
12
- export const getBuyingPoliciesService = async ({
16
+ const getBuyingPoliciesFunction = async ({
13
17
  search,
14
18
  page = 1,
15
19
  contractId,
@@ -19,25 +23,19 @@ export const getBuyingPoliciesService = async ({
19
23
  data: BuyingPolicy[];
20
24
  total: number;
21
25
  }> => {
22
- try {
23
- return await buyingPoliciesClient.getBuyingPoliciesByOrgUnitId(
24
- contractId,
25
- orgUnitId,
26
- cookie,
27
- search,
28
- page
29
- );
30
- } catch (error) {
31
- console.error("Error in getBuyingPoliciesService:", {
32
- error,
33
- orgUnitId,
34
- contractId,
35
- errorMessage: (error as { message?: string })?.message,
36
- });
26
+ return await buyingPoliciesClient.getBuyingPoliciesByOrgUnitId(
27
+ contractId,
28
+ orgUnitId,
29
+ cookie,
30
+ search,
31
+ page
32
+ );
33
+ };
37
34
 
38
- return {
39
- data: [],
40
- total: 0,
41
- };
35
+ export const getBuyingPoliciesService = withClientErrorBoundary(
36
+ getBuyingPoliciesFunction,
37
+ {
38
+ componentName: "BuyingPoliciesService",
39
+ onError: handleUnauthorizedRedirect,
42
40
  }
43
- };
41
+ );
@@ -1,3 +1,7 @@
1
+ import {
2
+ withClientErrorBoundary,
3
+ handleUnauthorizedRedirect,
4
+ } from "../../shared/utils/withClientErrorBoundary";
1
5
  import { contractsClient } from "../clients/ContractsClient";
2
6
 
3
7
  type GetContractDetailsServiceProps = {
@@ -6,7 +10,7 @@ type GetContractDetailsServiceProps = {
6
10
  unitId: string;
7
11
  };
8
12
 
9
- export const getContractDetailsService = async ({
13
+ const getContractDetailsFunction = async ({
10
14
  contractId,
11
15
  cookie,
12
16
  unitId,
@@ -19,3 +23,11 @@ export const getContractDetailsService = async ({
19
23
 
20
24
  return contract;
21
25
  };
26
+
27
+ export const getContractDetailsService = withClientErrorBoundary(
28
+ getContractDetailsFunction,
29
+ {
30
+ componentName: "ContractDetails",
31
+ onError: handleUnauthorizedRedirect,
32
+ }
33
+ );