@open-mercato/ui 0.4.11-develop.1971.0f53c78f63 → 0.4.11-develop.1980.243750a91b

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@open-mercato/ui",
3
- "version": "0.4.11-develop.1971.0f53c78f63",
3
+ "version": "0.4.11-develop.1980.243750a91b",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "scripts": {
@@ -132,12 +132,12 @@
132
132
  "recharts": "^2.15.0"
133
133
  },
134
134
  "peerDependencies": {
135
- "@open-mercato/shared": "0.4.11-develop.1971.0f53c78f63",
135
+ "@open-mercato/shared": "0.4.11-develop.1980.243750a91b",
136
136
  "react": ">=18.0.0",
137
137
  "react-dom": ">=18.0.0"
138
138
  },
139
139
  "devDependencies": {
140
- "@open-mercato/shared": "0.4.11-develop.1971.0f53c78f63",
140
+ "@open-mercato/shared": "0.4.11-develop.1980.243750a91b",
141
141
  "@testing-library/dom": "^10.4.1",
142
142
  "@testing-library/jest-dom": "^6.9.1",
143
143
  "@testing-library/react": "^16.3.1",
@@ -37,10 +37,29 @@ jest.mock('../injection/InjectionSpot', () => ({
37
37
  },
38
38
  }))
39
39
 
40
+ jest.mock('../injection/useInjectedMenuItems', () => ({
41
+ useInjectedMenuItems: () => ({
42
+ items: [],
43
+ isLoading: false,
44
+ }),
45
+ }))
46
+
47
+ jest.mock('../injection/eventBridge', () => ({
48
+ useEventBridge: jest.fn(),
49
+ }))
50
+
51
+ jest.mock('../injection/StatusBadgeInjectionSpot', () => ({
52
+ StatusBadgeInjectionSpot: () => <div data-testid="status-badge-injection-spot" />,
53
+ }))
54
+
40
55
  jest.mock('../operations/LastOperationBanner', () => ({
41
56
  LastOperationBanner: () => <div data-testid="last-operation-banner" />,
42
57
  }))
43
58
 
59
+ jest.mock('../progress/ProgressTopBar', () => ({
60
+ ProgressTopBar: () => <div data-testid="progress-top-bar" />,
61
+ }))
62
+
44
63
  jest.mock('../indexes/PartialIndexBanner', () => ({
45
64
  PartialIndexBanner: () => <div data-testid="partial-index-banner" />,
46
65
  }))
@@ -57,6 +76,10 @@ jest.mock('../upgrades/UpgradeActionBanner', () => ({
57
76
  UpgradeActionBanner: () => <div data-testid="upgrade-action-banner" />,
58
77
  }))
59
78
 
