@paakd/api 0.0.1 → 0.0.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.
Files changed (201) hide show
  1. package/buf/validate/validate_pb.ts +5001 -0
  2. package/dist/gen/buf/validate/validate_pb.d.ts +4634 -0
  3. package/dist/gen/buf/validate/validate_pb.d.ts.map +1 -0
  4. package/dist/gen/buf/validate/validate_pb.js +414 -0
  5. package/dist/gen/src/proto/auth/v1/entities/auth_pb.d.ts +268 -0
  6. package/dist/gen/src/proto/auth/v1/entities/auth_pb.d.ts.map +1 -0
  7. package/dist/gen/src/proto/auth/v1/entities/auth_pb.js +120 -0
  8. package/dist/gen/src/proto/auth/v1/entities/policy_pb.d.ts +235 -0
  9. package/dist/gen/src/proto/auth/v1/entities/policy_pb.d.ts.map +1 -0
  10. package/dist/gen/src/proto/auth/v1/entities/policy_pb.js +98 -0
  11. package/dist/gen/src/proto/auth/v1/service_pb.d.ts +117 -0
  12. package/dist/gen/src/proto/auth/v1/service_pb.d.ts.map +1 -0
  13. package/dist/gen/src/proto/auth/v1/service_pb.js +22 -0
  14. package/dist/gen/src/proto/customers/v1/entities/address_pb.d.ts +371 -0
  15. package/dist/gen/src/proto/customers/v1/entities/address_pb.d.ts.map +1 -0
  16. package/dist/gen/src/proto/customers/v1/entities/address_pb.js +84 -0
  17. package/dist/gen/src/proto/customers/v1/entities/profile_pb.d.ts +189 -0
  18. package/dist/gen/src/proto/customers/v1/entities/profile_pb.d.ts.map +1 -0
  19. package/dist/gen/src/proto/customers/v1/entities/profile_pb.js +70 -0
  20. package/dist/gen/src/proto/customers/v1/service_pb.d.ts +85 -0
  21. package/dist/gen/src/proto/customers/v1/service_pb.d.ts.map +1 -0
  22. package/dist/gen/src/proto/customers/v1/service_pb.js +22 -0
  23. package/dist/gen/src/proto/products/v1/entities/category_pb.d.ts +234 -0
  24. package/dist/gen/src/proto/products/v1/entities/category_pb.d.ts.map +1 -0
  25. package/dist/gen/src/proto/products/v1/entities/category_pb.js +84 -0
  26. package/dist/gen/src/proto/products/v1/entities/collection_pb.d.ts +159 -0
  27. package/dist/gen/src/proto/products/v1/entities/collection_pb.d.ts.map +1 -0
  28. package/dist/gen/src/proto/products/v1/entities/collection_pb.js +70 -0
  29. package/dist/gen/src/proto/products/v1/entities/product/create_pb.d.ts +146 -0
  30. package/dist/gen/src/proto/products/v1/entities/product/create_pb.d.ts.map +1 -0
  31. package/dist/gen/src/proto/products/v1/entities/product/create_pb.js +32 -0
  32. package/dist/gen/src/proto/products/v1/entities/product/option_pb.d.ts +50 -0
  33. package/dist/gen/src/proto/products/v1/entities/product/option_pb.d.ts.map +1 -0
  34. package/dist/gen/src/proto/products/v1/entities/product/option_pb.js +32 -0
  35. package/dist/gen/src/proto/products/v1/entities/product/shared_pb.d.ts +1042 -0
  36. package/dist/gen/src/proto/products/v1/entities/product/shared_pb.d.ts.map +1 -0
  37. package/dist/gen/src/proto/products/v1/entities/product/shared_pb.js +258 -0
  38. package/dist/gen/src/proto/products/v1/entities/product/update_pb.d.ts +236 -0
  39. package/dist/gen/src/proto/products/v1/entities/product/update_pb.d.ts.map +1 -0
  40. package/dist/gen/src/proto/products/v1/entities/product/update_pb.js +88 -0
  41. package/dist/gen/src/proto/products/v1/entities/tag_pb.d.ts +175 -0
  42. package/dist/gen/src/proto/products/v1/entities/tag_pb.d.ts.map +1 -0
  43. package/dist/gen/src/proto/products/v1/entities/tag_pb.js +84 -0
  44. package/dist/gen/src/proto/products/v1/entities/taxonomy_pb.d.ts +477 -0
  45. package/dist/gen/src/proto/products/v1/entities/taxonomy_pb.d.ts.map +1 -0
  46. package/dist/gen/src/proto/products/v1/entities/taxonomy_pb.js +235 -0
  47. package/dist/gen/src/proto/products/v1/entities/type_pb.d.ts +158 -0
  48. package/dist/gen/src/proto/products/v1/entities/type_pb.d.ts.map +1 -0
  49. package/dist/gen/src/proto/products/v1/entities/type_pb.js +70 -0
  50. package/dist/gen/src/proto/products/v1/entities/variant_pb.d.ts +489 -0
  51. package/dist/gen/src/proto/products/v1/entities/variant_pb.d.ts.map +1 -0
  52. package/dist/gen/src/proto/products/v1/entities/variant_pb.js +147 -0
  53. package/dist/gen/src/proto/products/v1/service_pb.d.ts +316 -0
  54. package/dist/gen/src/proto/products/v1/service_pb.d.ts.map +1 -0
  55. package/dist/gen/src/proto/products/v1/service_pb.js +36 -0
  56. package/dist/src/address.d.ts +53 -0
  57. package/dist/src/address.d.ts.map +1 -0
  58. package/dist/src/address.js +233 -0
  59. package/dist/src/address.spec.d.ts +2 -0
  60. package/dist/src/address.spec.d.ts.map +1 -0
  61. package/dist/src/address.spec.js +488 -0
  62. package/dist/src/auth.d.ts +27 -0
  63. package/dist/src/auth.d.ts.map +1 -0
  64. package/dist/src/auth.js +155 -0
  65. package/dist/src/auth.spec.d.ts +2 -0
  66. package/dist/src/auth.spec.d.ts.map +1 -0
  67. package/dist/src/auth.spec.js +582 -0
  68. package/dist/src/compressor/brotli.d.ts +3 -0
  69. package/dist/src/compressor/brotli.d.ts.map +1 -0
  70. package/dist/src/compressor/brotli.js +30 -0
  71. package/dist/src/index.d.ts +6 -0
  72. package/dist/src/index.d.ts.map +1 -0
  73. package/dist/src/interceptors.d.ts +16 -0
  74. package/dist/src/interceptors.d.ts.map +1 -0
  75. package/dist/src/interceptors.js +156 -0
  76. package/dist/src/interceptors.spec.d.ts +2 -0
  77. package/dist/src/interceptors.spec.d.ts.map +1 -0
  78. package/dist/src/interceptors.spec.js +1063 -0
  79. package/dist/src/policies.d.ts +217 -0
  80. package/dist/src/policies.d.ts.map +1 -0
  81. package/dist/src/policies.js +322 -0
  82. package/dist/src/policies.spec.d.ts +2 -0
  83. package/dist/src/policies.spec.d.ts.map +1 -0
  84. package/dist/src/policies.spec.js +463 -0
  85. package/dist/src/products.d.ts +39 -0
  86. package/dist/src/products.d.ts.map +1 -0
  87. package/dist/src/products.js +95 -0
  88. package/dist/src/products.spec.d.ts +2 -0
  89. package/dist/src/products.spec.d.ts.map +1 -0
  90. package/dist/src/products.spec.js +519 -0
  91. package/dist/src/profile.d.ts +62 -0
  92. package/dist/src/profile.d.ts.map +1 -0
  93. package/dist/src/profile.js +151 -0
  94. package/dist/src/profile.spec.d.ts +2 -0
  95. package/dist/src/profile.spec.d.ts.map +1 -0
  96. package/dist/src/profile.spec.js +475 -0
  97. package/dist/src/registration.d.ts +60 -0
  98. package/dist/src/registration.d.ts.map +1 -0
  99. package/dist/src/registration.js +147 -0
  100. package/dist/src/test-utils.d.ts +87 -0
  101. package/dist/src/test-utils.d.ts.map +1 -0
  102. package/dist/src/test-utils.js +132 -0
  103. package/gen/buf/validate/validate_pb.ts +4799 -0
  104. package/gen/src/proto/auth/v1/authv1connect/service.connect.go +454 -0
  105. package/gen/src/proto/auth/v1/entities/auth.pb.go +818 -0
  106. package/gen/src/proto/auth/v1/entities/auth_pb.ts +348 -0
  107. package/gen/src/proto/auth/v1/entities/policy.pb.go +727 -0
  108. package/gen/src/proto/auth/v1/entities/policy_pb.ts +306 -0
  109. package/gen/src/proto/auth/v1/service-AuthService_connectquery.ts +70 -0
  110. package/gen/src/proto/auth/v1/service.pb.go +119 -0
  111. package/gen/src/proto/auth/v1/service_pb.ts +152 -0
  112. package/gen/src/proto/customers/v1/customersv1connect/service.connect.go +358 -0
  113. package/gen/src/proto/customers/v1/entities/address.pb.go +1073 -0
  114. package/gen/src/proto/customers/v1/entities/address_pb.ts +478 -0
  115. package/gen/src/proto/customers/v1/entities/profile.pb.go +633 -0
  116. package/gen/src/proto/customers/v1/entities/profile_pb.ts +252 -0
  117. package/gen/src/proto/customers/v1/service-CustomerService_connectquery.ts +50 -0
  118. package/gen/src/proto/customers/v1/service.pb.go +110 -0
  119. package/gen/src/proto/customers/v1/service_pb.ts +121 -0
  120. package/gen/src/proto/files/v1/entities/file.pb.go +669 -0
  121. package/gen/src/proto/files/v1/entities/file_pb.ts +265 -0
  122. package/gen/src/proto/files/v1/filesv1connect/service.connect.go +200 -0
  123. package/gen/src/proto/files/v1/service-FileService_connectquery.ts +25 -0
  124. package/gen/src/proto/files/v1/service.pb.go +85 -0
  125. package/gen/src/proto/files/v1/service_pb.ts +65 -0
  126. package/gen/src/proto/products/v1/entities/category.pb.go +744 -0
  127. package/gen/src/proto/products/v1/entities/category_pb.ts +318 -0
  128. package/gen/src/proto/products/v1/entities/collection.pb.go +528 -0
  129. package/gen/src/proto/products/v1/entities/collection_pb.ts +214 -0
  130. package/gen/src/proto/products/v1/entities/product/create.pb.go +453 -0
  131. package/gen/src/proto/products/v1/entities/product/create_pb.ts +199 -0
  132. package/gen/src/proto/products/v1/entities/product/option.pb.go +206 -0
  133. package/gen/src/proto/products/v1/entities/product/option_pb.ts +74 -0
  134. package/gen/src/proto/products/v1/entities/product/shared.pb.go +2890 -0
  135. package/gen/src/proto/products/v1/entities/product/shared_pb.ts +1317 -0
  136. package/gen/src/proto/products/v1/entities/product/update.pb.go +794 -0
  137. package/gen/src/proto/products/v1/entities/product/update_pb.ts +325 -0
  138. package/gen/src/proto/products/v1/entities/tag.pb.go +610 -0
  139. package/gen/src/proto/products/v1/entities/tag_pb.ts +233 -0
  140. package/gen/src/proto/products/v1/entities/taxonomy.pb.go +1352 -0
  141. package/gen/src/proto/products/v1/entities/taxonomy_pb.ts +606 -0
  142. package/gen/src/proto/products/v1/entities/type.pb.go +553 -0
  143. package/gen/src/proto/products/v1/entities/type_pb.ts +215 -0
  144. package/gen/src/proto/products/v1/entities/variant.pb.go +1474 -0
  145. package/gen/src/proto/products/v1/entities/variant_pb.ts +629 -0
  146. package/gen/src/proto/products/v1/productsv1connect/service.connect.go +1195 -0
  147. package/gen/src/proto/products/v1/service-ProductsService_connectquery.ts +199 -0
  148. package/gen/src/proto/products/v1/service.pb.go +250 -0
  149. package/gen/src/proto/products/v1/service_pb.ts +429 -0
  150. package/gen/src/proto/promotions/v1/entities/campaign.pb.go +1229 -0
  151. package/gen/src/proto/promotions/v1/entities/campaign_pb.ts +511 -0
  152. package/gen/src/proto/promotions/v1/promotionsv1connect/service.connect.go +289 -0
  153. package/gen/src/proto/promotions/v1/service-CampaignService_connectquery.ts +42 -0
  154. package/gen/src/proto/promotions/v1/service.pb.go +98 -0
  155. package/gen/src/proto/promotions/v1/service_pb.ts +95 -0
  156. package/gen/src/proto/stocknodes/v1/entities/stocknode.pb.go +1499 -0
  157. package/gen/src/proto/stocknodes/v1/entities/stocknode_pb.ts +655 -0
  158. package/gen/src/proto/stocknodes/v1/service-StockNodesService_connectquery.ts +41 -0
  159. package/gen/src/proto/stocknodes/v1/service.pb.go +98 -0
  160. package/gen/src/proto/stocknodes/v1/service_pb.ts +95 -0
  161. package/gen/src/proto/stocknodes/v1/stocknodesv1connect/service.connect.go +297 -0
  162. package/package.json +5 -2
  163. package/src/address.spec.ts +0 -662
  164. package/src/address.ts +0 -300
  165. package/src/auth.spec.ts +0 -771
  166. package/src/auth.ts +0 -168
  167. package/src/compressor/brotli.ts +0 -26
  168. package/src/index.ts +0 -5
  169. package/src/interceptors.spec.ts +0 -1343
  170. package/src/interceptors.ts +0 -224
  171. package/src/policies.spec.ts +0 -595
  172. package/src/policies.ts +0 -431
  173. package/src/products.spec.ts +0 -710
  174. package/src/products.ts +0 -112
  175. package/src/profile.spec.ts +0 -626
  176. package/src/profile.ts +0 -169
  177. package/src/proto/auth/v1/entities/auth.proto +0 -140
  178. package/src/proto/auth/v1/entities/policy.proto +0 -57
  179. package/src/proto/auth/v1/service.proto +0 -26
  180. package/src/proto/customers/v1/entities/address.proto +0 -101
  181. package/src/proto/customers/v1/entities/profile.proto +0 -118
  182. package/src/proto/customers/v1/service.proto +0 -36
  183. package/src/proto/files/v1/entities/file.proto +0 -62
  184. package/src/proto/files/v1/service.proto +0 -19
  185. package/src/proto/products/v1/entities/category.proto +0 -98
  186. package/src/proto/products/v1/entities/collection.proto +0 -72
  187. package/src/proto/products/v1/entities/product/create.proto +0 -41
  188. package/src/proto/products/v1/entities/product/option.proto +0 -17
  189. package/src/proto/products/v1/entities/product/shared.proto +0 -255
  190. package/src/proto/products/v1/entities/product/update.proto +0 -66
  191. package/src/proto/products/v1/entities/tag.proto +0 -73
  192. package/src/proto/products/v1/entities/taxonomy.proto +0 -146
  193. package/src/proto/products/v1/entities/type.proto +0 -98
  194. package/src/proto/products/v1/entities/variant.proto +0 -127
  195. package/src/proto/products/v1/service.proto +0 -78
  196. package/src/proto/promotions/v1/entities/campaign.proto +0 -145
  197. package/src/proto/promotions/v1/service.proto +0 -17
  198. package/src/proto/stocknodes/v1/entities/stocknode.proto +0 -167
  199. package/src/proto/stocknodes/v1/service.proto +0 -21
  200. package/src/registration.ts +0 -170
  201. package/src/test-utils.ts +0 -176
