@congminh1254/shopee-sdk 1.6.2 → 1.8.0
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/README.md +9 -3
- package/lib/__tests__/errors.test.d.ts +1 -0
- package/lib/__tests__/errors.test.js +49 -0
- package/lib/__tests__/errors.test.js.map +1 -0
- package/lib/__tests__/fetch.test.d.ts +1 -0
- package/lib/__tests__/fetch.test.js +494 -0
- package/lib/__tests__/fetch.test.js.map +1 -0
- package/lib/__tests__/integration.test.d.ts +1 -0
- package/lib/__tests__/integration.test.js +201 -0
- package/lib/__tests__/integration.test.js.map +1 -0
- package/lib/__tests__/managers/account-health.manager.test.d.ts +1 -0
- package/lib/__tests__/managers/account-health.manager.test.js +446 -0
- package/lib/__tests__/managers/account-health.manager.test.js.map +1 -0
- package/lib/__tests__/managers/add-on-deal.manager.test.d.ts +1 -0
- package/lib/__tests__/managers/add-on-deal.manager.test.js +636 -0
- package/lib/__tests__/managers/add-on-deal.manager.test.js.map +1 -0
- package/lib/__tests__/managers/ads.manager.test.d.ts +1 -0
- package/lib/__tests__/managers/ads.manager.test.js +1016 -0
- package/lib/__tests__/managers/ads.manager.test.js.map +1 -0
- package/lib/__tests__/managers/ams.manager.test.d.ts +1 -0
- package/lib/__tests__/managers/ams.manager.test.js +1170 -0
- package/lib/__tests__/managers/ams.manager.test.js.map +1 -0
- package/lib/__tests__/managers/auth.manager.test.d.ts +1 -0
- package/lib/__tests__/managers/auth.manager.test.js +193 -0
- package/lib/__tests__/managers/auth.manager.test.js.map +1 -0
- package/lib/__tests__/managers/bundle-deal.manager.test.d.ts +1 -0
- package/lib/__tests__/managers/bundle-deal.manager.test.js +465 -0
- package/lib/__tests__/managers/bundle-deal.manager.test.js.map +1 -0
- package/lib/__tests__/managers/discount.manager.test.d.ts +1 -0
- package/lib/__tests__/managers/discount.manager.test.js +615 -0
- package/lib/__tests__/managers/discount.manager.test.js.map +1 -0
- package/lib/__tests__/managers/fbs.manager.test.d.ts +1 -0
- package/lib/__tests__/managers/fbs.manager.test.js +349 -0
- package/lib/__tests__/managers/fbs.manager.test.js.map +1 -0
- package/lib/__tests__/managers/first-mile.manager.test.d.ts +1 -0
- package/lib/__tests__/managers/first-mile.manager.test.js +629 -0
- package/lib/__tests__/managers/first-mile.manager.test.js.map +1 -0
- package/lib/__tests__/managers/follow-prize.manager.test.d.ts +1 -0
- package/lib/__tests__/managers/follow-prize.manager.test.js +408 -0
- package/lib/__tests__/managers/follow-prize.manager.test.js.map +1 -0
- package/lib/__tests__/managers/global-product.manager.test.d.ts +1 -0
- package/lib/__tests__/managers/global-product.manager.test.js +1253 -0
- package/lib/__tests__/managers/global-product.manager.test.js.map +1 -0
- package/lib/__tests__/managers/livestream.manager.test.d.ts +1 -0
- package/lib/__tests__/managers/livestream.manager.test.js +877 -0
- package/lib/__tests__/managers/livestream.manager.test.js.map +1 -0
- package/lib/__tests__/managers/logistics.manager.test.d.ts +1 -0
- package/lib/__tests__/managers/logistics.manager.test.js +1125 -0
- package/lib/__tests__/managers/logistics.manager.test.js.map +1 -0
- package/lib/__tests__/managers/media-space.manager.test.d.ts +1 -0
- package/lib/__tests__/managers/media-space.manager.test.js +556 -0
- package/lib/__tests__/managers/media-space.manager.test.js.map +1 -0
- package/lib/__tests__/managers/media.manager.test.d.ts +1 -0
- package/lib/__tests__/managers/media.manager.test.js +681 -0
- package/lib/__tests__/managers/media.manager.test.js.map +1 -0
- package/lib/__tests__/managers/merchant.manager.test.d.ts +1 -0
- package/lib/__tests__/managers/merchant.manager.test.js +328 -0
- package/lib/__tests__/managers/merchant.manager.test.js.map +1 -0
- package/lib/__tests__/managers/order.manager.test.d.ts +1 -0
- package/lib/__tests__/managers/order.manager.test.js +937 -0
- package/lib/__tests__/managers/order.manager.test.js.map +1 -0
- package/lib/__tests__/managers/payment.manager.test.d.ts +1 -0
- package/lib/__tests__/managers/payment.manager.test.js +1167 -0
- package/lib/__tests__/managers/payment.manager.test.js.map +1 -0
- package/lib/__tests__/managers/product.manager.test.d.ts +1 -0
- package/lib/__tests__/managers/product.manager.test.js +2247 -0
- package/lib/__tests__/managers/product.manager.test.js.map +1 -0
- package/lib/__tests__/managers/public.manager.test.d.ts +1 -0
- package/lib/__tests__/managers/public.manager.test.js +209 -0
- package/lib/__tests__/managers/public.manager.test.js.map +1 -0
- package/lib/__tests__/managers/push.manager.test.d.ts +1 -0
- package/lib/__tests__/managers/push.manager.test.js +244 -0
- package/lib/__tests__/managers/push.manager.test.js.map +1 -0
- package/lib/__tests__/managers/returns.manager.test.d.ts +1 -0
- package/lib/__tests__/managers/returns.manager.test.js +783 -0
- package/lib/__tests__/managers/returns.manager.test.js.map +1 -0
- package/lib/__tests__/managers/sbs.manager.test.d.ts +1 -0
- package/lib/__tests__/managers/sbs.manager.test.js +492 -0
- package/lib/__tests__/managers/sbs.manager.test.js.map +1 -0
- package/lib/__tests__/managers/shop-category.manager.test.d.ts +1 -0
- package/lib/__tests__/managers/shop-category.manager.test.js +425 -0
- package/lib/__tests__/managers/shop-category.manager.test.js.map +1 -0
- package/lib/__tests__/managers/shop-flash-sale.manager.test.d.ts +1 -0
- package/lib/__tests__/managers/shop-flash-sale.manager.test.js +492 -0
- package/lib/__tests__/managers/shop-flash-sale.manager.test.js.map +1 -0
- package/lib/__tests__/managers/shop.manager.test.d.ts +1 -0
- package/lib/__tests__/managers/shop.manager.test.js +637 -0
- package/lib/__tests__/managers/shop.manager.test.js.map +1 -0
- package/lib/__tests__/managers/top-picks.manager.test.d.ts +1 -0
- package/lib/__tests__/managers/top-picks.manager.test.js +324 -0
- package/lib/__tests__/managers/top-picks.manager.test.js.map +1 -0
- package/lib/__tests__/managers/video.manager.test.d.ts +1 -0
- package/lib/__tests__/managers/video.manager.test.js +1039 -0
- package/lib/__tests__/managers/video.manager.test.js.map +1 -0
- package/lib/__tests__/managers/voucher.manager.test.d.ts +1 -0
- package/lib/__tests__/managers/voucher.manager.test.js +442 -0
- package/lib/__tests__/managers/voucher.manager.test.js.map +1 -0
- package/lib/__tests__/sdk.test.d.ts +1 -0
- package/lib/__tests__/sdk.test.js +316 -0
- package/lib/__tests__/sdk.test.js.map +1 -0
- package/lib/__tests__/storage/custom-token-storage.test.d.ts +1 -0
- package/lib/__tests__/storage/custom-token-storage.test.js +337 -0
- package/lib/__tests__/storage/custom-token-storage.test.js.map +1 -0
- package/lib/__tests__/utils/signature.test.d.ts +1 -0
- package/lib/__tests__/utils/signature.test.js +38 -0
- package/lib/__tests__/utils/signature.test.js.map +1 -0
- package/lib/__tests__/utils/spec-audit.test.d.ts +1 -0
- package/lib/__tests__/utils/spec-audit.test.js +176 -0
- package/lib/__tests__/utils/spec-audit.test.js.map +1 -0
- package/lib/errors.js +2 -0
- package/lib/errors.js.map +1 -1
- package/lib/fetch.js +1 -1
- package/lib/fetch.js.map +1 -1
- package/lib/managers/ads.manager.d.ts +1 -41
- package/lib/managers/ads.manager.js +0 -54
- package/lib/managers/ads.manager.js.map +1 -1
- package/lib/managers/auth.manager.d.ts +2 -1
- package/lib/managers/auth.manager.js +2 -5
- package/lib/managers/auth.manager.js.map +1 -1
- package/lib/managers/base.manager.js +1 -0
- package/lib/managers/base.manager.js.map +1 -1
- package/lib/managers/media.manager.d.ts +36 -1
- package/lib/managers/media.manager.js +68 -0
- package/lib/managers/media.manager.js.map +1 -1
- package/lib/managers/order.manager.js +1 -0
- package/lib/managers/order.manager.js.map +1 -1
- package/lib/managers/payment.manager.d.ts +13 -1
- package/lib/managers/payment.manager.js +26 -0
- package/lib/managers/payment.manager.js.map +1 -1
- package/lib/managers/product.manager.js +1 -1
- package/lib/managers/product.manager.js.map +1 -1
- package/lib/schemas/ads.d.ts +2 -56
- package/lib/schemas/ams.d.ts +92 -0
- package/lib/schemas/base.d.ts +2 -0
- package/lib/schemas/discount.d.ts +4 -0
- package/lib/schemas/fetch.d.ts +1 -1
- package/lib/schemas/livestream.d.ts +14 -0
- package/lib/schemas/media.d.ts +107 -0
- package/lib/schemas/merchant.d.ts +2 -0
- package/lib/schemas/order.d.ts +22 -0
- package/lib/schemas/payment.d.ts +96 -0
- package/lib/schemas/product.d.ts +253 -15
- package/lib/schemas/public.d.ts +3 -0
- package/lib/schemas/region.d.ts +9 -2
- package/lib/schemas/region.js +9 -2
- package/lib/schemas/region.js.map +1 -1
- package/lib/schemas/returns.d.ts +38 -1
- package/lib/schemas/shop.d.ts +16 -0
- package/lib/schemas/video.d.ts +83 -37
- package/lib/schemas/voucher.d.ts +2 -0
- package/lib/sdk.d.ts +6 -1
- package/lib/sdk.js +53 -6
- package/lib/sdk.js.map +1 -1
- package/lib/storage/custom-token-storage.js +2 -0
- package/lib/storage/custom-token-storage.js.map +1 -1
- package/lib/version.d.ts +1 -1
- package/lib/version.js +1 -1
- package/package.json +3 -3
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
import { ShopeeSDK } from "../sdk.js";
|
|
2
|
+
import { ShopeeRegion } from "../schemas/region.js";
|
|
3
|
+
import { ShopeeSdkError } from "../errors.js";
|
|
4
|
+
import { jest } from "@jest/globals";
|
|
5
|
+
import { Agent } from "node:http";
|
|
6
|
+
// Mock the managers
|
|
7
|
+
jest.mock("../managers/auth.manager.js");
|
|
8
|
+
jest.mock("../managers/product.manager.js");
|
|
9
|
+
jest.mock("../managers/order.manager.js");
|
|
10
|
+
jest.mock("../managers/public.manager.js");
|
|
11
|
+
jest.mock("../managers/push.manager.js");
|
|
12
|
+
jest.mock("../storage/custom-token-storage.js");
|
|
13
|
+
describe("ShopeeSDK", () => {
|
|
14
|
+
let sdk;
|
|
15
|
+
const mockConfig = {
|
|
16
|
+
partner_id: 12345,
|
|
17
|
+
partner_key: "test_key",
|
|
18
|
+
shop_id: 67890,
|
|
19
|
+
};
|
|
20
|
+
beforeEach(() => {
|
|
21
|
+
sdk = new ShopeeSDK(mockConfig);
|
|
22
|
+
});
|
|
23
|
+
describe("initialization", () => {
|
|
24
|
+
it("should initialize with default configuration", () => {
|
|
25
|
+
expect(sdk).toBeDefined();
|
|
26
|
+
expect(sdk.auth).toBeDefined();
|
|
27
|
+
expect(sdk.product).toBeDefined();
|
|
28
|
+
expect(sdk.order).toBeDefined();
|
|
29
|
+
expect(sdk.public).toBeDefined();
|
|
30
|
+
expect(sdk.push).toBeDefined();
|
|
31
|
+
});
|
|
32
|
+
it("should initialize with custom region", () => {
|
|
33
|
+
const customSdk = new ShopeeSDK({
|
|
34
|
+
...mockConfig,
|
|
35
|
+
region: ShopeeRegion.CHINA,
|
|
36
|
+
});
|
|
37
|
+
const config = customSdk.getConfig();
|
|
38
|
+
expect(config.region).toBe(ShopeeRegion.CHINA);
|
|
39
|
+
});
|
|
40
|
+
it("should initialize with custom base URL", () => {
|
|
41
|
+
const customUrl = "https://custom.shopee.com/api/v2";
|
|
42
|
+
const customSdk = new ShopeeSDK({
|
|
43
|
+
...mockConfig,
|
|
44
|
+
base_url: customUrl,
|
|
45
|
+
});
|
|
46
|
+
const config = customSdk.getConfig();
|
|
47
|
+
expect(config.base_url).toBe(customUrl);
|
|
48
|
+
});
|
|
49
|
+
it("should initialize with custom token storage", () => {
|
|
50
|
+
const mockTokenStorage = {
|
|
51
|
+
store: jest.fn(),
|
|
52
|
+
get: jest.fn(),
|
|
53
|
+
clear: jest.fn(),
|
|
54
|
+
};
|
|
55
|
+
const customSdk = new ShopeeSDK(mockConfig, mockTokenStorage);
|
|
56
|
+
expect(customSdk).toBeDefined();
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
describe("configuration", () => {
|
|
60
|
+
it("should get current configuration", () => {
|
|
61
|
+
const config = sdk.getConfig();
|
|
62
|
+
expect(config.partner_id).toBe(mockConfig.partner_id);
|
|
63
|
+
expect(config.partner_key).toBe(mockConfig.partner_key);
|
|
64
|
+
expect(config.shop_id).toBe(mockConfig.shop_id);
|
|
65
|
+
});
|
|
66
|
+
it("should set region and update base URL", () => {
|
|
67
|
+
sdk.setRegion(ShopeeRegion.CHINA);
|
|
68
|
+
const config = sdk.getConfig();
|
|
69
|
+
expect(config.region).toBe(ShopeeRegion.CHINA);
|
|
70
|
+
expect(config.base_url).toBeDefined();
|
|
71
|
+
});
|
|
72
|
+
it("should set custom base URL and clear region", () => {
|
|
73
|
+
const customUrl = "https://custom.shopee.com/api/v2";
|
|
74
|
+
sdk.setBaseUrl(customUrl);
|
|
75
|
+
const config = sdk.getConfig();
|
|
76
|
+
expect(config.base_url).toBe(customUrl);
|
|
77
|
+
expect(config.region).toBeUndefined();
|
|
78
|
+
});
|
|
79
|
+
it("should set custom base auth URL and clear region", () => {
|
|
80
|
+
const customAuthUrl = "https://custom.shopee.com/auth";
|
|
81
|
+
sdk.setBaseAuthUrl(customAuthUrl);
|
|
82
|
+
const config = sdk.getConfig();
|
|
83
|
+
expect(config.base_auth_url).toBe(customAuthUrl);
|
|
84
|
+
expect(config.region).toBeUndefined();
|
|
85
|
+
});
|
|
86
|
+
it("should set fetch agent", () => {
|
|
87
|
+
const mockAgent = new Agent();
|
|
88
|
+
sdk.setFetchAgent(mockAgent);
|
|
89
|
+
const config = sdk.getConfig();
|
|
90
|
+
expect(config.agent).toBe(mockAgent);
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
describe("authorization", () => {
|
|
94
|
+
it("should generate authorization URL with correct parameters", () => {
|
|
95
|
+
const redirectUri = "https://example.com/callback";
|
|
96
|
+
const url = sdk.getAuthorizationUrl(redirectUri, { state: "csrf_state" });
|
|
97
|
+
expect(url).toContain("https://open.shopee.com/auth");
|
|
98
|
+
expect(url).toContain("partner_id=12345");
|
|
99
|
+
expect(url).toContain("auth_type=seller");
|
|
100
|
+
expect(url).toContain("redirect_uri=" + encodeURIComponent(redirectUri));
|
|
101
|
+
expect(url).toContain("response_type=code");
|
|
102
|
+
expect(url).toContain("state=csrf_state");
|
|
103
|
+
});
|
|
104
|
+
it("should generate sandbox authorization URL when sandbox region is used", () => {
|
|
105
|
+
const sandboxSdk = new ShopeeSDK({
|
|
106
|
+
...mockConfig,
|
|
107
|
+
region: ShopeeRegion.TEST_GLOBAL,
|
|
108
|
+
});
|
|
109
|
+
const redirectUri = "http://local.host";
|
|
110
|
+
const url = sandboxSdk.getAuthorizationUrl(redirectUri, { auth_type: "supplier" });
|
|
111
|
+
expect(url).toContain("https://open.sandbox.test-stable.shopee.com/auth");
|
|
112
|
+
expect(url).toContain("partner_id=12345");
|
|
113
|
+
expect(url).toContain("auth_type=supplier");
|
|
114
|
+
expect(url).toContain("redirect_uri=" + encodeURIComponent(redirectUri));
|
|
115
|
+
expect(url).toContain("response_type=code");
|
|
116
|
+
});
|
|
117
|
+
it("should generate correct authorization URLs for all ShopeeRegion values", () => {
|
|
118
|
+
const testCases = [
|
|
119
|
+
{ region: ShopeeRegion.GLOBAL, expected: "https://open.shopee.com/auth" },
|
|
120
|
+
{ region: ShopeeRegion.CHINA, expected: "https://open.shopee.cn/auth" },
|
|
121
|
+
{ region: ShopeeRegion.BRAZIL, expected: "https://open.shopee.com.br/auth" },
|
|
122
|
+
{
|
|
123
|
+
region: ShopeeRegion.TEST_GLOBAL,
|
|
124
|
+
expected: "https://open.sandbox.test-stable.shopee.com/auth",
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
region: ShopeeRegion.TEST_CHINA,
|
|
128
|
+
expected: "https://open.sandbox.test-stable.shopee.cn/auth",
|
|
129
|
+
},
|
|
130
|
+
];
|
|
131
|
+
for (const { region, expected } of testCases) {
|
|
132
|
+
const regionalSdk = new ShopeeSDK({
|
|
133
|
+
...mockConfig,
|
|
134
|
+
region,
|
|
135
|
+
});
|
|
136
|
+
const url = regionalSdk.getAuthorizationUrl("http://local.host");
|
|
137
|
+
expect(url).toContain(expected);
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
it("should generate correct URLs based on custom base_url configuration when region is undefined", () => {
|
|
141
|
+
const testCases = [
|
|
142
|
+
{
|
|
143
|
+
base_url: "https://openplatform.test-stable.shopee.cn/api/v2",
|
|
144
|
+
base_auth_url: "https://open.sandbox.test-stable.shopee.cn/auth",
|
|
145
|
+
expected: "https://open.sandbox.test-stable.shopee.cn/auth",
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
base_url: "https://openplatform.test-stable.shopee.com.br/api/v2",
|
|
149
|
+
base_auth_url: "https://open.sandbox.test-stable.shopee.com.br/auth",
|
|
150
|
+
expected: "https://open.sandbox.test-stable.shopee.com.br/auth",
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
base_url: "https://partner.test-stable.shopeemobile.com/api/v2",
|
|
154
|
+
base_auth_url: "https://open.sandbox.test-stable.shopee.com/auth",
|
|
155
|
+
expected: "https://open.sandbox.test-stable.shopee.com/auth",
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
base_url: "https://openplatform.shopee.cn/api/v2",
|
|
159
|
+
base_auth_url: "https://open.shopee.cn/auth",
|
|
160
|
+
expected: "https://open.shopee.cn/auth",
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
base_url: "https://openplatform.shopee.com.br/api/v2",
|
|
164
|
+
base_auth_url: "https://open.shopee.com.br/auth",
|
|
165
|
+
expected: "https://open.shopee.com.br/auth",
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
base_url: "https://partner.shopeemobile.com/api/v2",
|
|
169
|
+
base_auth_url: "https://open.shopee.com/auth",
|
|
170
|
+
expected: "https://open.shopee.com/auth",
|
|
171
|
+
},
|
|
172
|
+
];
|
|
173
|
+
for (const { base_url, base_auth_url, expected } of testCases) {
|
|
174
|
+
const customSdk = new ShopeeSDK({
|
|
175
|
+
partner_id: mockConfig.partner_id,
|
|
176
|
+
partner_key: mockConfig.partner_key,
|
|
177
|
+
base_url,
|
|
178
|
+
base_auth_url,
|
|
179
|
+
});
|
|
180
|
+
const url = customSdk.getAuthorizationUrl("http://local.host");
|
|
181
|
+
expect(url).toContain(expected);
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
it("should generate different URLs for different redirect URIs", () => {
|
|
185
|
+
const url1 = sdk.getAuthorizationUrl("https://example1.com/callback");
|
|
186
|
+
const url2 = sdk.getAuthorizationUrl("https://example2.com/callback");
|
|
187
|
+
expect(url1).not.toBe(url2);
|
|
188
|
+
});
|
|
189
|
+
});
|
|
190
|
+
describe("authentication", () => {
|
|
191
|
+
it("should authenticate with code and store token", async () => {
|
|
192
|
+
const mockToken = {
|
|
193
|
+
access_token: "test_token",
|
|
194
|
+
refresh_token: "test_refresh_token",
|
|
195
|
+
expire_in: 3600,
|
|
196
|
+
request_id: "test_request_id",
|
|
197
|
+
error: "",
|
|
198
|
+
message: "",
|
|
199
|
+
};
|
|
200
|
+
// Mock auth manager's getAccessToken
|
|
201
|
+
const mockGetAccessToken = jest.fn();
|
|
202
|
+
mockGetAccessToken.mockResolvedValue(mockToken);
|
|
203
|
+
const mockAuthManager = sdk.auth;
|
|
204
|
+
mockAuthManager.getAccessToken = mockGetAccessToken;
|
|
205
|
+
// Mock token storage
|
|
206
|
+
const mockStore = jest.fn();
|
|
207
|
+
const mockTokenStorage = {
|
|
208
|
+
store: mockStore,
|
|
209
|
+
get: jest.fn(),
|
|
210
|
+
clear: jest.fn(),
|
|
211
|
+
};
|
|
212
|
+
sdk["tokenStorage"] = mockTokenStorage;
|
|
213
|
+
const token = await sdk.authenticateWithCode("test_code");
|
|
214
|
+
expect(mockGetAccessToken).toHaveBeenCalledWith("test_code", undefined, undefined);
|
|
215
|
+
expect(mockStore).toHaveBeenCalledWith(mockToken);
|
|
216
|
+
expect(token).toEqual(mockToken);
|
|
217
|
+
});
|
|
218
|
+
it("should get stored token", async () => {
|
|
219
|
+
const mockToken = {
|
|
220
|
+
access_token: "test_token",
|
|
221
|
+
refresh_token: "test_refresh_token",
|
|
222
|
+
expire_in: 3600,
|
|
223
|
+
request_id: "test_request_id",
|
|
224
|
+
error: "",
|
|
225
|
+
message: "",
|
|
226
|
+
};
|
|
227
|
+
// Mock token storage
|
|
228
|
+
const mockGet = jest.fn();
|
|
229
|
+
mockGet.mockResolvedValue(mockToken);
|
|
230
|
+
const mockTokenStorage = {
|
|
231
|
+
store: jest.fn(),
|
|
232
|
+
get: mockGet,
|
|
233
|
+
clear: jest.fn(),
|
|
234
|
+
};
|
|
235
|
+
sdk["tokenStorage"] = mockTokenStorage;
|
|
236
|
+
const token = await sdk.getAuthToken();
|
|
237
|
+
expect(token).toEqual(mockToken);
|
|
238
|
+
});
|
|
239
|
+
it("should refresh token", async () => {
|
|
240
|
+
const oldToken = {
|
|
241
|
+
access_token: "old_token",
|
|
242
|
+
refresh_token: "test_refresh_token",
|
|
243
|
+
expire_in: 3600,
|
|
244
|
+
request_id: "test_request_id",
|
|
245
|
+
error: "",
|
|
246
|
+
message: "",
|
|
247
|
+
};
|
|
248
|
+
const newToken = {
|
|
249
|
+
access_token: "new_token",
|
|
250
|
+
refresh_token: "new_refresh_token",
|
|
251
|
+
expire_in: 3600,
|
|
252
|
+
request_id: "test_request_id",
|
|
253
|
+
error: "",
|
|
254
|
+
message: "",
|
|
255
|
+
};
|
|
256
|
+
// Mock token storage
|
|
257
|
+
const mockGet = jest.fn();
|
|
258
|
+
mockGet.mockResolvedValue(oldToken);
|
|
259
|
+
const mockStore = jest.fn();
|
|
260
|
+
const mockTokenStorage = {
|
|
261
|
+
store: mockStore,
|
|
262
|
+
get: mockGet,
|
|
263
|
+
clear: jest.fn(),
|
|
264
|
+
};
|
|
265
|
+
sdk["tokenStorage"] = mockTokenStorage;
|
|
266
|
+
// Mock auth manager's getRefreshToken
|
|
267
|
+
const mockGetRefreshToken = jest.fn();
|
|
268
|
+
mockGetRefreshToken.mockResolvedValue(newToken);
|
|
269
|
+
const mockAuthManager = sdk.auth;
|
|
270
|
+
mockAuthManager.getRefreshToken = mockGetRefreshToken;
|
|
271
|
+
const token = await sdk.refreshToken();
|
|
272
|
+
expect(mockGetRefreshToken).toHaveBeenCalledWith("test_refresh_token", undefined, undefined);
|
|
273
|
+
expect(mockStore).toHaveBeenCalledWith(newToken);
|
|
274
|
+
expect(token).toEqual(newToken);
|
|
275
|
+
});
|
|
276
|
+
it("should throw error when refreshing without stored token", async () => {
|
|
277
|
+
// Mock token storage to return null
|
|
278
|
+
const mockGet = jest.fn();
|
|
279
|
+
mockGet.mockResolvedValue(null);
|
|
280
|
+
const mockTokenStorage = {
|
|
281
|
+
store: jest.fn(),
|
|
282
|
+
get: mockGet,
|
|
283
|
+
clear: jest.fn(),
|
|
284
|
+
};
|
|
285
|
+
sdk["tokenStorage"] = mockTokenStorage;
|
|
286
|
+
await expect(sdk.refreshToken()).rejects.toThrow(ShopeeSdkError);
|
|
287
|
+
});
|
|
288
|
+
it("should return null when refresh token returns null", async () => {
|
|
289
|
+
const oldToken = {
|
|
290
|
+
access_token: "old_token",
|
|
291
|
+
refresh_token: "test_refresh_token",
|
|
292
|
+
expire_in: 3600,
|
|
293
|
+
request_id: "test_request_id",
|
|
294
|
+
error: "",
|
|
295
|
+
message: "",
|
|
296
|
+
};
|
|
297
|
+
// Mock token storage
|
|
298
|
+
const mockGet = jest.fn();
|
|
299
|
+
mockGet.mockResolvedValue(oldToken);
|
|
300
|
+
const mockTokenStorage = {
|
|
301
|
+
store: jest.fn(),
|
|
302
|
+
get: mockGet,
|
|
303
|
+
clear: jest.fn(),
|
|
304
|
+
};
|
|
305
|
+
sdk["tokenStorage"] = mockTokenStorage;
|
|
306
|
+
// Mock auth manager's getRefreshToken to return null
|
|
307
|
+
const mockGetRefreshToken = jest.fn();
|
|
308
|
+
mockGetRefreshToken.mockResolvedValue(null);
|
|
309
|
+
const mockAuthManager = sdk.auth;
|
|
310
|
+
mockAuthManager.getRefreshToken = mockGetRefreshToken;
|
|
311
|
+
const token = await sdk.refreshToken();
|
|
312
|
+
expect(token).toBeNull();
|
|
313
|
+
});
|
|
314
|
+
});
|
|
315
|
+
});
|
|
316
|
+
//# sourceMappingURL=sdk.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sdk.test.js","sourceRoot":"","sources":["../../src/__tests__/sdk.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
import { jest } from "@jest/globals";
|
|
2
|
+
import { CustomTokenStorage } from "../../storage/custom-token-storage.js";
|
|
3
|
+
import fs from "fs";
|
|
4
|
+
import path from "path";
|
|
5
|
+
// Create a unique test directory for each test run
|
|
6
|
+
const TEST_DIR = path.join(process.cwd(), ".token-test-" + Date.now());
|
|
7
|
+
describe("CustomTokenStorage", () => {
|
|
8
|
+
beforeAll(() => {
|
|
9
|
+
// Mock process.cwd to use test directory
|
|
10
|
+
jest.spyOn(process, "cwd").mockReturnValue(TEST_DIR);
|
|
11
|
+
});
|
|
12
|
+
afterAll(() => {
|
|
13
|
+
// Restore original cwd
|
|
14
|
+
jest.restoreAllMocks();
|
|
15
|
+
// Clean up test directory
|
|
16
|
+
if (fs.existsSync(path.join(TEST_DIR, ".token"))) {
|
|
17
|
+
const tokenDir = path.join(TEST_DIR, ".token");
|
|
18
|
+
const files = fs.readdirSync(tokenDir);
|
|
19
|
+
files.forEach((file) => {
|
|
20
|
+
fs.unlinkSync(path.join(tokenDir, file));
|
|
21
|
+
});
|
|
22
|
+
fs.rmdirSync(tokenDir);
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
afterEach(() => {
|
|
26
|
+
// Clean up token files after each test
|
|
27
|
+
const tokenDir = path.join(TEST_DIR, ".token");
|
|
28
|
+
if (fs.existsSync(tokenDir)) {
|
|
29
|
+
const files = fs.readdirSync(tokenDir);
|
|
30
|
+
files.forEach((file) => {
|
|
31
|
+
fs.unlinkSync(path.join(tokenDir, file));
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
describe("constructor", () => {
|
|
36
|
+
it("should create token directory if it does not exist", () => {
|
|
37
|
+
new CustomTokenStorage(123456);
|
|
38
|
+
const tokenDir = path.join(TEST_DIR, ".token");
|
|
39
|
+
expect(fs.existsSync(tokenDir)).toBe(true);
|
|
40
|
+
});
|
|
41
|
+
it("should use default.json when no shopId is provided", () => {
|
|
42
|
+
new CustomTokenStorage();
|
|
43
|
+
// We can't directly access private properties, but we can verify the storage is created
|
|
44
|
+
const tokenDir = path.join(TEST_DIR, ".token");
|
|
45
|
+
expect(fs.existsSync(tokenDir)).toBe(true);
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
describe("store method", () => {
|
|
49
|
+
it("should store token successfully", async () => {
|
|
50
|
+
const storage = new CustomTokenStorage(123456);
|
|
51
|
+
const token = {
|
|
52
|
+
access_token: "test_token",
|
|
53
|
+
refresh_token: "test_refresh",
|
|
54
|
+
expire_in: 14400,
|
|
55
|
+
expired_at: Date.now() + 14400000,
|
|
56
|
+
shop_id: 123456,
|
|
57
|
+
request_id: "test-request-id",
|
|
58
|
+
error: "",
|
|
59
|
+
message: "",
|
|
60
|
+
};
|
|
61
|
+
await storage.store(token);
|
|
62
|
+
const tokenPath = path.join(TEST_DIR, ".token", "123456.json");
|
|
63
|
+
expect(fs.existsSync(tokenPath)).toBe(true);
|
|
64
|
+
const storedData = JSON.parse(fs.readFileSync(tokenPath, "utf-8"));
|
|
65
|
+
expect(storedData).toEqual(token);
|
|
66
|
+
});
|
|
67
|
+
it("should create default token file on first store with shopId", async () => {
|
|
68
|
+
const storage = new CustomTokenStorage(789012);
|
|
69
|
+
const token = {
|
|
70
|
+
access_token: "test_token",
|
|
71
|
+
refresh_token: "test_refresh",
|
|
72
|
+
expire_in: 14400,
|
|
73
|
+
expired_at: Date.now() + 14400000,
|
|
74
|
+
shop_id: 789012,
|
|
75
|
+
request_id: "test-request-id",
|
|
76
|
+
error: "",
|
|
77
|
+
message: "",
|
|
78
|
+
};
|
|
79
|
+
await storage.store(token);
|
|
80
|
+
const tokenPath = path.join(TEST_DIR, ".token", "789012.json");
|
|
81
|
+
const defaultPath = path.join(TEST_DIR, ".token", "default.json");
|
|
82
|
+
expect(fs.existsSync(tokenPath)).toBe(true);
|
|
83
|
+
expect(fs.existsSync(defaultPath)).toBe(true);
|
|
84
|
+
const storedData = JSON.parse(fs.readFileSync(tokenPath, "utf-8"));
|
|
85
|
+
const defaultData = JSON.parse(fs.readFileSync(defaultPath, "utf-8"));
|
|
86
|
+
expect(storedData).toEqual(token);
|
|
87
|
+
expect(defaultData).toEqual(token);
|
|
88
|
+
});
|
|
89
|
+
it("should not overwrite existing default token", async () => {
|
|
90
|
+
// First, create a default token
|
|
91
|
+
const firstStorage = new CustomTokenStorage(111111);
|
|
92
|
+
const firstToken = {
|
|
93
|
+
access_token: "first_token",
|
|
94
|
+
refresh_token: "first_refresh",
|
|
95
|
+
expire_in: 14400,
|
|
96
|
+
expired_at: Date.now() + 14400000,
|
|
97
|
+
shop_id: 111111,
|
|
98
|
+
request_id: "test-request-id",
|
|
99
|
+
error: "",
|
|
100
|
+
message: "",
|
|
101
|
+
};
|
|
102
|
+
await firstStorage.store(firstToken);
|
|
103
|
+
// Then store a second token with different shopId
|
|
104
|
+
const secondStorage = new CustomTokenStorage(222222);
|
|
105
|
+
const secondToken = {
|
|
106
|
+
access_token: "second_token",
|
|
107
|
+
refresh_token: "second_refresh",
|
|
108
|
+
expire_in: 14400,
|
|
109
|
+
expired_at: Date.now() + 14400000,
|
|
110
|
+
shop_id: 222222,
|
|
111
|
+
request_id: "test-request-id",
|
|
112
|
+
error: "",
|
|
113
|
+
message: "",
|
|
114
|
+
};
|
|
115
|
+
await secondStorage.store(secondToken);
|
|
116
|
+
const defaultPath = path.join(TEST_DIR, ".token", "default.json");
|
|
117
|
+
const defaultData = JSON.parse(fs.readFileSync(defaultPath, "utf-8"));
|
|
118
|
+
// Default should still be the first token
|
|
119
|
+
expect(defaultData.access_token).toBe("first_token");
|
|
120
|
+
});
|
|
121
|
+
it("should throw error on write failure", async () => {
|
|
122
|
+
const storage = new CustomTokenStorage(999999);
|
|
123
|
+
const token = {
|
|
124
|
+
access_token: "test_token",
|
|
125
|
+
refresh_token: "test_refresh",
|
|
126
|
+
expire_in: 14400,
|
|
127
|
+
expired_at: Date.now() + 14400000,
|
|
128
|
+
shop_id: 999999,
|
|
129
|
+
request_id: "test-request-id",
|
|
130
|
+
error: "",
|
|
131
|
+
message: "",
|
|
132
|
+
};
|
|
133
|
+
// Mock writeFileSync to throw an error
|
|
134
|
+
const originalWriteFileSync = fs.writeFileSync;
|
|
135
|
+
jest.spyOn(fs, "writeFileSync").mockImplementation(() => {
|
|
136
|
+
throw new Error("Write failed");
|
|
137
|
+
});
|
|
138
|
+
await expect(storage.store(token)).rejects.toThrow("Failed to store token");
|
|
139
|
+
await expect(storage.store(token)).rejects.toThrow("Write failed");
|
|
140
|
+
// Restore original function
|
|
141
|
+
fs.writeFileSync = originalWriteFileSync;
|
|
142
|
+
});
|
|
143
|
+
});
|
|
144
|
+
describe("get method", () => {
|
|
145
|
+
it("should retrieve stored token successfully", async () => {
|
|
146
|
+
const storage = new CustomTokenStorage(123456);
|
|
147
|
+
const token = {
|
|
148
|
+
access_token: "test_token",
|
|
149
|
+
refresh_token: "test_refresh",
|
|
150
|
+
expire_in: 14400,
|
|
151
|
+
expired_at: Date.now() + 14400000,
|
|
152
|
+
shop_id: 123456,
|
|
153
|
+
request_id: "test-request-id",
|
|
154
|
+
error: "",
|
|
155
|
+
message: "",
|
|
156
|
+
};
|
|
157
|
+
await storage.store(token);
|
|
158
|
+
const retrieved = await storage.get();
|
|
159
|
+
expect(retrieved).toEqual(token);
|
|
160
|
+
});
|
|
161
|
+
it("should return null when token file does not exist", async () => {
|
|
162
|
+
const storage = new CustomTokenStorage(999999);
|
|
163
|
+
const result = await storage.get();
|
|
164
|
+
expect(result).toBeNull();
|
|
165
|
+
});
|
|
166
|
+
it("should throw error on read failure (non-ENOENT)", async () => {
|
|
167
|
+
const storage = new CustomTokenStorage(555555);
|
|
168
|
+
const token = {
|
|
169
|
+
access_token: "test_token",
|
|
170
|
+
refresh_token: "test_refresh",
|
|
171
|
+
expire_in: 14400,
|
|
172
|
+
expired_at: Date.now() + 14400000,
|
|
173
|
+
shop_id: 555555,
|
|
174
|
+
request_id: "test-request-id",
|
|
175
|
+
error: "",
|
|
176
|
+
message: "",
|
|
177
|
+
};
|
|
178
|
+
await storage.store(token);
|
|
179
|
+
// Mock readFileSync to throw a non-ENOENT error
|
|
180
|
+
const originalReadFileSync = fs.readFileSync;
|
|
181
|
+
jest.spyOn(fs, "readFileSync").mockImplementation(() => {
|
|
182
|
+
const error = new Error("Permission denied");
|
|
183
|
+
error.code = "EACCES";
|
|
184
|
+
throw error;
|
|
185
|
+
});
|
|
186
|
+
await expect(storage.get()).rejects.toThrow("Failed to get token");
|
|
187
|
+
await expect(storage.get()).rejects.toThrow("Permission denied");
|
|
188
|
+
// Restore original function
|
|
189
|
+
fs.readFileSync = originalReadFileSync;
|
|
190
|
+
});
|
|
191
|
+
});
|
|
192
|
+
describe("clear method", () => {
|
|
193
|
+
it("should clear stored token successfully", async () => {
|
|
194
|
+
const storage = new CustomTokenStorage(123456);
|
|
195
|
+
const token = {
|
|
196
|
+
access_token: "test_token",
|
|
197
|
+
refresh_token: "test_refresh",
|
|
198
|
+
expire_in: 14400,
|
|
199
|
+
expired_at: Date.now() + 14400000,
|
|
200
|
+
shop_id: 123456,
|
|
201
|
+
request_id: "test-request-id",
|
|
202
|
+
error: "",
|
|
203
|
+
message: "",
|
|
204
|
+
};
|
|
205
|
+
await storage.store(token);
|
|
206
|
+
const tokenPath = path.join(TEST_DIR, ".token", "123456.json");
|
|
207
|
+
expect(fs.existsSync(tokenPath)).toBe(true);
|
|
208
|
+
await storage.clear();
|
|
209
|
+
expect(fs.existsSync(tokenPath)).toBe(false);
|
|
210
|
+
const retrieved = await storage.get();
|
|
211
|
+
expect(retrieved).toBeNull();
|
|
212
|
+
});
|
|
213
|
+
it("should handle clearing non-existent token gracefully", async () => {
|
|
214
|
+
const storage = new CustomTokenStorage(999999);
|
|
215
|
+
// Should not throw error
|
|
216
|
+
await expect(storage.clear()).resolves.not.toThrow();
|
|
217
|
+
});
|
|
218
|
+
it("should throw error on delete failure (non-ENOENT)", async () => {
|
|
219
|
+
const storage = new CustomTokenStorage(777777);
|
|
220
|
+
const token = {
|
|
221
|
+
access_token: "test_token",
|
|
222
|
+
refresh_token: "test_refresh",
|
|
223
|
+
expire_in: 14400,
|
|
224
|
+
expired_at: Date.now() + 14400000,
|
|
225
|
+
shop_id: 777777,
|
|
226
|
+
request_id: "test-request-id",
|
|
227
|
+
error: "",
|
|
228
|
+
message: "",
|
|
229
|
+
};
|
|
230
|
+
await storage.store(token);
|
|
231
|
+
// Mock unlinkSync to throw a non-ENOENT error
|
|
232
|
+
const originalUnlinkSync = fs.unlinkSync;
|
|
233
|
+
jest.spyOn(fs, "unlinkSync").mockImplementation(() => {
|
|
234
|
+
const error = new Error("Permission denied");
|
|
235
|
+
error.code = "EACCES";
|
|
236
|
+
throw error;
|
|
237
|
+
});
|
|
238
|
+
await expect(storage.clear()).rejects.toThrow("Failed to clear token");
|
|
239
|
+
await expect(storage.clear()).rejects.toThrow("Permission denied");
|
|
240
|
+
// Restore original function
|
|
241
|
+
fs.unlinkSync = originalUnlinkSync;
|
|
242
|
+
});
|
|
243
|
+
});
|
|
244
|
+
describe("integration tests", () => {
|
|
245
|
+
it("should handle full lifecycle: store, get, clear", async () => {
|
|
246
|
+
const storage = new CustomTokenStorage(888888);
|
|
247
|
+
// Initially should be null
|
|
248
|
+
let result = await storage.get();
|
|
249
|
+
expect(result).toBeNull();
|
|
250
|
+
// Store a token
|
|
251
|
+
const token = {
|
|
252
|
+
access_token: "lifecycle_token",
|
|
253
|
+
refresh_token: "lifecycle_refresh",
|
|
254
|
+
expire_in: 14400,
|
|
255
|
+
expired_at: Date.now() + 14400000,
|
|
256
|
+
shop_id: 888888,
|
|
257
|
+
request_id: "test-request-id",
|
|
258
|
+
error: "",
|
|
259
|
+
message: "",
|
|
260
|
+
};
|
|
261
|
+
await storage.store(token);
|
|
262
|
+
// Retrieve the token
|
|
263
|
+
result = await storage.get();
|
|
264
|
+
expect(result).toEqual(token);
|
|
265
|
+
// Clear the token
|
|
266
|
+
await storage.clear();
|
|
267
|
+
// Should be null again
|
|
268
|
+
result = await storage.get();
|
|
269
|
+
expect(result).toBeNull();
|
|
270
|
+
});
|
|
271
|
+
it("should handle multiple shop IDs independently", async () => {
|
|
272
|
+
const storage1 = new CustomTokenStorage(111);
|
|
273
|
+
const storage2 = new CustomTokenStorage(222);
|
|
274
|
+
const token1 = {
|
|
275
|
+
access_token: "token_111",
|
|
276
|
+
refresh_token: "refresh_111",
|
|
277
|
+
expire_in: 14400,
|
|
278
|
+
expired_at: Date.now() + 14400000,
|
|
279
|
+
shop_id: 111,
|
|
280
|
+
request_id: "test-request-id",
|
|
281
|
+
error: "",
|
|
282
|
+
message: "",
|
|
283
|
+
};
|
|
284
|
+
const token2 = {
|
|
285
|
+
access_token: "token_222",
|
|
286
|
+
refresh_token: "refresh_222",
|
|
287
|
+
expire_in: 14400,
|
|
288
|
+
expired_at: Date.now() + 14400000,
|
|
289
|
+
shop_id: 222,
|
|
290
|
+
request_id: "test-request-id",
|
|
291
|
+
error: "",
|
|
292
|
+
message: "",
|
|
293
|
+
};
|
|
294
|
+
await storage1.store(token1);
|
|
295
|
+
await storage2.store(token2);
|
|
296
|
+
const retrieved1 = await storage1.get();
|
|
297
|
+
const retrieved2 = await storage2.get();
|
|
298
|
+
expect(retrieved1?.shop_id).toBe(111);
|
|
299
|
+
expect(retrieved2?.shop_id).toBe(222);
|
|
300
|
+
});
|
|
301
|
+
});
|
|
302
|
+
describe("Non-Error Exception Handling", () => {
|
|
303
|
+
let originalWrite;
|
|
304
|
+
let originalRead;
|
|
305
|
+
let originalUnlink;
|
|
306
|
+
beforeEach(() => {
|
|
307
|
+
originalWrite = fs.writeFileSync;
|
|
308
|
+
originalRead = fs.readFileSync;
|
|
309
|
+
originalUnlink = fs.unlinkSync;
|
|
310
|
+
});
|
|
311
|
+
afterEach(() => {
|
|
312
|
+
fs.writeFileSync = originalWrite;
|
|
313
|
+
fs.readFileSync = originalRead;
|
|
314
|
+
fs.unlinkSync = originalUnlink;
|
|
315
|
+
jest.restoreAllMocks();
|
|
316
|
+
});
|
|
317
|
+
it("should catch non-Error exceptions correctly", async () => {
|
|
318
|
+
const storage = new CustomTokenStorage(888899);
|
|
319
|
+
// 1. fs.writeFileSync throws string
|
|
320
|
+
jest.spyOn(fs, "writeFileSync").mockImplementation(() => {
|
|
321
|
+
throw "String write error";
|
|
322
|
+
});
|
|
323
|
+
await expect(storage.store({})).rejects.toThrow("Failed to store token: Unknown error");
|
|
324
|
+
// 2. fs.readFileSync throws string
|
|
325
|
+
jest.spyOn(fs, "readFileSync").mockImplementation(() => {
|
|
326
|
+
throw "String read error";
|
|
327
|
+
});
|
|
328
|
+
await expect(storage.get()).rejects.toThrow("Failed to get token: Unknown error");
|
|
329
|
+
// 3. fs.unlinkSync throws string
|
|
330
|
+
jest.spyOn(fs, "unlinkSync").mockImplementation(() => {
|
|
331
|
+
throw "String unlink error";
|
|
332
|
+
});
|
|
333
|
+
await expect(storage.clear()).rejects.toThrow("Failed to clear token: Unknown error");
|
|
334
|
+
});
|
|
335
|
+
});
|
|
336
|
+
});
|
|
337
|
+
//# sourceMappingURL=custom-token-storage.test.js.map
|