@smess/networking 1.0.3 → 1.0.5
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 +9 -9
- package/dist/index.js +11 -31
- package/dist/scripts/real-test.js +184 -23
- package/dist/src/core/axios.d.ts +5 -12
- package/dist/src/core/axios.js +21 -24
- package/dist/src/core/axios.observable.d.ts +2 -2
- package/dist/src/core/axios.observable.js +14 -17
- package/dist/src/core/base.provider.advanced.test.js +3 -5
- package/dist/src/core/base.provider.d.ts +1 -1
- package/dist/src/core/base.provider.js +6 -6
- package/dist/src/core/base.provider.test.js +3 -5
- package/dist/src/core/base.service.wrapper.advanced.test.js +9 -11
- package/dist/src/core/base.service.wrapper.d.ts +1 -1
- package/dist/src/core/base.service.wrapper.js +3 -7
- package/dist/src/core/base.service.wrapper.test.js +6 -8
- package/dist/src/core/rx.http.service.d.ts +5 -12
- package/dist/src/core/rx.http.service.js +21 -24
- package/dist/src/services/auth.service.d.ts +10 -8
- package/dist/src/services/auth.service.js +31 -35
- package/dist/src/services/auth.service.test.js +38 -38
- package/dist/src/services/customer.service.d.ts +43 -0
- package/dist/src/services/customer.service.js +70 -0
- package/dist/src/services/customer.service.test.d.ts +1 -0
- package/dist/src/services/customer.service.test.js +96 -0
- package/dist/src/services/logger.service.js +4 -8
- package/dist/src/services/logger.service.test.js +16 -18
- package/dist/src/services/order.service.d.ts +60 -0
- package/dist/src/services/order.service.js +89 -0
- package/dist/src/services/order.service.test.d.ts +1 -0
- package/dist/src/services/order.service.test.js +135 -0
- package/dist/src/services/product.service.d.ts +6 -6
- package/dist/src/services/product.service.js +4 -9
- package/dist/src/services/product.service.test.js +20 -21
- package/dist/src/services/smess.service.d.ts +3 -2
- package/dist/src/services/smess.service.js +30 -39
- package/dist/src/services/smess.service.test.js +39 -46
- package/dist/src/services/store.service.d.ts +39 -0
- package/dist/src/services/store.service.js +73 -0
- package/dist/src/services/store.service.test.d.ts +1 -0
- package/dist/src/services/store.service.test.js +104 -0
- package/dist/src/services/user.service.d.ts +5 -5
- package/dist/src/services/user.service.js +4 -9
- package/dist/src/services/user.service.test.js +17 -18
- package/dist/src/types/types.d.ts +1 -3
- package/dist/src/types/types.js +6 -13
- package/dist/src/types/types.test.js +5 -7
- package/dist/src/utils/networking-import.js +3 -43
- package/dist/src/utils/rxjs-import.js +5 -34
- package/package.json +1 -1
|
@@ -1,27 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
};
|
|
5
|
-
|
|
6
|
-
exports.SmessService = exports.Accept = exports.ContentType = exports.SMESSHeader = void 0;
|
|
7
|
-
const types_1 = require("../types/types");
|
|
8
|
-
const rxjs_import_1 = require("../utils/rxjs-import");
|
|
9
|
-
const rx_http_service_1 = __importDefault(require("../core/rx.http.service"));
|
|
10
|
-
const logger_service_1 = require("../services/logger.service");
|
|
11
|
-
var SMESSHeader;
|
|
1
|
+
import { NetworkingUIEventWrapped, AlertModel, AlertButtonModel } from '../types/types.js';
|
|
2
|
+
import { of, catchError, mergeMap, startWith } from '../utils/rxjs-import.js';
|
|
3
|
+
import HttpService from '../core/rx.http.service.js';
|
|
4
|
+
import { $logger } from '../services/logger.service.js';
|
|
5
|
+
export var SMESSHeader;
|
|
12
6
|
(function (SMESSHeader) {
|
|
13
7
|
SMESSHeader["ContentType"] = "Content-Type";
|
|
14
8
|
SMESSHeader["Authorization"] = "Authorization";
|
|
15
9
|
SMESSHeader["Accept"] = "Accept";
|
|
16
10
|
SMESSHeader["ApiKey"] = "X-Api-Key";
|
|
17
11
|
SMESSHeader["ClientId"] = "X-Client-Id";
|
|
18
|
-
})(SMESSHeader || (
|
|
19
|
-
var ContentType;
|
|
12
|
+
})(SMESSHeader || (SMESSHeader = {}));
|
|
13
|
+
export var ContentType;
|
|
20
14
|
(function (ContentType) {
|
|
21
15
|
ContentType["Json"] = "application/json";
|
|
22
16
|
ContentType["FormURLEncoded"] = "application/x-www-form-urlencoded";
|
|
23
|
-
})(ContentType || (
|
|
24
|
-
var Accept;
|
|
17
|
+
})(ContentType || (ContentType = {}));
|
|
18
|
+
export var Accept;
|
|
25
19
|
(function (Accept) {
|
|
26
20
|
Accept["V1"] = "application/json";
|
|
27
21
|
Accept["V2"] = "application/vnd.smess.v2+json";
|
|
@@ -33,28 +27,27 @@ var Accept;
|
|
|
33
27
|
Accept["V8"] = "application/vnd.smess.v8+json";
|
|
34
28
|
Accept["V9"] = "application/vnd.smess.v9+json";
|
|
35
29
|
Accept["V10"] = "application/vnd.smess.v10+json";
|
|
36
|
-
})(Accept || (
|
|
37
|
-
class SmessService {
|
|
30
|
+
})(Accept || (Accept = {}));
|
|
31
|
+
export class SmessService {
|
|
38
32
|
constructor(target) {
|
|
39
33
|
this.target = target;
|
|
40
34
|
// Set default headers
|
|
41
|
-
|
|
35
|
+
$logger.info('SmessService initialized', {
|
|
42
36
|
target: this.target,
|
|
43
37
|
baseURL: this.target.baseURL,
|
|
44
38
|
method: this.target.method,
|
|
45
39
|
headers: this.target.headers,
|
|
46
40
|
}, 'SmessService');
|
|
47
|
-
this.httpService =
|
|
41
|
+
this.httpService = HttpService.create({
|
|
48
42
|
baseURL: this.target.baseURL,
|
|
49
43
|
headers: this.target.headers,
|
|
50
44
|
method: this.target.method,
|
|
51
45
|
});
|
|
52
46
|
this.httpService.interceptors.response.use((response) => response, async (error) => {
|
|
53
|
-
var _a;
|
|
54
47
|
const originalRequest = error.config;
|
|
55
|
-
if (
|
|
48
|
+
if (error.response?.status === 401 && !originalRequest._retry) {
|
|
56
49
|
originalRequest._retry = true;
|
|
57
|
-
|
|
50
|
+
$logger.info('SmessService constructor - 401 retry', originalRequest, 'SmessService');
|
|
58
51
|
// Implement token refresh logic here
|
|
59
52
|
// Then retry the original request
|
|
60
53
|
// return httpService.request(originalRequest);
|
|
@@ -69,8 +62,12 @@ class SmessService {
|
|
|
69
62
|
}
|
|
70
63
|
return headers;
|
|
71
64
|
}
|
|
65
|
+
static filterHeaders(headers) {
|
|
66
|
+
const filteredHeaders = Object.fromEntries(Object.entries(headers).filter(([_, value]) => value !== undefined && value !== null && value !== ''));
|
|
67
|
+
return filteredHeaders;
|
|
68
|
+
}
|
|
72
69
|
static commonHeaders(version, options) {
|
|
73
|
-
const { shouldAddClientIdHeader = true, } = options
|
|
70
|
+
const { shouldAddClientIdHeader = true, } = options ?? {};
|
|
74
71
|
const headers = {
|
|
75
72
|
Accept: version,
|
|
76
73
|
Authorization: '',
|
|
@@ -81,9 +78,6 @@ class SmessService {
|
|
|
81
78
|
}
|
|
82
79
|
// MARK: - Public
|
|
83
80
|
request(request, mockResponse, ...queryParams) {
|
|
84
|
-
if (mockResponse !== undefined) {
|
|
85
|
-
return (0, rxjs_import_1.of)(types_1.NetworkingUIEventWrapped.succeeded(mockResponse));
|
|
86
|
-
}
|
|
87
81
|
const url = queryParams.length
|
|
88
82
|
? this.target.getPath(...queryParams)
|
|
89
83
|
: this.target.path;
|
|
@@ -94,11 +88,9 @@ class SmessService {
|
|
|
94
88
|
config.data = request;
|
|
95
89
|
config.params = request;
|
|
96
90
|
}
|
|
97
|
-
// Note: HttpService.get expects (url, config)
|
|
98
91
|
observable = this.httpService.get(url, config);
|
|
99
92
|
}
|
|
100
93
|
else if (this.target.method === 'POST') {
|
|
101
|
-
// HttpService.post expects (url, data, config)
|
|
102
94
|
observable = this.httpService.post(url, request, config);
|
|
103
95
|
}
|
|
104
96
|
else if (this.target.method === 'PATCH') {
|
|
@@ -110,28 +102,27 @@ class SmessService {
|
|
|
110
102
|
else {
|
|
111
103
|
observable = this.httpService.request(config);
|
|
112
104
|
}
|
|
113
|
-
return observable.pipe(
|
|
105
|
+
return observable.pipe(catchError((error) => this.transformAxiosError(error, mockResponse)), mergeMap((data) => this.transformAxiosResponse(data)), startWith(NetworkingUIEventWrapped.waiting()));
|
|
114
106
|
}
|
|
115
107
|
// MARK: - Private
|
|
116
108
|
transformAxiosError(error, mockResponse) {
|
|
117
|
-
|
|
109
|
+
$logger.error('transformAxiosError', error, 'SmessService');
|
|
118
110
|
const message = error instanceof Error ? error.message : String(error);
|
|
119
111
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Required for axios compatibility
|
|
120
112
|
const response = error.response;
|
|
121
113
|
const httpErrorCode = response ? response.status : 0;
|
|
122
|
-
const title = response
|
|
123
|
-
const alertModel = new
|
|
114
|
+
const title = response?.statusText;
|
|
115
|
+
const alertModel = new AlertModel(message, httpErrorCode, true, title, response?.data, [AlertButtonModel.buttonYes()]);
|
|
124
116
|
if (mockResponse) {
|
|
125
|
-
return
|
|
117
|
+
return of(NetworkingUIEventWrapped.succeeded(mockResponse));
|
|
126
118
|
}
|
|
127
|
-
return
|
|
119
|
+
return of(NetworkingUIEventWrapped.failed(alertModel));
|
|
128
120
|
}
|
|
129
121
|
transformAxiosResponse(response) {
|
|
130
|
-
|
|
131
|
-
if (response instanceof
|
|
132
|
-
return
|
|
122
|
+
$logger.info('transformAxiosResponse', response, 'SmessService');
|
|
123
|
+
if (response instanceof NetworkingUIEventWrapped) {
|
|
124
|
+
return of(response);
|
|
133
125
|
}
|
|
134
|
-
return
|
|
126
|
+
return of(NetworkingUIEventWrapped.succeeded(response.data));
|
|
135
127
|
}
|
|
136
128
|
}
|
|
137
|
-
exports.SmessService = SmessService;
|
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
1
|
/* eslint-disable @typescript-eslint/no-explicit-any -- Required for test mocks */
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
import { SmessService } from './smess.service.js';
|
|
3
|
+
import { NetworkingUIEventWrapped } from '../types/types.js';
|
|
4
|
+
import { of, throwError } from 'rxjs';
|
|
7
5
|
describe('SmessService', () => {
|
|
8
6
|
const config = {
|
|
9
7
|
baseUrl: 'https://api.example.com',
|
|
@@ -19,88 +17,83 @@ describe('SmessService', () => {
|
|
|
19
17
|
getPath: () => '/resource',
|
|
20
18
|
};
|
|
21
19
|
it('should return succeeded for GET', done => {
|
|
22
|
-
const service = new
|
|
20
|
+
const service = new SmessService(provider);
|
|
23
21
|
service['httpService'] = {
|
|
24
|
-
get: jest.fn(() =>
|
|
22
|
+
get: jest.fn(() => of({ data: { foo: 'bar' } })),
|
|
25
23
|
post: jest.fn(),
|
|
26
24
|
patch: jest.fn(),
|
|
27
25
|
put: jest.fn(),
|
|
28
|
-
|
|
29
|
-
request: jest.fn((payload) => {
|
|
30
|
-
if (payload === 'error') {
|
|
31
|
-
return (0, rxjs_1.throwError)(() => new Error('Test error'));
|
|
32
|
-
}
|
|
33
|
-
return (0, rxjs_1.of)(types_1.NetworkingUIEventWrapped.succeeded({ foo: 'bar' }));
|
|
34
|
-
}),
|
|
26
|
+
request: jest.fn(),
|
|
35
27
|
interceptors: { response: { use: jest.fn() } },
|
|
36
28
|
};
|
|
37
|
-
service.request().subscribe(result => {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
29
|
+
service.request().subscribe((result) => {
|
|
30
|
+
if (result.hasSuccess) {
|
|
31
|
+
expect(result.response).toEqual({ foo: 'bar' });
|
|
32
|
+
done();
|
|
33
|
+
}
|
|
41
34
|
});
|
|
42
35
|
});
|
|
43
36
|
it('should return succeeded for POST', done => {
|
|
44
|
-
const postProvider =
|
|
45
|
-
const service = new
|
|
37
|
+
const postProvider = { ...provider, method: 'POST' };
|
|
38
|
+
const service = new SmessService(postProvider);
|
|
46
39
|
service['httpService'] = {
|
|
47
40
|
get: jest.fn(),
|
|
48
|
-
post: jest.fn((
|
|
49
|
-
if (payload === 'error') {
|
|
50
|
-
return (0, rxjs_1.throwError)(() => new Error('Test error'));
|
|
51
|
-
}
|
|
52
|
-
return (0, rxjs_1.of)(types_1.NetworkingUIEventWrapped.succeeded({ foo: 'baz' }));
|
|
53
|
-
}),
|
|
41
|
+
post: jest.fn(() => of({ data: { foo: 'baz' } })),
|
|
54
42
|
patch: jest.fn(),
|
|
55
43
|
put: jest.fn(),
|
|
56
44
|
request: jest.fn(),
|
|
57
45
|
interceptors: { response: { use: jest.fn() } },
|
|
58
46
|
};
|
|
59
|
-
service.request({ some: 'data' }).subscribe(result => {
|
|
60
|
-
|
|
61
|
-
|
|
47
|
+
service.request({ some: 'data' }).subscribe((result) => {
|
|
48
|
+
if (result.hasSuccess) {
|
|
49
|
+
expect(result.response).toEqual({ foo: 'baz' });
|
|
50
|
+
done();
|
|
51
|
+
}
|
|
62
52
|
});
|
|
63
53
|
});
|
|
64
54
|
it('should handle error', done => {
|
|
65
|
-
const service = new
|
|
55
|
+
const service = new SmessService(provider);
|
|
66
56
|
service['httpService'] = {
|
|
67
|
-
get: jest.fn(() =>
|
|
57
|
+
get: jest.fn(() => throwError(() => new Error('Test error'))),
|
|
68
58
|
post: jest.fn(),
|
|
69
59
|
patch: jest.fn(),
|
|
70
60
|
put: jest.fn(),
|
|
71
61
|
request: jest.fn(),
|
|
72
62
|
interceptors: { response: { use: jest.fn() } },
|
|
73
63
|
};
|
|
74
|
-
service.request().subscribe(result => {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
64
|
+
service.request().subscribe((result) => {
|
|
65
|
+
if (result.hasFailed) {
|
|
66
|
+
expect(result).toBeInstanceOf(NetworkingUIEventWrapped);
|
|
67
|
+
expect(result.hasFailed).toBe(true);
|
|
68
|
+
expect(result.alertModel).toBeTruthy();
|
|
69
|
+
expect(result.alertModel?.message).toBe('Test error');
|
|
70
|
+
done();
|
|
71
|
+
}
|
|
81
72
|
});
|
|
82
73
|
});
|
|
83
74
|
it('should return mock response if provided', done => {
|
|
84
|
-
const service = new
|
|
75
|
+
const service = new SmessService(provider);
|
|
85
76
|
service['httpService'] = {
|
|
86
|
-
get: jest.fn(() =>
|
|
77
|
+
get: jest.fn(() => throwError(() => new Error('Test error'))),
|
|
87
78
|
post: jest.fn(),
|
|
88
79
|
patch: jest.fn(),
|
|
89
80
|
put: jest.fn(),
|
|
90
81
|
request: jest.fn((payload, mockResponse) => {
|
|
91
82
|
if (payload === 'error') {
|
|
92
|
-
return
|
|
83
|
+
return throwError(() => new Error('Test error'));
|
|
93
84
|
}
|
|
94
85
|
if (mockResponse !== undefined) {
|
|
95
|
-
return
|
|
86
|
+
return of(NetworkingUIEventWrapped.succeeded(mockResponse));
|
|
96
87
|
}
|
|
97
|
-
return
|
|
88
|
+
return of({ data: { foo: 'mock' } });
|
|
98
89
|
}),
|
|
99
90
|
interceptors: { response: { use: jest.fn() } },
|
|
100
91
|
};
|
|
101
|
-
service.request(undefined, { foo: 'mock' }).subscribe(result => {
|
|
102
|
-
|
|
103
|
-
|
|
92
|
+
service.request(undefined, { foo: 'mock' }).subscribe((result) => {
|
|
93
|
+
if (result.hasSuccess) {
|
|
94
|
+
expect(result.response).toEqual({ foo: 'mock' });
|
|
95
|
+
done();
|
|
96
|
+
}
|
|
104
97
|
});
|
|
105
98
|
});
|
|
106
99
|
});
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { ProviderType, NetworkingConfig, NetworkingUIEventWrapped, HttpResponse } from '../types/types.js';
|
|
2
|
+
import { SmessService } from './smess.service.js';
|
|
3
|
+
import { BehaviorSubject, Observable } from 'rxjs';
|
|
4
|
+
export type StoreTarget = 'store-get' | 'store-list' | 'store-product-category-list' | 'store-product-collection' | 'store-featured-product-list';
|
|
5
|
+
export interface ProductCollectionRequest {
|
|
6
|
+
page?: number;
|
|
7
|
+
per_page?: number;
|
|
8
|
+
search?: string;
|
|
9
|
+
sort_by?: string;
|
|
10
|
+
category?: string;
|
|
11
|
+
min_price?: number;
|
|
12
|
+
max_price?: number;
|
|
13
|
+
only_discounted?: boolean;
|
|
14
|
+
unit?: string;
|
|
15
|
+
supplier?: string;
|
|
16
|
+
has_offer?: boolean;
|
|
17
|
+
}
|
|
18
|
+
export declare class StoreProvider implements ProviderType {
|
|
19
|
+
private readonly config;
|
|
20
|
+
private readonly target;
|
|
21
|
+
private readonly $authToken;
|
|
22
|
+
constructor(config: NetworkingConfig, target: StoreTarget, $authToken: BehaviorSubject<string | null>);
|
|
23
|
+
get baseURL(): string;
|
|
24
|
+
get path(): string;
|
|
25
|
+
get method(): string;
|
|
26
|
+
get headers(): Record<string, string>;
|
|
27
|
+
getPath(...queryParams: unknown[]): string;
|
|
28
|
+
}
|
|
29
|
+
export declare class StoreService {
|
|
30
|
+
private readonly config;
|
|
31
|
+
private readonly $authToken;
|
|
32
|
+
constructor(config: NetworkingConfig, $authToken: BehaviorSubject<string | null>);
|
|
33
|
+
provider(target: StoreTarget): SmessService<StoreProvider>;
|
|
34
|
+
get(id: string): Observable<NetworkingUIEventWrapped<HttpResponse>>;
|
|
35
|
+
list(): Observable<NetworkingUIEventWrapped<HttpResponse>>;
|
|
36
|
+
productCategoryList(): Observable<NetworkingUIEventWrapped<HttpResponse>>;
|
|
37
|
+
productCollection(id: string, payload: ProductCollectionRequest): Observable<NetworkingUIEventWrapped<HttpResponse>>;
|
|
38
|
+
featuredProductList(id: string): Observable<NetworkingUIEventWrapped<HttpResponse>>;
|
|
39
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { Accept, SMESSHeader, SmessService } from './smess.service.js';
|
|
2
|
+
export class StoreProvider {
|
|
3
|
+
constructor(config, target, $authToken) {
|
|
4
|
+
this.config = config;
|
|
5
|
+
this.target = target;
|
|
6
|
+
this.$authToken = $authToken;
|
|
7
|
+
}
|
|
8
|
+
get baseURL() {
|
|
9
|
+
return this.config.version ? `${this.config.baseUrl}/${this.config.version}` : this.config.baseUrl;
|
|
10
|
+
}
|
|
11
|
+
get path() {
|
|
12
|
+
switch (this.target) {
|
|
13
|
+
case 'store-get':
|
|
14
|
+
return '/store/${id}/information';
|
|
15
|
+
case 'store-list':
|
|
16
|
+
return '/store/list';
|
|
17
|
+
case 'store-product-category-list':
|
|
18
|
+
return '/store/product-category-list';
|
|
19
|
+
case 'store-product-collection':
|
|
20
|
+
return '/store/${id}/product-collection';
|
|
21
|
+
case 'store-featured-product-list':
|
|
22
|
+
return '/store/${id}/featured-product-list';
|
|
23
|
+
default:
|
|
24
|
+
return '/store/${id}';
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
get method() {
|
|
28
|
+
return 'GET';
|
|
29
|
+
}
|
|
30
|
+
get headers() {
|
|
31
|
+
let headers = SmessService.getHeaders(Accept.V1, this.$authToken.value);
|
|
32
|
+
if (this.config.clientId) {
|
|
33
|
+
headers[SMESSHeader.ClientId] = this.config.clientId;
|
|
34
|
+
}
|
|
35
|
+
if (this.config.apiKey) {
|
|
36
|
+
headers[SMESSHeader.ApiKey] = this.config.apiKey;
|
|
37
|
+
}
|
|
38
|
+
return SmessService.filterHeaders(headers);
|
|
39
|
+
}
|
|
40
|
+
getPath(...queryParams) {
|
|
41
|
+
let definedPath = this.path;
|
|
42
|
+
const params = definedPath.match(/\$\{(.+?)\}/g);
|
|
43
|
+
params?.forEach((value, index) => {
|
|
44
|
+
definedPath = definedPath.replace(value, String(queryParams[index]));
|
|
45
|
+
});
|
|
46
|
+
return definedPath;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
export class StoreService {
|
|
50
|
+
constructor(config, $authToken) {
|
|
51
|
+
this.config = config;
|
|
52
|
+
this.$authToken = $authToken;
|
|
53
|
+
}
|
|
54
|
+
provider(target) {
|
|
55
|
+
const targetWrapper = new StoreProvider(this.config, target, this.$authToken);
|
|
56
|
+
return new SmessService(targetWrapper);
|
|
57
|
+
}
|
|
58
|
+
get(id) {
|
|
59
|
+
return this.provider('store-get').request(null, undefined, id);
|
|
60
|
+
}
|
|
61
|
+
list() {
|
|
62
|
+
return this.provider('store-list').request();
|
|
63
|
+
}
|
|
64
|
+
productCategoryList() {
|
|
65
|
+
return this.provider('store-product-category-list').request();
|
|
66
|
+
}
|
|
67
|
+
productCollection(id, payload) {
|
|
68
|
+
return this.provider('store-product-collection').request(payload, undefined, id);
|
|
69
|
+
}
|
|
70
|
+
featuredProductList(id) {
|
|
71
|
+
return this.provider('store-featured-product-list').request(null, undefined, id);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { StoreService } from './store.service.js';
|
|
2
|
+
import { NetworkingUIEventWrapped, AlertModel } from '../types/types.js';
|
|
3
|
+
import { of, BehaviorSubject } from 'rxjs';
|
|
4
|
+
describe('StoreService', () => {
|
|
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
|
+
let $authToken;
|
|
13
|
+
beforeEach(() => {
|
|
14
|
+
$authToken = new BehaviorSubject(null);
|
|
15
|
+
service = new StoreService(config, $authToken);
|
|
16
|
+
});
|
|
17
|
+
it('get success', async () => {
|
|
18
|
+
const response = { data: { id: '1', name: 'Store' } };
|
|
19
|
+
jest.spyOn(service, 'provider').mockReturnValue({
|
|
20
|
+
request: (_payload, _mockResponse, id) => of(NetworkingUIEventWrapped.succeeded(response)),
|
|
21
|
+
});
|
|
22
|
+
const result = await service.get('1').toPromise();
|
|
23
|
+
expect(result?.hasSuccess).toBe(true);
|
|
24
|
+
expect(result?.response).toEqual(response);
|
|
25
|
+
});
|
|
26
|
+
it('get error', async () => {
|
|
27
|
+
jest.spyOn(service, 'provider').mockReturnValue({
|
|
28
|
+
request: (_payload, _mockResponse, id) => of(NetworkingUIEventWrapped.failed(AlertModel.default())),
|
|
29
|
+
});
|
|
30
|
+
const result = await service.get('1').toPromise();
|
|
31
|
+
expect(result?.hasFailed).toBe(true);
|
|
32
|
+
expect(result?.alertModel).toBeInstanceOf(AlertModel);
|
|
33
|
+
});
|
|
34
|
+
it('list success', async () => {
|
|
35
|
+
const response = { data: [{ id: '1', name: 'Store' }] };
|
|
36
|
+
jest.spyOn(service, 'provider').mockReturnValue({
|
|
37
|
+
request: () => of(NetworkingUIEventWrapped.succeeded(response)),
|
|
38
|
+
});
|
|
39
|
+
const result = await service.list().toPromise();
|
|
40
|
+
expect(result?.hasSuccess).toBe(true);
|
|
41
|
+
expect(result?.response).toEqual(response);
|
|
42
|
+
});
|
|
43
|
+
it('list error', async () => {
|
|
44
|
+
jest.spyOn(service, 'provider').mockReturnValue({
|
|
45
|
+
request: () => of(NetworkingUIEventWrapped.failed(AlertModel.default())),
|
|
46
|
+
});
|
|
47
|
+
const result = await service.list().toPromise();
|
|
48
|
+
expect(result?.hasFailed).toBe(true);
|
|
49
|
+
expect(result?.alertModel).toBeInstanceOf(AlertModel);
|
|
50
|
+
});
|
|
51
|
+
it('productCategoryList success', async () => {
|
|
52
|
+
const response = { data: [{ id: 'cat1', name: 'Category' }] };
|
|
53
|
+
jest.spyOn(service, 'provider').mockReturnValue({
|
|
54
|
+
request: () => of(NetworkingUIEventWrapped.succeeded(response)),
|
|
55
|
+
});
|
|
56
|
+
const result = await service.productCategoryList().toPromise();
|
|
57
|
+
expect(result?.hasSuccess).toBe(true);
|
|
58
|
+
expect(result?.response).toEqual(response);
|
|
59
|
+
});
|
|
60
|
+
it('productCategoryList error', async () => {
|
|
61
|
+
jest.spyOn(service, 'provider').mockReturnValue({
|
|
62
|
+
request: () => of(NetworkingUIEventWrapped.failed(AlertModel.default())),
|
|
63
|
+
});
|
|
64
|
+
const result = await service.productCategoryList().toPromise();
|
|
65
|
+
expect(result?.hasFailed).toBe(true);
|
|
66
|
+
expect(result?.alertModel).toBeInstanceOf(AlertModel);
|
|
67
|
+
});
|
|
68
|
+
it('productCollection success', async () => {
|
|
69
|
+
const response = { data: [{ id: 'prod1', name: 'Product' }] };
|
|
70
|
+
const payload = { page: 1, per_page: 10 };
|
|
71
|
+
jest.spyOn(service, 'provider').mockReturnValue({
|
|
72
|
+
request: (payload, _mockResponse, id) => of(NetworkingUIEventWrapped.succeeded(response)),
|
|
73
|
+
});
|
|
74
|
+
const result = await service.productCollection('1', payload).toPromise();
|
|
75
|
+
expect(result?.hasSuccess).toBe(true);
|
|
76
|
+
expect(result?.response).toEqual(response);
|
|
77
|
+
});
|
|
78
|
+
it('productCollection error', async () => {
|
|
79
|
+
const payload = { page: 1, per_page: 10 };
|
|
80
|
+
jest.spyOn(service, 'provider').mockReturnValue({
|
|
81
|
+
request: (payload, _mockResponse, id) => of(NetworkingUIEventWrapped.failed(AlertModel.default())),
|
|
82
|
+
});
|
|
83
|
+
const result = await service.productCollection('1', payload).toPromise();
|
|
84
|
+
expect(result?.hasFailed).toBe(true);
|
|
85
|
+
expect(result?.alertModel).toBeInstanceOf(AlertModel);
|
|
86
|
+
});
|
|
87
|
+
it('featuredProductList success', async () => {
|
|
88
|
+
const response = { data: [{ id: 'feat1', name: 'Featured' }] };
|
|
89
|
+
jest.spyOn(service, 'provider').mockReturnValue({
|
|
90
|
+
request: (_payload, _mockResponse, storeId) => of(NetworkingUIEventWrapped.succeeded(response)),
|
|
91
|
+
});
|
|
92
|
+
const result = await service.featuredProductList('1').toPromise();
|
|
93
|
+
expect(result?.hasSuccess).toBe(true);
|
|
94
|
+
expect(result?.response).toEqual(response);
|
|
95
|
+
});
|
|
96
|
+
it('featuredProductList error', async () => {
|
|
97
|
+
jest.spyOn(service, 'provider').mockReturnValue({
|
|
98
|
+
request: (_payload, _mockResponse, storeId) => of(NetworkingUIEventWrapped.failed(AlertModel.default())),
|
|
99
|
+
});
|
|
100
|
+
const result = await service.featuredProductList('1').toPromise();
|
|
101
|
+
expect(result?.hasFailed).toBe(true);
|
|
102
|
+
expect(result?.alertModel).toBeInstanceOf(AlertModel);
|
|
103
|
+
});
|
|
104
|
+
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { BaseProvider } from '../core/base.provider';
|
|
2
|
-
import { BaseServiceWrapper } from '../core/base.service.wrapper';
|
|
3
|
-
import { NetworkingConfig } from '../types/types';
|
|
1
|
+
import { BaseProvider } from '../core/base.provider.js';
|
|
2
|
+
import { BaseServiceWrapper } from '../core/base.service.wrapper.js';
|
|
3
|
+
import { NetworkingConfig } from '../types/types.js';
|
|
4
4
|
export interface User {
|
|
5
5
|
id: number;
|
|
6
6
|
name: string;
|
|
@@ -11,6 +11,6 @@ export declare class UserProvider extends BaseProvider {
|
|
|
11
11
|
}
|
|
12
12
|
export declare class UserService extends BaseServiceWrapper<UserProvider> {
|
|
13
13
|
constructor(config: NetworkingConfig, userId?: number);
|
|
14
|
-
fetchUserById(id: number): import("rxjs").Observable<import("../types/types").NetworkingUIEventWrapped<User>>;
|
|
15
|
-
fetchAllUsers(): import("rxjs").Observable<import("../types/types").NetworkingUIEventWrapped<User[]>>;
|
|
14
|
+
fetchUserById(id: number): import("rxjs").Observable<import("../types/types.js").NetworkingUIEventWrapped<User>>;
|
|
15
|
+
fetchAllUsers(): import("rxjs").Observable<import("../types/types.js").NetworkingUIEventWrapped<User[]>>;
|
|
16
16
|
}
|
|
@@ -1,10 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
exports.UserService = exports.UserProvider = void 0;
|
|
4
|
-
const base_provider_1 = require("../core/base.provider");
|
|
5
|
-
const base_service_wrapper_1 = require("../core/base.service.wrapper");
|
|
1
|
+
import { BaseProvider } from '../core/base.provider.js';
|
|
2
|
+
import { BaseServiceWrapper } from '../core/base.service.wrapper.js';
|
|
6
3
|
// UserProvider implements ProviderType for user endpoints
|
|
7
|
-
class UserProvider extends
|
|
4
|
+
export class UserProvider extends BaseProvider {
|
|
8
5
|
constructor(config, userId) {
|
|
9
6
|
super({
|
|
10
7
|
config,
|
|
@@ -15,9 +12,8 @@ class UserProvider extends base_provider_1.BaseProvider {
|
|
|
15
12
|
});
|
|
16
13
|
}
|
|
17
14
|
}
|
|
18
|
-
exports.UserProvider = UserProvider;
|
|
19
15
|
// UserService provides high-level methods for user API
|
|
20
|
-
class UserService extends
|
|
16
|
+
export class UserService extends BaseServiceWrapper {
|
|
21
17
|
constructor(config, userId) {
|
|
22
18
|
super(new UserProvider(config, userId));
|
|
23
19
|
}
|
|
@@ -32,7 +28,6 @@ class UserService extends base_service_wrapper_1.BaseServiceWrapper {
|
|
|
32
28
|
return this.request();
|
|
33
29
|
}
|
|
34
30
|
}
|
|
35
|
-
exports.UserService = UserService;
|
|
36
31
|
// Example usage:
|
|
37
32
|
// setNetworkingConfig({ baseUrl: 'https://jsonplaceholder.typicode.com', isProd: false });
|
|
38
33
|
// const userService = new UserService();
|
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const rxjs_1 = require("rxjs");
|
|
6
|
-
const base_service_wrapper_1 = require("../core/base.service.wrapper");
|
|
1
|
+
import { UserService } from './user.service.js';
|
|
2
|
+
import { NetworkingUIEventWrapped } from '../types/types.js';
|
|
3
|
+
import { of, throwError } from 'rxjs';
|
|
4
|
+
import { BaseServiceWrapper } from '../core/base.service.wrapper.js';
|
|
7
5
|
describe('UserService', () => {
|
|
8
6
|
const config = {
|
|
9
7
|
baseUrl: 'https://jsonplaceholder.typicode.com',
|
|
@@ -14,30 +12,31 @@ describe('UserService', () => {
|
|
|
14
12
|
const user = { id: 1, name: 'Test', email: 'test@example.com' };
|
|
15
13
|
let requestSpy;
|
|
16
14
|
beforeEach(() => {
|
|
17
|
-
requestSpy = jest.spyOn(
|
|
15
|
+
requestSpy = jest.spyOn(BaseServiceWrapper.prototype, 'request').mockImplementation(() => of(NetworkingUIEventWrapped.succeeded(user)));
|
|
18
16
|
});
|
|
19
17
|
afterEach(() => {
|
|
20
18
|
requestSpy.mockRestore();
|
|
21
19
|
});
|
|
22
|
-
it('fetchUserById should return user (success)', done => {
|
|
23
|
-
const service = new
|
|
24
|
-
service.fetchUserById(1).subscribe(result => {
|
|
20
|
+
it('fetchUserById should return user (success)', (done) => {
|
|
21
|
+
const service = new UserService(config);
|
|
22
|
+
service.fetchUserById(1).subscribe((result) => {
|
|
25
23
|
expect(result.response).toEqual(user);
|
|
26
24
|
done();
|
|
27
25
|
});
|
|
28
26
|
});
|
|
29
|
-
it('fetchAllUsers should return users (success)', done => {
|
|
30
|
-
const service = new
|
|
31
|
-
service.fetchAllUsers().subscribe(result => {
|
|
27
|
+
it('fetchAllUsers should return users (success)', (done) => {
|
|
28
|
+
const service = new UserService(config);
|
|
29
|
+
service.fetchAllUsers().subscribe((result) => {
|
|
32
30
|
expect(result.response).toEqual(user);
|
|
33
31
|
done();
|
|
34
32
|
});
|
|
35
33
|
});
|
|
36
|
-
it('request should handle error', done => {
|
|
37
|
-
requestSpy.mockImplementationOnce(() =>
|
|
38
|
-
const service = new
|
|
39
|
-
|
|
40
|
-
|
|
34
|
+
it('request should handle error', (done) => {
|
|
35
|
+
requestSpy.mockImplementationOnce(() => throwError(() => new Error('Test error')));
|
|
36
|
+
const service = new UserService(config);
|
|
37
|
+
// Simulate error by calling a method that uses request
|
|
38
|
+
service.fetchUserById(1).subscribe({
|
|
39
|
+
error: (err) => {
|
|
41
40
|
expect(err).toBeInstanceOf(Error);
|
|
42
41
|
expect(err.message).toBe('Test error');
|
|
43
42
|
done();
|
|
@@ -63,9 +63,6 @@ export interface ProviderType {
|
|
|
63
63
|
headers: Record<string, string | undefined>;
|
|
64
64
|
getPath(...queryParams: unknown[]): string;
|
|
65
65
|
}
|
|
66
|
-
export interface ProviderTypeMockable {
|
|
67
|
-
shouldUseMockData: boolean;
|
|
68
|
-
}
|
|
69
66
|
export interface HeaderType {
|
|
70
67
|
shouldAddEncryptionHeader?: boolean;
|
|
71
68
|
shouldAddClientIdHeader?: boolean;
|
|
@@ -88,6 +85,7 @@ export interface ServerErrorResponse {
|
|
|
88
85
|
}
|
|
89
86
|
export interface NetworkingConfig {
|
|
90
87
|
baseUrl: string;
|
|
88
|
+
version?: string;
|
|
91
89
|
isProd: boolean;
|
|
92
90
|
clientId?: string;
|
|
93
91
|
apiKey?: string;
|