79
+ jest.mock('../devtools', () => ({
80
+ UmesDevToolsPanel: () => null,
81
+ }))
82
+
60
83
  const dict = {
61
84
  'appShell.productName': 'Mercato',
62
85
  'appShell.menu': 'Menu',
@@ -1,7 +1,12 @@
1
1
  /** @jest-environment jsdom */
2
+ jest.setTimeout(15000)
2
3
 
3
4
  const fetchCustomFieldFormStructureMock = jest.fn()
4
5
  const buildFormFieldFromCustomFieldDefMock = jest.fn()
6
+ const triggerInjectionEventMock = jest.fn(async (_event: string, data: Record<string, unknown>) => ({
7
+ ok: true,
8
+ data,
9
+ }))
5
10
 
6
11
  jest.mock('next/navigation', () => ({
7
12
  useRouter: () => ({ push: jest.fn() }),
@@ -16,6 +21,16 @@ jest.mock('../confirm-dialog', () => ({
16
21
  ConfirmDialogElement: null,
17
22
  }),
18
23
  }))
24
+ jest.mock('../injection/InjectionSpot', () => ({
25
+ __esModule: true,
26
+ InjectionSpot: () => null,
27
+ useInjectionWidgets: () => ({ widgets: [], loading: false, error: null }),
28
+ useInjectionSpotEvents: () => ({ triggerEvent: triggerInjectionEventMock }),
29
+ }))
30
+ jest.mock('../injection/useInjectionDataWidgets', () => ({
31
+ __esModule: true,
32
+ useInjectionDataWidgets: () => ({ widgets: [], isLoading: false, error: null }),
33
+ }))
19
34
  jest.mock('../custom-fields/FieldDefinitionsManager', () => {
20
35
  const React = require('react')
21
36
  return {
@@ -31,7 +46,7 @@ jest.mock('../utils/customFieldForms', () => ({
31
46
  }))
32
47
 
33
48
  import * as React from 'react'
34
- import { act, fireEvent, screen } from '@testing-library/react'
49
+ import { act, fireEvent, screen, waitFor } from '@testing-library/react'
35
50
  import { renderWithProviders } from '@open-mercato/shared/lib/testing/renderWithProviders'
36
51
  import { CrudForm, type CrudField, type CrudFormGroup } from '../CrudForm'
37
52
 
@@ -53,6 +68,7 @@ describe('CrudForm custom field loading', () => {
53
68
  beforeEach(() => {
54
69
  fetchCustomFieldFormStructureMock.mockReset()
55
70
  buildFormFieldFromCustomFieldDefMock.mockReset()
71
+ triggerInjectionEventMock.mockClear()
56
72
  buildFormFieldFromCustomFieldDefMock.mockReturnValue(null)
57
73
  fetchCustomFieldFormStructureMock.mockResolvedValue({
58
74
  fields: [],
@@ -149,9 +165,14 @@ describe('CrudForm custom field loading', () => {
149
165
  },
150
166
  )
151
167
 
152
- const manageButton = await screen.findByRole('button', { name: 'Manage fields' })
168
+ await waitFor(() => {
169
+ expect(fetchCustomFieldFormStructureMock).toHaveBeenCalledTimes(1)
170
+ })
171
+ const manageButton = await screen.findByRole('button', { name: 'Manage fields' }, { timeout: 3000 })
153
172
 
154
- fireEvent.click(manageButton)
173
+ await act(async () => {
174
+ fireEvent.click(manageButton)
175
+ })
155
176
 
156
177
  expect(handleSubmit).not.toHaveBeenCalled()
157
178
  expect(await screen.findByText('Edit custom fields')).toBeInTheDocument()
@@ -1,4 +1,11 @@
1
1
  /** @jest-environment jsdom */
2
+ jest.setTimeout(15000)
3
+
4
+ const triggerInjectionEventMock = jest.fn(async (_event: string, data: Record<string, unknown>) => ({
5
+ ok: true,
6
+ data,
7
+ }))
8
+
2
9
  jest.mock('next/navigation', () => ({
3
10
  useRouter: () => ({ push: () => {} }),
4
11
  usePathname: () => '/',
@@ -6,6 +13,16 @@ jest.mock('next/navigation', () => ({
6
13
  }))
7
14
  jest.mock('remark-gfm', () => ({ __esModule: true, default: {} }))
8
15
  jest.mock('@uiw/react-md-editor', () => ({ __esModule: true, default: () => null }))
16
+ jest.mock('../injection/InjectionSpot', () => ({
17
+ __esModule: true,
18
+ InjectionSpot: () => null,
19
+ useInjectionWidgets: () => ({ widgets: [], loading: false, error: null }),
20
+ useInjectionSpotEvents: () => ({ triggerEvent: triggerInjectionEventMock }),
21
+ }))
22
+ jest.mock('../injection/useInjectionDataWidgets', () => ({
23
+ __esModule: true,
24
+ useInjectionDataWidgets: () => ({ widgets: [], isLoading: false, error: null }),
25
+ }))
9
26
 
10
27
  import * as React from 'react'
11
28
  import { renderToString } from 'react-dom/server'
@@ -39,6 +56,10 @@ describe('CrudForm SSR render', () => {
39
56
  describe('CrudForm initialValues', () => {
40
57
  const fields: CrudField[] = [{ id: 'name', label: 'Name', type: 'text' }]
41
58
 
59
+ beforeEach(() => {
60
+ triggerInjectionEventMock.mockClear()
61
+ })
62
+
42
63
  function getInput(container: HTMLElement): HTMLInputElement {
43
64
  return container.querySelector('[data-crud-field-id="name"] input[type="text"]') as HTMLInputElement
44
65
  }
@@ -1,4 +1,5 @@
1
1
  /** @jest-environment jsdom */
2
+ jest.setTimeout(15000)
2
3
 
3
4
  const pushMock = jest.fn()
4
5
  const confirmDialogMock = jest.fn()
@@ -1,4 +1,6 @@
1
1
  /** @jest-environment jsdom */
2
+ jest.setTimeout(15000)
3
+
2
4
  const pushMock = jest.fn()
3
5
  const confirmDialogMock = jest.fn()
4
6
 
@@ -15,6 +17,16 @@ jest.mock('../confirm-dialog', () => ({
15
17
  ConfirmDialogElement: null,
16
18
  }),
17
19
  }))
20
+ jest.mock('../injection/InjectionSpot', () => ({
21
+ __esModule: true,
22
+ InjectionSpot: () => null,
23
+ useInjectionWidgets: () => ({ widgets: [], loading: false, error: null }),
24
+ useInjectionSpotEvents: () => ({ triggerEvent: jest.fn() }),
25
+ }))
26
+ jest.mock('../injection/useInjectionDataWidgets', () => ({
27
+ __esModule: true,
28
+ useInjectionDataWidgets: () => ({ widgets: [], isLoading: false, error: null }),
29
+ }))
18
30
 
19
31
  import * as React from 'react'
20
32
  import { act, fireEvent } from '@testing-library/react'
@@ -1,4 +1,6 @@
1
1
  /** @jest-environment jsdom */
2
+ jest.setTimeout(15000)
3
+
2
4
  jest.mock('next/navigation', () => ({
3
5
  useRouter: () => ({ push: () => {} }),
4
6
  usePathname: () => '/',
@@ -6,9 +8,19 @@ jest.mock('next/navigation', () => ({
6
8
  }))
7
9
  jest.mock('remark-gfm', () => ({ __esModule: true, default: {} }))
8
10
  jest.mock('@uiw/react-md-editor', () => ({ __esModule: true, default: () => null }))
11
+ jest.mock('../injection/InjectionSpot', () => ({
12
+ __esModule: true,
13
+ InjectionSpot: () => null,
14
+ useInjectionWidgets: () => ({ widgets: [], loading: false, error: null }),
15
+ useInjectionSpotEvents: () => ({ triggerEvent: jest.fn() }),
16
+ }))
17
+ jest.mock('../injection/useInjectionDataWidgets', () => ({
18
+ __esModule: true,
19
+ useInjectionDataWidgets: () => ({ widgets: [], isLoading: false, error: null }),
20
+ }))
9
21
 
10
22
  import * as React from 'react'
11
- import { act, fireEvent } from '@testing-library/react'
23
+ import { act, fireEvent, waitFor } from '@testing-library/react'
12
24
  import { z } from 'zod'
13
25
  import { renderWithProviders } from '@open-mercato/shared/lib/testing/renderWithProviders'
14
26
  import { CrudForm, type CrudField } from '../CrudForm'
@@ -38,22 +50,32 @@ describe('CrudForm validation state', () => {
38
50
  )
39
51
 
40
52
  const form = container.querySelector('form')
53
+ const nameField = container.querySelector('[data-crud-field-id="name"]')
54
+ const gatewayField = container.querySelector('[data-crud-field-id="gatewayProviderKey"]')
41
55
  const nameInput = container.querySelector('[data-crud-field-id="name"] input[type="text"]')
42
56
 
43
57
  expect(form).not.toBeNull()
58
+ expect(nameField).not.toBeNull()
59
+ expect(gatewayField).not.toBeNull()
44
60
  expect(nameInput).not.toBeNull()
45
61
 
46
62
  await act(async () => {
47
63
  fireEvent.submit(form as HTMLFormElement)
48
64
  })
49
65
 
50
- expect(container.querySelectorAll('.text-xs.text-red-600')).toHaveLength(2)
66
+ await waitFor(() => {
67
+ expect(nameField?.querySelector('.text-xs.text-red-600')).toHaveTextContent('This field is required')
68
+ expect(gatewayField?.querySelector('.text-xs.text-red-600')).toHaveTextContent('This field is required')
69
+ })
51
70
 
52
71
  await act(async () => {
53
72
  fireEvent.change(nameInput as HTMLInputElement, { target: { value: 'QA test link' } })
54
73
  })
55
74
 
56
- expect(container.querySelectorAll('.text-xs.text-red-600')).toHaveLength(1)
75
+ await waitFor(() => {
76
+ expect(nameField?.querySelector('.text-xs.text-red-600')).toBeNull()
77
+ expect(gatewayField?.querySelector('.text-xs.text-red-600')).toHaveTextContent('This field is required')
78
+ })
57
79
  expect(container.textContent).toContain('Gateway provider')
58
80
  })
59
81
 
@@ -97,7 +119,9 @@ describe('CrudForm validation state', () => {
97
119
  fireEvent.submit(form as HTMLFormElement)
98
120
  })
99
121
 
100
- expect(getByText('Use camelCase starting with a letter.')).toBeInTheDocument()
122
+ await waitFor(() => {
123
+ expect(getByText('Use camelCase starting with a letter.')).toBeInTheDocument()
124
+ })
101
125
  })
102
126
 
103
127
  it('validates number fields on blur', async () => {