@@ -1,626 +0,0 @@
1
- import { Code, createClient } from '@connectrpc/connect'
2
- import { createGrpcTransport } from '@connectrpc/connect-node'
3
- import { getCheckoutConfig } from '@paakd/config'
4
- import {
5
- getBasicProfile,
6
- getProfile,
7
- updateProfile,
8
- type UpdateProfileProps,
9
- } from './profile'
10
- import {
11
- createAuthenticationInterceptor,
12
- createCustomerAuthenticationInterceptor,
13
- createHeadersInterceptor,
14
- } from './interceptors'
15
- import {
16
- type BaseTestContext,
17
- type MockServiceClient,
18
- clearAllMocks,
19
- createMockConnectError,
20
- setupCommonMocks,
21
- } from './test-utils'
22
-
23
- // Mock dependencies
24
- vi.mock('@connectrpc/connect', async () => {
25
- const actual = await vi.importActual('@connectrpc/connect')
26
- return {
27
- ...actual,
28
- createClient: vi.fn(),
29
- }
30
- })
31
-
32
- vi.mock('@connectrpc/connect-node', () => ({
33
- createGrpcTransport: vi.fn(),
34
- }))
35
-
36
- vi.mock('@paakd/config', () => ({
37
- getCheckoutConfig: vi.fn(),
38
- }))
39
-
40
- vi.mock('./interceptors', () => ({
41
- createAuthenticationInterceptor: vi.fn(),
42
- createCustomerAuthenticationInterceptor: vi.fn(),
43
- createHeadersInterceptor: vi.fn(),
44
- }))
45
-
46
- vi.mock('./compressor/brotli', () => ({
47
- brotliCompression: {
48
- name: 'brotli',
49
- compress: vi.fn(),
50
- decompress: vi.fn(),
51
- },
52
- }))
53
-
54
- vi.mock('../gen/src/proto/customers/v1/service_pb', () => ({
55
- CustomerService: {},
56
- }))
57
-
58
- const mockGetCheckoutConfig = vi.mocked(getCheckoutConfig)
59
- const mockCreateGrpcTransport = vi.mocked(createGrpcTransport)
60
- const mockCreateClient = vi.mocked(createClient)
61
- const mockCreateAuthenticationInterceptor = vi.mocked(
62
- createAuthenticationInterceptor
63
- )
64
- const mockCreateCustomerAuthenticationInterceptor = vi.mocked(
65
- createCustomerAuthenticationInterceptor
66
- )
67
- const mockCreateHeadersInterceptor = vi.mocked(createHeadersInterceptor)
68
-
69
- /**
70
- * Extended test context for profile service
71
- */
72
- interface ProfileTestContext extends BaseTestContext {
73
- client: MockServiceClient
74
- }
75
-
76
- function setupProfileService(): ProfileTestContext {
77
- clearAllMocks()
78
- const { config, interceptors, transport } = setupCommonMocks()
79
-
80
- const client: MockServiceClient = {
81
- basicProfile: vi.fn(),
82
- profile: vi.fn(),
83
- updateProfile: vi.fn(),
84
- }
85
-
86
- mockGetCheckoutConfig.mockResolvedValue(config)
87
- mockCreateGrpcTransport.mockReturnValue(transport)
88
- mockCreateHeadersInterceptor.mockImplementation(() => next => async req => {
89
- return await next(req)
90
- })
91
- mockCreateAuthenticationInterceptor.mockImplementation(
92
- () => next => async req => {
93
- return await next(req)
94
- }
95
- )
96
- mockCreateCustomerAuthenticationInterceptor.mockImplementation(
97
- () => next => async req => {
98
- return await next(req)
99
- }
100
- )
101
- mockCreateClient.mockReturnValue(client as any)
102
-
103
- return {
104
- client,
105
- config,
106
- interceptors,
107
- transport,
108
- }
109
- }
110
-
111
- describe('Profile Service', () => {
112
- let consoleSpy: any
113
-
114
- beforeEach(() => {
115
- consoleSpy = vi.spyOn(console, 'log').mockImplementation(() => {})
116
- })
117
-
118
- afterEach(() => {
119
- consoleSpy.mockRestore()
120
- })
121
-
122
- describe('getBasicProfile', () => {
123
- it('should successfully fetch basic profile for customer', async () => {
124
- const { client } = setupProfileService()
125
-
126
- const mockProfile = {
127
- customerId: 'cust-1',
128
- email: 'user@example.com',
129
- firstName: 'John',
130
- lastName: 'Doe',
131
- }
132
-
133
- client.basicProfile.mockResolvedValue(mockProfile)
134
-
135
- const result = await getBasicProfile({
136
- body: {
137
- customerId: 'cust-1',
138
- jwt: 'token-123',
139
- },
140
- headers: {},
141
- })
142
-
143
- expect((result as any).status).toBe('success')
144
- expect((result as any).value).toEqual(mockProfile)
145
- })
146
-
147
- it('should reject request without authentication', async () => {
148
- const { client } = setupProfileService()
149
-
150
- const error = createMockConnectError(
151
- 16,
152
- 'UNAUTHENTICATED',
153
- 'Invalid JWT token'
154
- )
155
- client.basicProfile.mockRejectedValue(error)
156
-
157
- const result = await getBasicProfile({
158
- body: {
159
- customerId: 'cust-1',
160
- jwt: 'invalid-token',
161
- },
162
- headers: {},
163
- })
164
-
165
- expect((result as any).status).toBe('failed')
166
- })
167
-
168
- it('should handle customer not found error', async () => {
169
- const { client } = setupProfileService()
170
-
171
- const error = createMockConnectError(5, 'NOT_FOUND', 'Customer not found')
172
- client.basicProfile.mockRejectedValue(error)
173
-
174
- const result = await getBasicProfile({
175
- body: {
176
- customerId: 'invalid-cust',
177
- jwt: 'token-123',
178
- },
179
- headers: {},
180
- })
181
-
182
- expect((result as any).status).toBe('failed')
183
- expect((result as any).code).toBe(5)
184
- })
185
-
186
- it('should apply customer authentication interceptor', async () => {
187
- const { client } = setupProfileService()
188
- const jwt = 'user-jwt-token'
189
-
190
- client.basicProfile.mockResolvedValue({
191
- customerId: 'cust-1',
192
- email: 'user@example.com',
193
- })
194
-
195
- await getBasicProfile({
196
- body: {
197
- customerId: 'cust-1',
198
- jwt,
199
- },
200
- headers: {},
201
- })
202
-
203
- expect(mockCreateCustomerAuthenticationInterceptor).toHaveBeenCalledWith(
204
- jwt
205
- )
206
- })
207
- })
208
-
209
- describe('getProfile', () => {
210
- it('should successfully fetch full profile for customer', async () => {
211
- const { client } = setupProfileService()
212
-
213
- const mockProfile = {
214
- customerId: 'cust-1',
215
- email: 'user@example.com',
216
- firstName: 'John',
217
- lastName: 'Doe',
218
- phone: '555-1234',
219
- dateOfBirth: '1990-01-01',
220
- preferences: {
221
- newsletter: true,
222
- sms: false,
223
- },
224
- }
225
-
226
- client.profile.mockResolvedValue(mockProfile)
227
-
228
- const result = await getProfile({
229
- body: {
230
- customerId: 'cust-1',
231
- jwt: 'token-123',
232
- },
233
- headers: {},
234
- })
235
-
236
- expect((result as any).status).toBe('success')
237
- expect((result as any).value).toEqual(mockProfile)
238
- })
239
-
240
- it('should reject unauthenticated requests', async () => {
241
- const { client } = setupProfileService()
242
-
243
- const error = createMockConnectError(
244
- 16,
245
- 'UNAUTHENTICATED',
246
- 'Session expired'
247
- )
248
- client.profile.mockRejectedValue(error)
249
-
250
- const result = await getProfile({
251
- body: {
252
- customerId: 'cust-1',
253
- jwt: 'expired-token',
254
- },
255
- headers: {},
256
- })
257
-
258
- expect((result as any).status).toBe('failed')
259
- })
260
-
261
- it('should handle service unavailability', async () => {
262
- const { client } = setupProfileService()
263
-
264
- const error = createMockConnectError(
265
- 14,
266
- 'UNAVAILABLE',
267
- 'Service temporarily unavailable'
268
- )
269
- client.profile.mockRejectedValue(error)
270
-
271
- const result = await getProfile({
272
- body: {
273
- customerId: 'cust-1',
274
- jwt: 'token-123',
275
- },
276
- headers: {},
277
- })
278
-
279
- expect((result as any).status).toBe('failed')
280
- })
281
-
282
- it('should use checkout config for enterprise URL', async () => {
283
- const { client, config } = setupProfileService()
284
-
285
- client.profile.mockResolvedValue({
286
- customerId: 'cust-1',
287
- email: 'user@example.com',
288
- })
289
-
290
- await getProfile({
291
- body: {
292
- customerId: 'cust-1',
293
- jwt: 'token-123',
294
- },
295
- headers: {},
296
- })
297
-
298
- expect(mockCreateGrpcTransport).toHaveBeenCalledWith(
299
- expect.objectContaining({
300
- baseUrl: config.enterpriseURL,
301
- })
302
- )
303
- })
304
- })
305
-
306
- describe('updateProfile', () => {
307
- it('should successfully update customer profile', async () => {
308
- const { client } = setupProfileService()
309
-
310
- const updateData: UpdateProfileProps = {
311
- body: {
312
- customerId: 'cust-1',
313
- firstName: 'Jane',
314
- lastName: 'Doe',
315
- email: 'jane@example.com',
316
- otherNames: 'Jane Marie',
317
- dateOfBirth: '1990-01-01',
318
- gender: 'female',
319
- phone: '555-1234',
320
- jwt: 'token-123',
321
- } as any,
322
- headers: {},
323
- }
324
-
325
- const mockResponse = {
326
- customerId: 'cust-1',
327
- firstName: 'Jane',
328
- lastName: 'Smith',
329
- email: 'user@example.com',
330
- }
331
-
332
- client.updateProfile.mockResolvedValue(mockResponse)
333
-
334
- const result = await updateProfile(updateData)
335
-
336
- expect((result as any).status).toBe('success')
337
- expect((result as any).value).toEqual(mockResponse)
338
- })
339
-
340
- it('should reject invalid profile data', async () => {
341
- const { client } = setupProfileService()
342
-
343
- const error = createMockConnectError(
344
- 3,
345
- 'INVALID_ARGUMENT',
346
- 'Invalid profile data'
347
- )
348
- client.updateProfile.mockRejectedValue(error)
349
-
350
- const result = await updateProfile({
351
- body: {
352
- customerId: 'cust-1',
353
- firstName: '',
354
- jwt: 'token-123',
355
- } as any,
356
- headers: {},
357
- })
358
-
359
- expect((result as any).status).toBe('failed')
360
- })
361
-
362
- it('should reject update without authentication', async () => {
363
- const { client } = setupProfileService()
364
-
365
- const error = createMockConnectError(16, 'UNAUTHENTICATED', 'Invalid JWT')
366
- client.updateProfile.mockRejectedValue(error)
367
-
368
- const result = await updateProfile({
369
- body: {
370
- customerId: 'cust-1',
371
- firstName: 'John',
372
- jwt: 'invalid-token',
373
- } as any,
374
- headers: {},
375
- })
376
-
377
- expect((result as any).status).toBe('failed')
378
- })
379
-
380
- it('should handle permission denied error', async () => {
381
- const { client } = setupProfileService()
382
-
383
- const error = createMockConnectError(
384
- 7,
385
- 'PERMISSION_DENIED',
386
- 'Cannot update profile for another customer'
387
- )
388
- client.updateProfile.mockRejectedValue(error)
389
-
390
- const result = await updateProfile({
391
- body: {
392
- customerId: 'other-cust',
393
- firstName: 'Jane',
394
- jwt: 'user-jwt',
395
- } as any,
396
- headers: {},
397
- })
398
-
399
- expect((result as any).status).toBe('failed')
400
- })
401
-
402
- it('should not include JWT in service request body', async () => {
403
- const { client } = setupProfileService()
404
-
405
- client.updateProfile.mockResolvedValue({
406
- customerId: 'cust-1',
407
- firstName: 'Jane',
408
- })
409
-
410
- const jwt = 'user-jwt-token'
411
- const updateData: UpdateProfileProps = {
412
- body: {
413
- customerId: 'cust-1',
414
- firstName: 'Jane',
415
- lastName: 'Doe',
416
- email: 'jane@example.com',
417
- otherNames: 'Jane Marie',
418
- dateOfBirth: '1990-01-01',
419
- gender: 'female',
420
- phone: '555-1234',
421
- jwt,
422
- } as any,
423
- headers: {},
424
- }
425
-
426
- await updateProfile(updateData)
427
-
428
- const callArgs = client.updateProfile.mock.calls[0][0]
429
- expect(callArgs).not.toHaveProperty('jwt')
430
- })
431
-
432
- it('should apply three interceptors in correct order', async () => {
433
- const { client } = setupProfileService()
434
-
435
- client.updateProfile.mockResolvedValue({
436
- customerId: 'cust-1',
437
- firstName: 'Jane',
438
- })
439
-
440
- const headers = {
441
- 'x-shop-id': '123',
442
- }
443
- const jwt = 'user-jwt-token'
444
-
445
- await updateProfile({
446
- body: {
447
- customerId: 'cust-1',
448
- firstName: 'Jane',
449
- lastName: 'Doe',
450
- email: 'jane@example.com',
451
- otherNames: 'Jane Marie',
452
- dateOfBirth: '1990-01-01',
453
- gender: 'female',
454
- phone: '555-1234',
455
- jwt,
456
- } as any,
457
- headers,
458
- })
459
-
460
- expect(mockCreateHeadersInterceptor).toHaveBeenCalledWith(headers)
461
- expect(mockCreateAuthenticationInterceptor).toHaveBeenCalled()
462
- expect(mockCreateCustomerAuthenticationInterceptor).toHaveBeenCalledWith(
463
- jwt
464
- )
465
- })
466
-
467
- it('should handle database errors gracefully', async () => {
468
- const { client } = setupProfileService()
469
-
470
- const error = createMockConnectError(13, 'INTERNAL', 'Database error')
471
- client.updateProfile.mockRejectedValue(error)
472
-
473
- const result = await updateProfile({
474
- body: {
475
- customerId: 'cust-1',
476
- firstName: 'Jane',
477
- jwt: 'token-123',
478
- } as any,
479
- headers: {},
480
- })
481
-
482
- expect((result as any).status).toBe('failed')
483
- expect((result as any).code).toBe(Code.Internal)
484
- })
485
- })
486
-
487
- describe('Profile Service - Common Behavior', () => {
488
- it('should load configuration for each request', async () => {
489
- const { client } = setupProfileService()
490
-
491
- client.basicProfile.mockResolvedValue({
492
- customerId: 'cust-1',
493
- email: 'user@example.com',
494
- })
495
-
496
- await getBasicProfile({
497
- body: {
498
- customerId: 'cust-1',
499
- firstName: 'John',
500
- lastName: 'Doe',
501
- email: 'john@example.com',
502
- otherNames: 'John Michael',
503
- dateOfBirth: '1985-05-15',
504
- gender: 'male',
505
- phone: '555-5678',
506
- jwt: 'token-123',
507
- } as any,
508
- headers: {},
509
- })
510
-
511
- expect(mockGetCheckoutConfig).toHaveBeenCalled()
512
- })
513
-
514
- it('should enable compression for all operations', async () => {
515
- const { client } = setupProfileService()
516
-
517
- client.basicProfile.mockResolvedValue({
518
- customerId: 'cust-1',
519
- email: 'user@example.com',
520
- })
521
-
522
- await getBasicProfile({
523
- body: {
524
- customerId: 'cust-1',
525
- firstName: 'John',
526
- lastName: 'Doe',
527
- email: 'john@example.com',
528
- otherNames: 'John Michael',
529
- dateOfBirth: '1985-05-15',
530
- gender: 'male',
531
- phone: '555-5678',
532
- jwt: 'token-123',
533
- } as any,
534
- headers: {},
535
- })
536
-
537
- const transportConfig = (mockCreateGrpcTransport as any).mock.calls[0][0]
538
- expect(transportConfig).toHaveProperty('acceptCompression')
539
- expect(transportConfig).toHaveProperty('sendCompression')
540
- })
541
-
542
- it('should handle concurrent profile operations', async () => {
543
- const { client } = setupProfileService()
544
-
545
- const mockProfile1 = {
546
- customerId: 'cust-1',
547
- email: 'user1@example.com',
548
- firstName: 'John',
549
- }
550
-
551
- const mockProfile2 = {
552
- customerId: 'cust-2',
553
- email: 'user2@example.com',
554
- firstName: 'Jane',
555
- }
556
-
557
- client.basicProfile.mockResolvedValueOnce(mockProfile1)
558
- client.basicProfile.mockResolvedValueOnce(mockProfile2)
559
-
560
- const results = await Promise.all([
561
- getBasicProfile({
562
- body: {
563
- customerId: 'cust-1',
564
- jwt: 'token-1',
565
- },
566
- headers: {},
567
- }),
568
- getBasicProfile({
569
- body: {
570
- customerId: 'cust-2',
571
- jwt: 'token-2',
572
- },
573
- headers: {},
574
- }),
575
- ])
576
-
577
- expect(results).toHaveLength(2)
578
- expect(results.every(r => (r as any).status === 'success')).toBe(true)
579
- })
580
-
581
- it('should handle edge cases with special characters in data', async () => {
582
- const { client } = setupProfileService()
583
-
584
- const mockProfile = {
585
- customerId: 'cust-1',
586
- email: 'user+tag@example.com',
587
- firstName: "O'Connor",
588
- lastName: 'François',
589
- }
590
-
591
- client.basicProfile.mockResolvedValue(mockProfile)
592
-
593
- const result = await getBasicProfile({
594
- body: {
595
- customerId: 'cust-1',
596
- jwt: 'token-123',
597
- },
598
- headers: {},
599
- })
600
-
601
- expect((result as any).status).toBe('success')
602
- expect((result as any).value).toEqual(mockProfile)
603
- })
604
-
605
- it('should handle null or undefined headers gracefully', async () => {
606
- const { client } = setupProfileService()
607
-
608
- client.basicProfile.mockResolvedValue({
609
- customerId: 'cust-1',
610
- email: 'user@example.com',
611
- })
612
-
613
- const result = await getBasicProfile({
614
- body: {
615
- customerId: 'cust-1',
616
- jwt: 'token-123',
617
- },
618
- headers: {
619
- 'x-header': null,
620
- },
621
- })
622
-
623
- expect((result as any).status).toBe('success')
624
- })
625
- })
626
- })