@smess/networking 1.0.16 → 1.0.19
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/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/services/store.cart.service.d.ts +139 -0
- package/dist/services/store.cart.service.js +166 -0
- package/dist/services/store.cart.service.test.d.ts +1 -0
- package/dist/services/store.cart.service.test.js +335 -0
- package/dist/services/store.product.service.d.ts +161 -0
- package/dist/services/store.product.service.js +164 -0
- package/dist/services/store.product.service.test.d.ts +1 -0
- package/dist/services/store.product.service.test.js +402 -0
- package/dist/services/store.service.d.ts +9 -0
- package/dist/services/store.service.js +14 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -2,6 +2,8 @@ export * from "./services/user.service";
|
|
|
2
2
|
export * from "./services/product.service";
|
|
3
3
|
export * from "./services/auth.service";
|
|
4
4
|
export * from "./services/store.service";
|
|
5
|
+
export * from "./services/store.cart.service";
|
|
6
|
+
export * from "./services/store.product.service";
|
|
5
7
|
export * from "./services/customer.service";
|
|
6
8
|
export * from "./services/order.service";
|
|
7
9
|
export * from "./services/cache.service";
|
package/dist/index.js
CHANGED
|
@@ -2,6 +2,8 @@ export * from "./services/user.service";
|
|
|
2
2
|
export * from "./services/product.service";
|
|
3
3
|
export * from "./services/auth.service";
|
|
4
4
|
export * from "./services/store.service";
|
|
5
|
+
export * from "./services/store.cart.service";
|
|
6
|
+
export * from "./services/store.product.service";
|
|
5
7
|
export * from "./services/customer.service";
|
|
6
8
|
export * from "./services/order.service";
|
|
7
9
|
export * from "./services/cache.service";
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { ProviderType, NetworkingConfig, NetworkingUIEventWrapped, HttpResponse } from "../types/types";
|
|
2
|
+
import { SmessService } from "./smess.service";
|
|
3
|
+
import { BehaviorSubject, Observable } from "rxjs";
|
|
4
|
+
export type StoreCartTarget = "cart-get" | "cart-update" | "cart-add-item" | "cart-update-item" | "cart-delete-item" | "cart-delete-all-items";
|
|
5
|
+
export interface BillingInformation {
|
|
6
|
+
email?: string;
|
|
7
|
+
phone_number?: string;
|
|
8
|
+
street?: string;
|
|
9
|
+
city?: string;
|
|
10
|
+
postal_code?: string;
|
|
11
|
+
state?: string;
|
|
12
|
+
country?: string;
|
|
13
|
+
[key: string]: unknown;
|
|
14
|
+
}
|
|
15
|
+
export interface ShippingInformation {
|
|
16
|
+
email?: string;
|
|
17
|
+
phone_number?: string;
|
|
18
|
+
street?: string;
|
|
19
|
+
city?: string;
|
|
20
|
+
postal_code?: string;
|
|
21
|
+
state?: string;
|
|
22
|
+
country?: string;
|
|
23
|
+
[key: string]: unknown;
|
|
24
|
+
}
|
|
25
|
+
export interface CartItem {
|
|
26
|
+
[key: string]: unknown;
|
|
27
|
+
}
|
|
28
|
+
export interface StoreInfo {
|
|
29
|
+
[key: string]: unknown;
|
|
30
|
+
}
|
|
31
|
+
export interface Cart {
|
|
32
|
+
dateCreated: string;
|
|
33
|
+
dateModified: string;
|
|
34
|
+
discountTotal: number;
|
|
35
|
+
discountTax: number;
|
|
36
|
+
shippingTotal: number;
|
|
37
|
+
shippingTax: number;
|
|
38
|
+
cartTax: number;
|
|
39
|
+
total: number;
|
|
40
|
+
totalTax: number;
|
|
41
|
+
customerId: string | null;
|
|
42
|
+
billingInformation: BillingInformation | null;
|
|
43
|
+
shippingInformation: ShippingInformation | null;
|
|
44
|
+
paymentMethod: string;
|
|
45
|
+
deliveryType: string;
|
|
46
|
+
transactionId: string | null;
|
|
47
|
+
customerIpAddress: string;
|
|
48
|
+
customerUserAgent: string;
|
|
49
|
+
customerNote: string | null;
|
|
50
|
+
cartHash: string;
|
|
51
|
+
cartItems: CartItem[];
|
|
52
|
+
paymentUrl: string | null;
|
|
53
|
+
store: StoreInfo | null;
|
|
54
|
+
[key: string]: unknown;
|
|
55
|
+
}
|
|
56
|
+
export interface CartUpdateRequest {
|
|
57
|
+
status?: string;
|
|
58
|
+
customer_note?: string;
|
|
59
|
+
customer_id?: string;
|
|
60
|
+
payment_method?: string;
|
|
61
|
+
delivery_type?: string;
|
|
62
|
+
billing_information?: BillingInformation;
|
|
63
|
+
shipping_information?: ShippingInformation;
|
|
64
|
+
[key: string]: unknown;
|
|
65
|
+
}
|
|
66
|
+
export interface CartAddItemRequest {
|
|
67
|
+
product_id: string;
|
|
68
|
+
quantity: number;
|
|
69
|
+
[key: string]: unknown;
|
|
70
|
+
}
|
|
71
|
+
export interface CartUpdateItemQuantityRequest {
|
|
72
|
+
quantity: number;
|
|
73
|
+
}
|
|
74
|
+
export declare class StoreCartProvider implements ProviderType {
|
|
75
|
+
private readonly config;
|
|
76
|
+
private readonly target;
|
|
77
|
+
private readonly $cartHash;
|
|
78
|
+
private readonly $storeId;
|
|
79
|
+
constructor(config: NetworkingConfig, target: StoreCartTarget, $cartHash: BehaviorSubject<string | null>, $storeId: BehaviorSubject<string | null>);
|
|
80
|
+
get baseURL(): string;
|
|
81
|
+
get path(): string;
|
|
82
|
+
get method(): string;
|
|
83
|
+
get headers(): Record<string, string>;
|
|
84
|
+
getPath(...queryParams: unknown[]): string;
|
|
85
|
+
}
|
|
86
|
+
export interface StoreCartServiceType {
|
|
87
|
+
getCart(): Observable<NetworkingUIEventWrapped<HttpResponse>>;
|
|
88
|
+
updateCart(payload: CartUpdateRequest): Observable<NetworkingUIEventWrapped<HttpResponse>>;
|
|
89
|
+
addItem(payload: CartAddItemRequest): Observable<NetworkingUIEventWrapped<HttpResponse>>;
|
|
90
|
+
updateItemQuantity(itemId: string, payload: CartUpdateItemQuantityRequest): Observable<NetworkingUIEventWrapped<HttpResponse>>;
|
|
91
|
+
deleteItem(itemId: string): Observable<NetworkingUIEventWrapped<HttpResponse>>;
|
|
92
|
+
deleteAllItems(): Observable<NetworkingUIEventWrapped<HttpResponse>>;
|
|
93
|
+
}
|
|
94
|
+
export declare class StoreCartService implements StoreCartServiceType {
|
|
95
|
+
private readonly config;
|
|
96
|
+
private readonly $cartHash;
|
|
97
|
+
private readonly $storeId;
|
|
98
|
+
constructor(config: NetworkingConfig, $storeId?: BehaviorSubject<string | null>);
|
|
99
|
+
get currentCartHash(): string | null;
|
|
100
|
+
get cartHash$(): BehaviorSubject<string | null>;
|
|
101
|
+
get currentStoreId(): string | null;
|
|
102
|
+
get storeId$(): BehaviorSubject<string | null>;
|
|
103
|
+
setStoreId(storeId: string | null): void;
|
|
104
|
+
provider(target: StoreCartTarget): SmessService<StoreCartProvider>;
|
|
105
|
+
/**
|
|
106
|
+
* Update the cart hash from cart response
|
|
107
|
+
*/
|
|
108
|
+
private updateCartHash;
|
|
109
|
+
/**
|
|
110
|
+
* Get the current cart
|
|
111
|
+
* GET api/v1/store/cart
|
|
112
|
+
*/
|
|
113
|
+
getCart(): Observable<NetworkingUIEventWrapped<HttpResponse>>;
|
|
114
|
+
/**
|
|
115
|
+
* Update cart (e.g., add notes, apply coupon)
|
|
116
|
+
* PUT api/v1/store/cart
|
|
117
|
+
*/
|
|
118
|
+
updateCart(payload: CartUpdateRequest): Observable<NetworkingUIEventWrapped<HttpResponse>>;
|
|
119
|
+
/**
|
|
120
|
+
* Add item to cart
|
|
121
|
+
* POST api/v1/store/cart/items
|
|
122
|
+
*/
|
|
123
|
+
addItem(payload: CartAddItemRequest): Observable<NetworkingUIEventWrapped<HttpResponse>>;
|
|
124
|
+
/**
|
|
125
|
+
* Update item quantity in cart
|
|
126
|
+
* PUT api/v1/store/cart/items/{id}
|
|
127
|
+
*/
|
|
128
|
+
updateItemQuantity(itemId: string, payload: CartUpdateItemQuantityRequest): Observable<NetworkingUIEventWrapped<HttpResponse>>;
|
|
129
|
+
/**
|
|
130
|
+
* Delete item from cart
|
|
131
|
+
* DELETE api/v1/store/cart/items/{id}
|
|
132
|
+
*/
|
|
133
|
+
deleteItem(itemId: string): Observable<NetworkingUIEventWrapped<HttpResponse>>;
|
|
134
|
+
/**
|
|
135
|
+
* Delete all items from cart
|
|
136
|
+
* DELETE api/v1/store/cart/items
|
|
137
|
+
*/
|
|
138
|
+
deleteAllItems(): Observable<NetworkingUIEventWrapped<HttpResponse>>;
|
|
139
|
+
}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { Accept, SMESSHeader, SmessService } from "./smess.service";
|
|
2
|
+
import { BehaviorSubject } from "rxjs";
|
|
3
|
+
import { tap } from "rxjs/operators";
|
|
4
|
+
export class StoreCartProvider {
|
|
5
|
+
constructor(config, target, $cartHash, $storeId) {
|
|
6
|
+
this.config = config;
|
|
7
|
+
this.target = target;
|
|
8
|
+
this.$cartHash = $cartHash;
|
|
9
|
+
this.$storeId = $storeId;
|
|
10
|
+
}
|
|
11
|
+
get baseURL() {
|
|
12
|
+
return this.config.version
|
|
13
|
+
? `${this.config.baseUrl}/${this.config.version}`
|
|
14
|
+
: this.config.baseUrl;
|
|
15
|
+
}
|
|
16
|
+
get path() {
|
|
17
|
+
switch (this.target) {
|
|
18
|
+
case "cart-get":
|
|
19
|
+
return "/store/cart";
|
|
20
|
+
case "cart-update":
|
|
21
|
+
return "/store/cart";
|
|
22
|
+
case "cart-add-item":
|
|
23
|
+
return "/store/cart/items";
|
|
24
|
+
case "cart-update-item":
|
|
25
|
+
return "/store/cart/items/\${id}";
|
|
26
|
+
case "cart-delete-item":
|
|
27
|
+
return "/store/cart/items/\${id}";
|
|
28
|
+
case "cart-delete-all-items":
|
|
29
|
+
return "/store/cart/items";
|
|
30
|
+
default:
|
|
31
|
+
return "/store/cart";
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
get method() {
|
|
35
|
+
switch (this.target) {
|
|
36
|
+
case "cart-get":
|
|
37
|
+
return "GET";
|
|
38
|
+
case "cart-update":
|
|
39
|
+
return "PUT";
|
|
40
|
+
case "cart-add-item":
|
|
41
|
+
return "POST";
|
|
42
|
+
case "cart-update-item":
|
|
43
|
+
return "PUT";
|
|
44
|
+
case "cart-delete-item":
|
|
45
|
+
return "DELETE";
|
|
46
|
+
case "cart-delete-all-items":
|
|
47
|
+
return "DELETE";
|
|
48
|
+
default:
|
|
49
|
+
return "GET";
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
get headers() {
|
|
53
|
+
let headers = SmessService.getHeaders(Accept.V1, null);
|
|
54
|
+
if (this.config.clientId) {
|
|
55
|
+
headers[SMESSHeader.ClientId] = this.config.clientId;
|
|
56
|
+
}
|
|
57
|
+
if (this.config.apiKey) {
|
|
58
|
+
headers[SMESSHeader.ApiKey] = this.config.apiKey;
|
|
59
|
+
}
|
|
60
|
+
const filteredHeaders = SmessService.filterHeaders(headers);
|
|
61
|
+
// Add X-Nonce-Token header if cartHash is available
|
|
62
|
+
if (this.$cartHash.value) {
|
|
63
|
+
filteredHeaders["X-Nonce-Token"] = this.$cartHash.value;
|
|
64
|
+
}
|
|
65
|
+
// Add X-Store-Id header if storeId is available
|
|
66
|
+
if (this.$storeId.value) {
|
|
67
|
+
filteredHeaders["X-Store-Id"] = this.$storeId.value;
|
|
68
|
+
}
|
|
69
|
+
return filteredHeaders;
|
|
70
|
+
}
|
|
71
|
+
getPath(...queryParams) {
|
|
72
|
+
let definedPath = this.path;
|
|
73
|
+
const params = definedPath.match(/\$\{(.+?)\}/g);
|
|
74
|
+
params?.forEach((value, index) => {
|
|
75
|
+
definedPath = definedPath.replace(value, String(queryParams[index]));
|
|
76
|
+
});
|
|
77
|
+
return definedPath;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
export class StoreCartService {
|
|
81
|
+
constructor(config, $storeId) {
|
|
82
|
+
this.config = config;
|
|
83
|
+
this.$cartHash = new BehaviorSubject(null);
|
|
84
|
+
// Use the provided BehaviorSubject or create a new one
|
|
85
|
+
this.$storeId = $storeId || new BehaviorSubject(null);
|
|
86
|
+
}
|
|
87
|
+
// Getter to access the current cart hash
|
|
88
|
+
get currentCartHash() {
|
|
89
|
+
return this.$cartHash.value;
|
|
90
|
+
}
|
|
91
|
+
// Getter to access the cart hash as observable
|
|
92
|
+
get cartHash$() {
|
|
93
|
+
return this.$cartHash;
|
|
94
|
+
}
|
|
95
|
+
// Getter to access the current store ID
|
|
96
|
+
get currentStoreId() {
|
|
97
|
+
return this.$storeId.value;
|
|
98
|
+
}
|
|
99
|
+
// Getter to access the store ID as observable
|
|
100
|
+
get storeId$() {
|
|
101
|
+
return this.$storeId;
|
|
102
|
+
}
|
|
103
|
+
// Method to update the store ID
|
|
104
|
+
setStoreId(storeId) {
|
|
105
|
+
this.$storeId.next(storeId);
|
|
106
|
+
}
|
|
107
|
+
provider(target) {
|
|
108
|
+
const targetWrapper = new StoreCartProvider(this.config, target, this.$cartHash, this.$storeId);
|
|
109
|
+
return new SmessService(targetWrapper);
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Update the cart hash from cart response
|
|
113
|
+
*/
|
|
114
|
+
updateCartHash(result) {
|
|
115
|
+
if (result.hasSuccess && result.response) {
|
|
116
|
+
const response = result.response;
|
|
117
|
+
// Try to extract cartHash from different possible structures
|
|
118
|
+
const cartHash = response.data?.cartHash || response.cartHash;
|
|
119
|
+
if (cartHash) {
|
|
120
|
+
this.$cartHash.next(cartHash);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Get the current cart
|
|
126
|
+
* GET api/v1/store/cart
|
|
127
|
+
*/
|
|
128
|
+
getCart() {
|
|
129
|
+
return this.provider("cart-get").request().pipe(tap((result) => this.updateCartHash(result)));
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Update cart (e.g., add notes, apply coupon)
|
|
133
|
+
* PUT api/v1/store/cart
|
|
134
|
+
*/
|
|
135
|
+
updateCart(payload) {
|
|
136
|
+
return this.provider("cart-update").request(payload).pipe(tap((result) => this.updateCartHash(result)));
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Add item to cart
|
|
140
|
+
* POST api/v1/store/cart/items
|
|
141
|
+
*/
|
|
142
|
+
addItem(payload) {
|
|
143
|
+
return this.provider("cart-add-item").request(payload).pipe(tap((result) => this.updateCartHash(result)));
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Update item quantity in cart
|
|
147
|
+
* PUT api/v1/store/cart/items/{id}
|
|
148
|
+
*/
|
|
149
|
+
updateItemQuantity(itemId, payload) {
|
|
150
|
+
return this.provider("cart-update-item").request(payload, undefined, itemId).pipe(tap((result) => this.updateCartHash(result)));
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Delete item from cart
|
|
154
|
+
* DELETE api/v1/store/cart/items/{id}
|
|
155
|
+
*/
|
|
156
|
+
deleteItem(itemId) {
|
|
157
|
+
return this.provider("cart-delete-item").request(undefined, undefined, itemId);
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Delete all items from cart
|
|
161
|
+
* DELETE api/v1/store/cart/items
|
|
162
|
+
*/
|
|
163
|
+
deleteAllItems() {
|
|
164
|
+
return this.provider("cart-delete-all-items").request();
|
|
165
|
+
}
|
|
166
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
import { StoreCartService, StoreCartProvider, } from "./store.cart.service";
|
|
2
|
+
import { NetworkingUIEventWrapped, AlertModel, } from "../types/types";
|
|
3
|
+
import { BehaviorSubject, of } from "rxjs";
|
|
4
|
+
describe("StoreCartService", () => {
|
|
5
|
+
const config = {
|
|
6
|
+
baseUrl: "https://api.example.com",
|
|
7
|
+
isProd: false,
|
|
8
|
+
clientId: "test-client-id",
|
|
9
|
+
apiKey: "test-api-key",
|
|
10
|
+
};
|
|
11
|
+
let service;
|
|
12
|
+
beforeEach(() => {
|
|
13
|
+
service = new StoreCartService(config);
|
|
14
|
+
});
|
|
15
|
+
it("should initialize with null cartHash and storeId", () => {
|
|
16
|
+
expect(service.currentCartHash).toBe(null);
|
|
17
|
+
expect(service.cartHash$.value).toBe(null);
|
|
18
|
+
expect(service.currentStoreId).toBe(null);
|
|
19
|
+
expect(service.storeId$.value).toBe(null);
|
|
20
|
+
});
|
|
21
|
+
it("should initialize with provided storeId BehaviorSubject", () => {
|
|
22
|
+
const storeId = "store-123";
|
|
23
|
+
const $storeId = new BehaviorSubject(storeId);
|
|
24
|
+
const serviceWithStore = new StoreCartService(config, $storeId);
|
|
25
|
+
expect(serviceWithStore.currentStoreId).toBe(storeId);
|
|
26
|
+
expect(serviceWithStore.storeId$.value).toBe(storeId);
|
|
27
|
+
});
|
|
28
|
+
it("should update storeId dynamically", () => {
|
|
29
|
+
expect(service.currentStoreId).toBe(null);
|
|
30
|
+
service.setStoreId("store-456");
|
|
31
|
+
expect(service.currentStoreId).toBe("store-456");
|
|
32
|
+
expect(service.storeId$.value).toBe("store-456");
|
|
33
|
+
});
|
|
34
|
+
describe("getCart", () => {
|
|
35
|
+
it("should get cart successfully and update cartHash", async () => {
|
|
36
|
+
const cart = {
|
|
37
|
+
dateCreated: "2025-10-14 12:56:31",
|
|
38
|
+
dateModified: "2025-10-14 12:56:31",
|
|
39
|
+
discountTotal: 0,
|
|
40
|
+
discountTax: 0,
|
|
41
|
+
shippingTotal: 0,
|
|
42
|
+
shippingTax: 0,
|
|
43
|
+
cartTax: 0,
|
|
44
|
+
total: 20.0,
|
|
45
|
+
totalTax: 0,
|
|
46
|
+
customerId: "cust-123",
|
|
47
|
+
billingInformation: null,
|
|
48
|
+
shippingInformation: null,
|
|
49
|
+
paymentMethod: "cash",
|
|
50
|
+
deliveryType: "pickup",
|
|
51
|
+
transactionId: null,
|
|
52
|
+
customerIpAddress: "172.18.0.1",
|
|
53
|
+
customerUserAgent: "Test Agent",
|
|
54
|
+
customerNote: null,
|
|
55
|
+
cartHash: "test-hash-123",
|
|
56
|
+
cartItems: [
|
|
57
|
+
{
|
|
58
|
+
id: "item-1",
|
|
59
|
+
productId: "prod-1",
|
|
60
|
+
name: "Test Product",
|
|
61
|
+
quantity: 2,
|
|
62
|
+
price: 10.0,
|
|
63
|
+
total: 20.0,
|
|
64
|
+
},
|
|
65
|
+
],
|
|
66
|
+
paymentUrl: null,
|
|
67
|
+
store: null,
|
|
68
|
+
};
|
|
69
|
+
jest.spyOn(service, "provider").mockReturnValue({
|
|
70
|
+
request: () => of(NetworkingUIEventWrapped.succeeded(cart)),
|
|
71
|
+
});
|
|
72
|
+
const result = await service.getCart().toPromise();
|
|
73
|
+
expect(result?.hasSuccess).toBe(true);
|
|
74
|
+
expect(result?.response).toEqual(cart);
|
|
75
|
+
expect(service.currentCartHash).toBe("test-hash-123");
|
|
76
|
+
});
|
|
77
|
+
it("should handle getCart error", async () => {
|
|
78
|
+
jest.spyOn(service, "provider").mockReturnValue({
|
|
79
|
+
request: () => of(NetworkingUIEventWrapped.failed(AlertModel.default())),
|
|
80
|
+
});
|
|
81
|
+
const result = await service.getCart().toPromise();
|
|
82
|
+
expect(result?.hasFailed).toBe(true);
|
|
83
|
+
expect(result?.alertModel).toBeInstanceOf(AlertModel);
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
describe("updateCart", () => {
|
|
87
|
+
it("should update cart successfully", async () => {
|
|
88
|
+
const payload = {
|
|
89
|
+
status: "submitted",
|
|
90
|
+
customer_note: "Customer Note Example",
|
|
91
|
+
customer_id: "f1df6e9a-0160-11f0-82c2-6cac1a7e2953",
|
|
92
|
+
payment_method: "bank_transfer",
|
|
93
|
+
delivery_type: "delivery",
|
|
94
|
+
billing_information: {
|
|
95
|
+
email: "billing@example.com",
|
|
96
|
+
phone_number: "+1-555-111-2222",
|
|
97
|
+
street: "456 Market Street",
|
|
98
|
+
city: "san_francisco",
|
|
99
|
+
postal_code: "94103",
|
|
100
|
+
state: "ca",
|
|
101
|
+
country: "us",
|
|
102
|
+
},
|
|
103
|
+
shipping_information: {
|
|
104
|
+
email: "john.doe@example.com",
|
|
105
|
+
phone_number: "+1-555-123-4567",
|
|
106
|
+
street: "123 Main Street",
|
|
107
|
+
city: "san_francisco",
|
|
108
|
+
postal_code: "94105",
|
|
109
|
+
state: "ca",
|
|
110
|
+
country: "us",
|
|
111
|
+
},
|
|
112
|
+
};
|
|
113
|
+
const cart = {
|
|
114
|
+
dateCreated: "2025-10-14 12:56:31",
|
|
115
|
+
dateModified: "2025-10-14 12:56:31",
|
|
116
|
+
discountTotal: 0,
|
|
117
|
+
discountTax: 0,
|
|
118
|
+
shippingTotal: 0,
|
|
119
|
+
shippingTax: 0,
|
|
120
|
+
cartTax: 0,
|
|
121
|
+
total: 0,
|
|
122
|
+
totalTax: 0,
|
|
123
|
+
customerId: null,
|
|
124
|
+
billingInformation: null,
|
|
125
|
+
shippingInformation: null,
|
|
126
|
+
paymentMethod: "cash",
|
|
127
|
+
deliveryType: "pickup",
|
|
128
|
+
transactionId: null,
|
|
129
|
+
customerIpAddress: "172.18.0.1",
|
|
130
|
+
customerUserAgent: "Test Agent",
|
|
131
|
+
customerNote: "Please deliver in the evening",
|
|
132
|
+
cartHash: "test-hash",
|
|
133
|
+
cartItems: [],
|
|
134
|
+
paymentUrl: null,
|
|
135
|
+
store: null,
|
|
136
|
+
};
|
|
137
|
+
jest.spyOn(service, "provider").mockReturnValue({
|
|
138
|
+
request: () => of(NetworkingUIEventWrapped.succeeded(cart)),
|
|
139
|
+
});
|
|
140
|
+
const result = await service.updateCart(payload).toPromise();
|
|
141
|
+
expect(result?.hasSuccess).toBe(true);
|
|
142
|
+
expect(result?.response).toEqual(cart);
|
|
143
|
+
});
|
|
144
|
+
it("should handle updateCart error", async () => {
|
|
145
|
+
const payload = {
|
|
146
|
+
status: "invalid_status",
|
|
147
|
+
};
|
|
148
|
+
jest.spyOn(service, "provider").mockReturnValue({
|
|
149
|
+
request: () => of(NetworkingUIEventWrapped.failed(AlertModel.default())),
|
|
150
|
+
});
|
|
151
|
+
const result = await service.updateCart(payload).toPromise();
|
|
152
|
+
expect(result?.hasFailed).toBe(true);
|
|
153
|
+
expect(result?.alertModel).toBeInstanceOf(AlertModel);
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
describe("addItem", () => {
|
|
157
|
+
it("should add item to cart successfully", async () => {
|
|
158
|
+
const payload = {
|
|
159
|
+
product_id: "prod-123",
|
|
160
|
+
quantity: 3,
|
|
161
|
+
};
|
|
162
|
+
const cart = {
|
|
163
|
+
dateCreated: "2025-10-14 12:56:31",
|
|
164
|
+
dateModified: "2025-10-14 12:56:31",
|
|
165
|
+
discountTotal: 0,
|
|
166
|
+
discountTax: 0,
|
|
167
|
+
shippingTotal: 0,
|
|
168
|
+
shippingTax: 0,
|
|
169
|
+
cartTax: 0,
|
|
170
|
+
total: 45.0,
|
|
171
|
+
totalTax: 0,
|
|
172
|
+
customerId: null,
|
|
173
|
+
billingInformation: null,
|
|
174
|
+
shippingInformation: null,
|
|
175
|
+
paymentMethod: "cash",
|
|
176
|
+
deliveryType: "pickup",
|
|
177
|
+
transactionId: null,
|
|
178
|
+
customerIpAddress: "172.18.0.1",
|
|
179
|
+
customerUserAgent: "Test Agent",
|
|
180
|
+
customerNote: null,
|
|
181
|
+
cartHash: "test-hash",
|
|
182
|
+
cartItems: [
|
|
183
|
+
{
|
|
184
|
+
id: "item-1",
|
|
185
|
+
productId: "prod-123",
|
|
186
|
+
quantity: 3,
|
|
187
|
+
price: 15.0,
|
|
188
|
+
total: 45.0,
|
|
189
|
+
},
|
|
190
|
+
],
|
|
191
|
+
paymentUrl: null,
|
|
192
|
+
store: null,
|
|
193
|
+
};
|
|
194
|
+
jest.spyOn(service, "provider").mockReturnValue({
|
|
195
|
+
request: () => of(NetworkingUIEventWrapped.succeeded(cart)),
|
|
196
|
+
});
|
|
197
|
+
const result = await service.addItem(payload).toPromise();
|
|
198
|
+
expect(result?.hasSuccess).toBe(true);
|
|
199
|
+
expect(result?.response).toEqual(cart);
|
|
200
|
+
});
|
|
201
|
+
it("should handle addItem error", async () => {
|
|
202
|
+
const payload = {
|
|
203
|
+
product_id: "prod-999",
|
|
204
|
+
quantity: 1,
|
|
205
|
+
};
|
|
206
|
+
jest.spyOn(service, "provider").mockReturnValue({
|
|
207
|
+
request: () => of(NetworkingUIEventWrapped.failed(AlertModel.default())),
|
|
208
|
+
});
|
|
209
|
+
const result = await service.addItem(payload).toPromise();
|
|
210
|
+
expect(result?.hasFailed).toBe(true);
|
|
211
|
+
expect(result?.alertModel).toBeInstanceOf(AlertModel);
|
|
212
|
+
});
|
|
213
|
+
});
|
|
214
|
+
describe("updateItemQuantity", () => {
|
|
215
|
+
it("should update item quantity successfully", async () => {
|
|
216
|
+
const itemId = "item-123";
|
|
217
|
+
const payload = {
|
|
218
|
+
quantity: 5,
|
|
219
|
+
};
|
|
220
|
+
const cart = {
|
|
221
|
+
dateCreated: "2025-10-14 12:56:31",
|
|
222
|
+
dateModified: "2025-10-14 12:56:31",
|
|
223
|
+
discountTotal: 0,
|
|
224
|
+
discountTax: 0,
|
|
225
|
+
shippingTotal: 0,
|
|
226
|
+
shippingTax: 0,
|
|
227
|
+
cartTax: 0,
|
|
228
|
+
total: 75.0,
|
|
229
|
+
totalTax: 0,
|
|
230
|
+
customerId: null,
|
|
231
|
+
billingInformation: null,
|
|
232
|
+
shippingInformation: null,
|
|
233
|
+
paymentMethod: "cash",
|
|
234
|
+
deliveryType: "pickup",
|
|
235
|
+
transactionId: null,
|
|
236
|
+
customerIpAddress: "172.18.0.1",
|
|
237
|
+
customerUserAgent: "Test Agent",
|
|
238
|
+
customerNote: null,
|
|
239
|
+
cartHash: "test-hash",
|
|
240
|
+
cartItems: [
|
|
241
|
+
{
|
|
242
|
+
id: itemId,
|
|
243
|
+
productId: "prod-123",
|
|
244
|
+
quantity: 5,
|
|
245
|
+
price: 15.0,
|
|
246
|
+
total: 75.0,
|
|
247
|
+
},
|
|
248
|
+
],
|
|
249
|
+
paymentUrl: null,
|
|
250
|
+
store: null,
|
|
251
|
+
};
|
|
252
|
+
jest.spyOn(service, "provider").mockReturnValue({
|
|
253
|
+
request: () => of(NetworkingUIEventWrapped.succeeded(cart)),
|
|
254
|
+
});
|
|
255
|
+
const result = await service.updateItemQuantity(itemId, payload).toPromise();
|
|
256
|
+
expect(result?.hasSuccess).toBe(true);
|
|
257
|
+
expect(result?.response).toEqual(cart);
|
|
258
|
+
});
|
|
259
|
+
it("should handle updateItemQuantity error", async () => {
|
|
260
|
+
const itemId = "item-999";
|
|
261
|
+
const payload = {
|
|
262
|
+
quantity: 5,
|
|
263
|
+
};
|
|
264
|
+
jest.spyOn(service, "provider").mockReturnValue({
|
|
265
|
+
request: () => of(NetworkingUIEventWrapped.failed(AlertModel.default())),
|
|
266
|
+
});
|
|
267
|
+
const result = await service.updateItemQuantity(itemId, payload).toPromise();
|
|
268
|
+
expect(result?.hasFailed).toBe(true);
|
|
269
|
+
expect(result?.alertModel).toBeInstanceOf(AlertModel);
|
|
270
|
+
});
|
|
271
|
+
});
|
|
272
|
+
describe("deleteItem", () => {
|
|
273
|
+
it("should delete item from cart successfully", async () => {
|
|
274
|
+
const itemId = "item-123";
|
|
275
|
+
jest.spyOn(service, "provider").mockReturnValue({
|
|
276
|
+
request: () => of(NetworkingUIEventWrapped.succeeded(undefined)),
|
|
277
|
+
});
|
|
278
|
+
const result = await service.deleteItem(itemId).toPromise();
|
|
279
|
+
expect(result?.hasSuccess).toBe(true);
|
|
280
|
+
});
|
|
281
|
+
it("should handle deleteItem error", async () => {
|
|
282
|
+
const itemId = "item-999";
|
|
283
|
+
jest.spyOn(service, "provider").mockReturnValue({
|
|
284
|
+
request: () => of(NetworkingUIEventWrapped.failed(AlertModel.default())),
|
|
285
|
+
});
|
|
286
|
+
const result = await service.deleteItem(itemId).toPromise();
|
|
287
|
+
expect(result?.hasFailed).toBe(true);
|
|
288
|
+
expect(result?.alertModel).toBeInstanceOf(AlertModel);
|
|
289
|
+
});
|
|
290
|
+
});
|
|
291
|
+
describe("deleteAllItems", () => {
|
|
292
|
+
it("should delete all items from cart successfully", async () => {
|
|
293
|
+
jest.spyOn(service, "provider").mockReturnValue({
|
|
294
|
+
request: () => of(NetworkingUIEventWrapped.succeeded(undefined)),
|
|
295
|
+
});
|
|
296
|
+
const result = await service.deleteAllItems().toPromise();
|
|
297
|
+
expect(result?.hasSuccess).toBe(true);
|
|
298
|
+
});
|
|
299
|
+
it("should handle deleteAllItems error", async () => {
|
|
300
|
+
jest.spyOn(service, "provider").mockReturnValue({
|
|
301
|
+
request: () => of(NetworkingUIEventWrapped.failed(AlertModel.default())),
|
|
302
|
+
});
|
|
303
|
+
const result = await service.deleteAllItems().toPromise();
|
|
304
|
+
expect(result?.hasFailed).toBe(true);
|
|
305
|
+
expect(result?.alertModel).toBeInstanceOf(AlertModel);
|
|
306
|
+
});
|
|
307
|
+
});
|
|
308
|
+
describe("headers", () => {
|
|
309
|
+
it("should include X-Store-Id header when storeId is set", () => {
|
|
310
|
+
const storeId = "store-123";
|
|
311
|
+
const cartHash = "cart-hash-456";
|
|
312
|
+
const $cartHashSubject = new BehaviorSubject(cartHash);
|
|
313
|
+
const $storeIdSubject = new BehaviorSubject(storeId);
|
|
314
|
+
const provider = new StoreCartProvider(config, "cart-get", $cartHashSubject, $storeIdSubject);
|
|
315
|
+
const headers = provider.headers;
|
|
316
|
+
expect(headers["X-Store-Id"]).toBe(storeId);
|
|
317
|
+
expect(headers["X-Nonce-Token"]).toBe(cartHash);
|
|
318
|
+
});
|
|
319
|
+
it("should not include X-Store-Id header when storeId is null", () => {
|
|
320
|
+
const $cartHashSubject = new BehaviorSubject(null);
|
|
321
|
+
const $storeIdSubject = new BehaviorSubject(null);
|
|
322
|
+
const provider = new StoreCartProvider(config, "cart-get", $cartHashSubject, $storeIdSubject);
|
|
323
|
+
const headers = provider.headers;
|
|
324
|
+
expect(headers["X-Store-Id"]).toBeUndefined();
|
|
325
|
+
});
|
|
326
|
+
it("should include X-Nonce-Token header when cartHash is set", () => {
|
|
327
|
+
const cartHash = "cart-hash-789";
|
|
328
|
+
const $cartHashSubject = new BehaviorSubject(cartHash);
|
|
329
|
+
const $storeIdSubject = new BehaviorSubject(null);
|
|
330
|
+
const provider = new StoreCartProvider(config, "cart-get", $cartHashSubject, $storeIdSubject);
|
|
331
|
+
const headers = provider.headers;
|
|
332
|
+
expect(headers["X-Nonce-Token"]).toBe(cartHash);
|
|
333
|
+
});
|
|
334
|
+
});
|
|
335
|
+
});
|