@pinata/sdk 1.1.26 → 1.2.1
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/.babelrc +4 -3
- package/.nvmrc +1 -1
- package/README.md +103 -19
- package/lib/pinata-sdk.js +615 -157
- package/lib/pinata-sdk.min.js +5 -5
- package/package.json +3 -2
- package/src/commands/data/getFilesByCount/getFilesByCount.js +67 -0
- package/src/commands/data/pinList/pinList.js +6 -11
- package/src/commands/data/pinList/queryBuilder.js +4 -0
- package/src/commands/data/testAuthentication.js +4 -11
- package/src/commands/data/userPinnedDataTotal.js +4 -11
- package/src/commands/pinning/hashMetadata.js +4 -11
- package/src/commands/pinning/hashPinPolicy.js +4 -10
- package/src/commands/pinning/pinByHash.js +4 -11
- package/src/commands/pinning/pinFileToIPFS.js +5 -16
- package/src/commands/pinning/pinFromFS.js +6 -23
- package/src/commands/pinning/pinJSONToIPFS.js +4 -10
- package/src/commands/pinning/pinJobs/pinJobs.js +4 -10
- package/src/commands/pinning/unpin.js +4 -11
- package/src/commands/pinning/userPinPolicy.js +4 -10
- package/src/constants.js +3 -0
- package/src/index.js +63 -13
- package/src/util/validators.js +88 -12
- package/test/commands/data/getFilesByCount/getFilesByCount.test.js +211 -0
- package/test/commands/data/pinList/pinList.test.js +100 -26
- package/test/commands/data/pinlist-sample-api.js +540 -0
- package/test/commands/data/testAuthentication.test.js +17 -13
- package/test/commands/data/userPinnedDataTotal.test.js +3 -3
- package/test/commands/pinning/hashMetadata.test.js +7 -7
- package/test/commands/pinning/hashPinPolicy.test.js +6 -6
- package/test/commands/pinning/pinByHash.test.js +4 -4
- package/test/commands/pinning/pinFileToIPFS.test.js +5 -5
- package/test/commands/pinning/pinFromFS.js +3 -3
- package/test/commands/pinning/pinJSONToIPFS.test.js +4 -4
- package/test/commands/pinning/pinJobs/pinJobs.test.js +3 -3
- package/test/commands/pinning/unpin.test.js +5 -5
- package/test/commands/pinning/userPinPolicy.test.js +51 -22
- package/test/util/validators.test.js +114 -72
- package/types/commands/data/getFilesByCount/getFilesByCount.d.ts +12 -0
- package/types/commands/data/pinList/pinList.d.ts +2 -2
- package/types/commands/data/testAuthentication.d.ts +1 -1
- package/types/commands/data/userPinnedDataTotal.d.ts +1 -1
- package/types/commands/pinning/hashMetadata.d.ts +1 -1
- package/types/commands/pinning/hashPinPolicy.d.ts +1 -1
- package/types/commands/pinning/pinByHash.d.ts +1 -1
- package/types/commands/pinning/pinFileToIPFS.d.ts +1 -1
- package/types/commands/pinning/pinFromFS.d.ts +1 -1
- package/types/commands/pinning/pinJSONToIPFS.d.ts +1 -1
- package/types/commands/pinning/pinJobs/pinJobs.d.ts +1 -1
- package/types/commands/pinning/unpin.d.ts +1 -1
- package/types/commands/pinning/userPinPolicy.d.ts +1 -1
- package/types/constants.d.ts +1 -0
- package/types/index.d.ts +9 -174
- package/types/util/validators.d.ts +34 -0
package/src/index.js
CHANGED
|
@@ -7,6 +7,7 @@ import pinJobs from './commands/pinning/pinJobs/pinJobs';
|
|
|
7
7
|
import unpin from './commands/pinning/unpin';
|
|
8
8
|
import testAuthentication from './commands/data/testAuthentication';
|
|
9
9
|
import pinList from './commands/data/pinList/pinList';
|
|
10
|
+
import getFilesByCount from './commands/data/getFilesByCount/getFilesByCount';
|
|
10
11
|
import userPinnedDataTotal from './commands/data/userPinnedDataTotal';
|
|
11
12
|
|
|
12
13
|
// OPTIONS
|
|
@@ -198,8 +199,16 @@ import userPinnedDataTotal from './commands/data/userPinnedDataTotal';
|
|
|
198
199
|
* @returns {Promise<number>}
|
|
199
200
|
*/
|
|
200
201
|
|
|
202
|
+
/**
|
|
203
|
+
* @typedef {Object} PinataConfig
|
|
204
|
+
* @property {string} [pinataApiKey]
|
|
205
|
+
* @property {string} [pinataSecretApiKey]
|
|
206
|
+
* @property {string} [pinataJWTKey]
|
|
207
|
+
*/
|
|
208
|
+
|
|
201
209
|
/**
|
|
202
210
|
* @typedef PinataClient
|
|
211
|
+
* @property {PinataConfig} config
|
|
203
212
|
* @property {pinByHash} pinByHash
|
|
204
213
|
* @property {hashMetadata} hashMetadata
|
|
205
214
|
* @property {pinFileToIPFS} pinFileToIPFS
|
|
@@ -212,46 +221,87 @@ import userPinnedDataTotal from './commands/data/userPinnedDataTotal';
|
|
|
212
221
|
* @property {userPinnedDataTotal} userPinnedDataTotal
|
|
213
222
|
*/
|
|
214
223
|
|
|
224
|
+
function refactorConfig(pinataConfigParam) {
|
|
225
|
+
const config = {};
|
|
226
|
+
if (pinataConfigParam.pinataApiKey) {
|
|
227
|
+
config.pinataApiKey = pinataConfigParam.pinataApiKey;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
if (pinataConfigParam.pinataSecretApiKey) {
|
|
231
|
+
config.pinataSecretApiKey = pinataConfigParam.pinataSecretApiKey;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
if (pinataConfigParam.pinataJWTKey) {
|
|
235
|
+
config.pinataJWTKey = pinataConfigParam.pinataJWTKey;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
return config;
|
|
239
|
+
}
|
|
240
|
+
function sanitizeConfig(pinataApiKey, pinataSecretApiKey) {
|
|
241
|
+
let config = {};
|
|
242
|
+
|
|
243
|
+
if (
|
|
244
|
+
typeof pinataApiKey === 'string' &&
|
|
245
|
+
typeof pinataSecretApiKey === 'string'
|
|
246
|
+
) {
|
|
247
|
+
config.pinataApiKey = pinataApiKey;
|
|
248
|
+
config.pinataSecretApiKey = pinataSecretApiKey;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
const isPinataConfigParam = typeof pinataApiKey === 'object';
|
|
252
|
+
if (isPinataConfigParam) {
|
|
253
|
+
config = refactorConfig(pinataApiKey);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
return config;
|
|
257
|
+
}
|
|
258
|
+
|
|
215
259
|
/**
|
|
216
260
|
* Pinata Client
|
|
217
261
|
*
|
|
218
|
-
* @param {string} pinataApiKey
|
|
219
|
-
* @param {string} pinataSecretApiKey
|
|
262
|
+
* @param {string | PinataConfig} [pinataApiKey]
|
|
263
|
+
* @param {string} [pinataSecretApiKey]
|
|
220
264
|
* @returns {PinataClient}
|
|
221
265
|
*/
|
|
222
266
|
export default function pinataClient(pinataApiKey, pinataSecretApiKey) {
|
|
223
|
-
|
|
267
|
+
const client = {
|
|
268
|
+
config: sanitizeConfig(pinataApiKey, pinataSecretApiKey)
|
|
269
|
+
};
|
|
224
270
|
|
|
225
271
|
// setting up the actual calls you can make using this package
|
|
226
272
|
client.pinByHash = function (hashToPin, options) {
|
|
227
|
-
return pinByHash(
|
|
273
|
+
return pinByHash(client.config, hashToPin, options);
|
|
228
274
|
};
|
|
229
275
|
client.hashMetadata = function (ipfsPinHash, metadata) {
|
|
230
|
-
return hashMetadata(
|
|
276
|
+
return hashMetadata(client.config, ipfsPinHash, metadata);
|
|
231
277
|
};
|
|
232
278
|
client.pinFileToIPFS = function (readableStream, options) {
|
|
233
|
-
return pinFileToIPFS(
|
|
279
|
+
return pinFileToIPFS(client.config, readableStream, options);
|
|
234
280
|
};
|
|
235
281
|
client.pinFromFS = function (sourcePath, options) {
|
|
236
|
-
return pinFromFS(
|
|
282
|
+
return pinFromFS(client.config, sourcePath, options);
|
|
237
283
|
};
|
|
238
284
|
client.pinJSONToIPFS = function (body, options) {
|
|
239
|
-
return pinJSONToIPFS(
|
|
285
|
+
return pinJSONToIPFS(client.config, body, options);
|
|
240
286
|
};
|
|
241
287
|
client.pinJobs = function (filters) {
|
|
242
|
-
return pinJobs(
|
|
288
|
+
return pinJobs(client.config, filters);
|
|
243
289
|
};
|
|
244
290
|
client.unpin = function (hashToUnpin) {
|
|
245
|
-
return unpin(
|
|
291
|
+
return unpin(client.config, hashToUnpin);
|
|
246
292
|
};
|
|
247
293
|
client.testAuthentication = function () {
|
|
248
|
-
return testAuthentication(
|
|
294
|
+
return testAuthentication(client.config);
|
|
249
295
|
};
|
|
250
296
|
client.pinList = function (filters) {
|
|
251
|
-
return pinList(
|
|
297
|
+
return pinList(client.config, filters);
|
|
298
|
+
};
|
|
299
|
+
|
|
300
|
+
client.getFilesByCount = function (filters, maxCount) {
|
|
301
|
+
return getFilesByCount(client.config, filters, maxCount);
|
|
252
302
|
};
|
|
253
303
|
client.userPinnedDataTotal = function () {
|
|
254
|
-
return userPinnedDataTotal(
|
|
304
|
+
return userPinnedDataTotal(client.config);
|
|
255
305
|
};
|
|
256
306
|
return client;
|
|
257
307
|
}
|
package/src/util/validators.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import isIPFS from 'is-ipfs';
|
|
2
|
-
|
|
2
|
+
import { ERROR_NO_CREDENTIALS_PROVIDED} from '../constants';
|
|
3
3
|
/**
|
|
4
4
|
* Validate API Keys
|
|
5
5
|
* @param {string} pinataApiKey
|
|
@@ -7,11 +7,53 @@ import isIPFS from 'is-ipfs';
|
|
|
7
7
|
*/
|
|
8
8
|
export function validateApiKeys(pinataApiKey, pinataSecretApiKey) {
|
|
9
9
|
if (!pinataApiKey || pinataApiKey === '') {
|
|
10
|
-
throw new Error(
|
|
10
|
+
throw new Error(
|
|
11
|
+
'No pinataApiKey provided! Please provide your pinata api key as an argument when you start this script'
|
|
12
|
+
);
|
|
11
13
|
}
|
|
12
14
|
if (!pinataSecretApiKey || pinataSecretApiKey === '') {
|
|
13
|
-
throw new Error(
|
|
15
|
+
throw new Error(
|
|
16
|
+
'No pinataSecretApiKey provided! Please provide your pinata secret api key as an argument when you start this script'
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function createConfigForAxiosHeaders(config) {
|
|
22
|
+
if (
|
|
23
|
+
config.pinataApiKey && config.pinataApiKey.length > 0 &&
|
|
24
|
+
config.pinataSecretApiKey && config.pinataSecretApiKey.length > 0
|
|
25
|
+
) {
|
|
26
|
+
return {
|
|
27
|
+
withCredentials: true,
|
|
28
|
+
headers: {
|
|
29
|
+
pinata_api_key: config.pinataApiKey,
|
|
30
|
+
pinata_secret_api_key: config.pinataSecretApiKey
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (config.pinataJWTKey && config.pinataJWTKey.length > 0) {
|
|
36
|
+
return {
|
|
37
|
+
headers: {
|
|
38
|
+
Authorization: `Bearer ${config.pinataJWTKey}`
|
|
39
|
+
}
|
|
40
|
+
};
|
|
14
41
|
}
|
|
42
|
+
|
|
43
|
+
throw new Error(ERROR_NO_CREDENTIALS_PROVIDED);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function createConfigForAxiosHeadersWithFormData(config, boundaryValue) {
|
|
47
|
+
const requestOptions = {
|
|
48
|
+
...createConfigForAxiosHeaders(config),
|
|
49
|
+
maxContentLength: Infinity, //this is needed to prevent axios from erroring out with large files
|
|
50
|
+
maxBodyLength: Infinity
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
requestOptions.headers[
|
|
54
|
+
'Content-type'
|
|
55
|
+
] = `multipart/form-data; boundary= ${boundaryValue}`;
|
|
56
|
+
return requestOptions;
|
|
15
57
|
}
|
|
16
58
|
|
|
17
59
|
/**
|
|
@@ -24,7 +66,9 @@ export function validateHostNodes(hostNodes) {
|
|
|
24
66
|
}
|
|
25
67
|
hostNodes.forEach((node) => {
|
|
26
68
|
if (!isIPFS.peerMultiaddr(node)) {
|
|
27
|
-
throw new Error(
|
|
69
|
+
throw new Error(
|
|
70
|
+
`host_node array entry: ${node} is not a valid peer multiaddr`
|
|
71
|
+
);
|
|
28
72
|
}
|
|
29
73
|
});
|
|
30
74
|
}
|
|
@@ -35,7 +79,12 @@ export function validateHostNodes(hostNodes) {
|
|
|
35
79
|
*/
|
|
36
80
|
export function validateMetadata(metadata) {
|
|
37
81
|
if (metadata.name) {
|
|
38
|
-
if (
|
|
82
|
+
if (
|
|
83
|
+
!(
|
|
84
|
+
typeof metadata.name === 'string' ||
|
|
85
|
+
metadata.name instanceof String
|
|
86
|
+
)
|
|
87
|
+
) {
|
|
39
88
|
throw new Error('metadata name must be of type string');
|
|
40
89
|
}
|
|
41
90
|
}
|
|
@@ -49,11 +98,21 @@ export function validateMetadata(metadata) {
|
|
|
49
98
|
|
|
50
99
|
Object.entries(metadata.keyvalues).forEach(function (keyValue) {
|
|
51
100
|
if (i > 9) {
|
|
52
|
-
throw new Error(
|
|
101
|
+
throw new Error(
|
|
102
|
+
'No more than 10 keyvalues can be provided for metadata entries'
|
|
103
|
+
);
|
|
53
104
|
}
|
|
54
105
|
// we want to make sure that the input is a string, a boolean, or a number, so we don't get an object passed in by accident
|
|
55
|
-
if (
|
|
56
|
-
|
|
106
|
+
if (
|
|
107
|
+
!(
|
|
108
|
+
typeof keyValue[1] === 'string' ||
|
|
109
|
+
typeof keyValue[1] === 'boolean' ||
|
|
110
|
+
!isNaN(keyValue[1])
|
|
111
|
+
)
|
|
112
|
+
) {
|
|
113
|
+
throw new Error(
|
|
114
|
+
'Metadata keyvalue values must be strings, booleans, or numbers'
|
|
115
|
+
);
|
|
57
116
|
}
|
|
58
117
|
i++;
|
|
59
118
|
});
|
|
@@ -75,11 +134,23 @@ export function validatePinPolicyStructure(pinPolicy) {
|
|
|
75
134
|
}
|
|
76
135
|
if (pinPolicy.regions.length) {
|
|
77
136
|
pinPolicy.regions.forEach((region) => {
|
|
78
|
-
if (
|
|
137
|
+
if (
|
|
138
|
+
!region.id ||
|
|
139
|
+
!(
|
|
140
|
+
Object.prototype.toString.call(region.id) ===
|
|
141
|
+
'[object String]'
|
|
142
|
+
)
|
|
143
|
+
) {
|
|
79
144
|
throw new Error('region id must be a string');
|
|
80
145
|
}
|
|
81
146
|
|
|
82
|
-
if (
|
|
147
|
+
if (
|
|
148
|
+
!(
|
|
149
|
+
region.desiredReplicationCount ||
|
|
150
|
+
region.desiredReplicationCount === 0
|
|
151
|
+
) ||
|
|
152
|
+
!Number.isInteger(region.desiredReplicationCount)
|
|
153
|
+
) {
|
|
83
154
|
throw new Error('desiredReplicationCount must be an integer');
|
|
84
155
|
}
|
|
85
156
|
});
|
|
@@ -103,8 +174,13 @@ export function validatePinataOptions(options) {
|
|
|
103
174
|
}
|
|
104
175
|
if (options.wrapWithDirectory) {
|
|
105
176
|
// eslint-disable-next-line eqeqeq
|
|
106
|
-
if (
|
|
107
|
-
|
|
177
|
+
if (
|
|
178
|
+
options.wrapWithDirectory !== true &&
|
|
179
|
+
options.wrapWithDirectory !== false
|
|
180
|
+
) {
|
|
181
|
+
throw new Error(
|
|
182
|
+
'wrapWithDirectory must be a boolean value of true or false'
|
|
183
|
+
);
|
|
108
184
|
}
|
|
109
185
|
}
|
|
110
186
|
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
import getFilesByCount from "../../../../src/commands/data/getFilesByCount/getFilesByCount";
|
|
2
|
+
import axios from "axios";
|
|
3
|
+
import {
|
|
4
|
+
APIData,
|
|
5
|
+
pinListAxiosMockPages,
|
|
6
|
+
fakeHeaders,
|
|
7
|
+
} from "../pinlist-sample-api";
|
|
8
|
+
|
|
9
|
+
jest.mock("axios");
|
|
10
|
+
|
|
11
|
+
const metadataName = (item) => {
|
|
12
|
+
return item.metadata.name;
|
|
13
|
+
};
|
|
14
|
+
const callIterableObject = async (config, filterToApply, pinsCount) => {
|
|
15
|
+
const pins = [];
|
|
16
|
+
for await (const item of getFilesByCount(
|
|
17
|
+
config,
|
|
18
|
+
filterToApply,
|
|
19
|
+
pinsCount
|
|
20
|
+
)) {
|
|
21
|
+
pins.push(metadataName(item));
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return pins;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
describe("Get Files By Count", () => {
|
|
28
|
+
const pinataConfig = {
|
|
29
|
+
pinataApiKey: fakeHeaders.headers.pinata_api_key,
|
|
30
|
+
pinataSecretApiKey: fakeHeaders.headers.pinata_secret_api_key,
|
|
31
|
+
};
|
|
32
|
+
const filterToApply = {
|
|
33
|
+
status: "pinned",
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
afterEach(() => {
|
|
37
|
+
jest.resetAllMocks();
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
test("Request 17 pins, pins available", async () => {
|
|
41
|
+
const pinsToRequest = 17;
|
|
42
|
+
|
|
43
|
+
axios.get
|
|
44
|
+
.mockResolvedValueOnce(pinListAxiosMockPages.firstPage.response)
|
|
45
|
+
.mockResolvedValueOnce(pinListAxiosMockPages.secondPage.response);
|
|
46
|
+
|
|
47
|
+
const pins = await callIterableObject(
|
|
48
|
+
pinataConfig,
|
|
49
|
+
filterToApply,
|
|
50
|
+
pinsToRequest
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
expect(pins).toEqual(
|
|
54
|
+
APIData.rows.slice(0, pinsToRequest).map(metadataName)
|
|
55
|
+
);
|
|
56
|
+
expect(pins).toHaveLength(pinsToRequest);
|
|
57
|
+
expect(axios.get).toHaveBeenNthCalledWith(
|
|
58
|
+
1,
|
|
59
|
+
pinListAxiosMockPages.firstPage.url,
|
|
60
|
+
pinListAxiosMockPages.firstPage.headers
|
|
61
|
+
);
|
|
62
|
+
expect(axios.get).toHaveBeenNthCalledWith(
|
|
63
|
+
2,
|
|
64
|
+
pinListAxiosMockPages.secondPage.url,
|
|
65
|
+
pinListAxiosMockPages.secondPage.headers
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
expect(axios.get).toHaveBeenCalledTimes(2);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
test("Request 6 pins, pins available", async () => {
|
|
72
|
+
const pinsToRequest = 6;
|
|
73
|
+
|
|
74
|
+
axios.get.mockResolvedValueOnce(
|
|
75
|
+
pinListAxiosMockPages.firstPage.response
|
|
76
|
+
);
|
|
77
|
+
const pins = await callIterableObject(
|
|
78
|
+
pinataConfig,
|
|
79
|
+
filterToApply,
|
|
80
|
+
pinsToRequest
|
|
81
|
+
);
|
|
82
|
+
expect(pins).toEqual(
|
|
83
|
+
APIData.rows.slice(0, pinsToRequest).map(metadataName)
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
expect(pins).toHaveLength(pinsToRequest);
|
|
87
|
+
expect(axios.get).toHaveBeenNthCalledWith(
|
|
88
|
+
1,
|
|
89
|
+
pinListAxiosMockPages.firstPage.url,
|
|
90
|
+
pinListAxiosMockPages.firstPage.headers
|
|
91
|
+
);
|
|
92
|
+
expect(axios.get).toHaveBeenCalledTimes(1);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
test("Request 25 pins, pins not available", async () => {
|
|
96
|
+
const pinsToRequest = 25;
|
|
97
|
+
|
|
98
|
+
axios.get
|
|
99
|
+
.mockResolvedValueOnce(pinListAxiosMockPages.firstPage.response)
|
|
100
|
+
.mockResolvedValueOnce(pinListAxiosMockPages.secondPage.response)
|
|
101
|
+
.mockResolvedValueOnce(
|
|
102
|
+
pinListAxiosMockPages.thirdPageEmpty.response
|
|
103
|
+
);
|
|
104
|
+
const pins = await callIterableObject(
|
|
105
|
+
pinataConfig,
|
|
106
|
+
filterToApply,
|
|
107
|
+
pinsToRequest
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
expect(pins).toEqual(
|
|
111
|
+
APIData.rows.slice(0, pinsToRequest).map(metadataName)
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
expect(pins).toHaveLength(20);
|
|
115
|
+
expect(axios.get).toHaveBeenNthCalledWith(
|
|
116
|
+
1,
|
|
117
|
+
pinListAxiosMockPages.firstPage.url,
|
|
118
|
+
pinListAxiosMockPages.firstPage.headers
|
|
119
|
+
);
|
|
120
|
+
expect(axios.get).toHaveBeenNthCalledWith(
|
|
121
|
+
2,
|
|
122
|
+
pinListAxiosMockPages.secondPage.url,
|
|
123
|
+
pinListAxiosMockPages.secondPage.headers
|
|
124
|
+
);
|
|
125
|
+
expect(axios.get).toHaveBeenNthCalledWith(
|
|
126
|
+
3,
|
|
127
|
+
pinListAxiosMockPages.thirdPageEmpty.url,
|
|
128
|
+
pinListAxiosMockPages.thirdPageEmpty.headers
|
|
129
|
+
);
|
|
130
|
+
|
|
131
|
+
expect(axios.get).toHaveBeenCalledTimes(3);
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
test("Request 3 pins, pins not available", async () => {
|
|
135
|
+
const pinsToRequest = 3;
|
|
136
|
+
|
|
137
|
+
axios.get.mockResolvedValueOnce(
|
|
138
|
+
pinListAxiosMockPages.firstPageEmpty.response
|
|
139
|
+
);
|
|
140
|
+
const pins = await callIterableObject(
|
|
141
|
+
pinataConfig,
|
|
142
|
+
filterToApply,
|
|
143
|
+
pinsToRequest
|
|
144
|
+
);
|
|
145
|
+
|
|
146
|
+
expect(pins).toEqual([]);
|
|
147
|
+
|
|
148
|
+
expect(pins).toHaveLength(0);
|
|
149
|
+
expect(axios.get).toHaveBeenNthCalledWith(
|
|
150
|
+
1,
|
|
151
|
+
pinListAxiosMockPages.firstPageEmpty.url,
|
|
152
|
+
pinListAxiosMockPages.firstPageEmpty.headers
|
|
153
|
+
);
|
|
154
|
+
|
|
155
|
+
expect(axios.get).toHaveBeenCalledTimes(1);
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
test("Request all pins, pins available", async () => {
|
|
159
|
+
axios.get
|
|
160
|
+
.mockResolvedValueOnce(pinListAxiosMockPages.firstPage.response)
|
|
161
|
+
.mockResolvedValueOnce(pinListAxiosMockPages.secondPage.response)
|
|
162
|
+
.mockResolvedValueOnce(
|
|
163
|
+
pinListAxiosMockPages.thirdPageEmpty.response
|
|
164
|
+
);
|
|
165
|
+
const pins = await callIterableObject(
|
|
166
|
+
pinataConfig,
|
|
167
|
+
filterToApply
|
|
168
|
+
);
|
|
169
|
+
expect(pins).toEqual(APIData.rows.map(metadataName));
|
|
170
|
+
|
|
171
|
+
expect(pins).toHaveLength(APIData.rows.length);
|
|
172
|
+
expect(axios.get).toHaveBeenNthCalledWith(
|
|
173
|
+
1,
|
|
174
|
+
pinListAxiosMockPages.firstPage.url,
|
|
175
|
+
pinListAxiosMockPages.firstPage.headers
|
|
176
|
+
);
|
|
177
|
+
expect(axios.get).toHaveBeenNthCalledWith(
|
|
178
|
+
2,
|
|
179
|
+
pinListAxiosMockPages.secondPage.url,
|
|
180
|
+
pinListAxiosMockPages.secondPage.headers
|
|
181
|
+
);
|
|
182
|
+
expect(axios.get).toHaveBeenNthCalledWith(
|
|
183
|
+
3,
|
|
184
|
+
pinListAxiosMockPages.thirdPageEmpty.url,
|
|
185
|
+
pinListAxiosMockPages.thirdPageEmpty.headers
|
|
186
|
+
);
|
|
187
|
+
|
|
188
|
+
expect(axios.get).toHaveBeenCalledTimes(3);
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
test("Request all pins, pins not available", async () => {
|
|
192
|
+
axios.get.mockResolvedValueOnce(
|
|
193
|
+
pinListAxiosMockPages.firstPageEmpty.response
|
|
194
|
+
);
|
|
195
|
+
const pins = await callIterableObject(
|
|
196
|
+
pinataConfig,
|
|
197
|
+
filterToApply
|
|
198
|
+
);
|
|
199
|
+
|
|
200
|
+
expect(pins).toEqual([]);
|
|
201
|
+
|
|
202
|
+
expect(pins).toHaveLength(0);
|
|
203
|
+
expect(axios.get).toHaveBeenNthCalledWith(
|
|
204
|
+
1,
|
|
205
|
+
pinListAxiosMockPages.firstPageEmpty.url,
|
|
206
|
+
pinListAxiosMockPages.firstPageEmpty.headers
|
|
207
|
+
);
|
|
208
|
+
|
|
209
|
+
expect(axios.get).toHaveBeenCalledTimes(1);
|
|
210
|
+
});
|
|
211
|
+
});
|
|
@@ -1,29 +1,103 @@
|
|
|
1
|
-
import axios from
|
|
2
|
-
import pinList from
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
status: 700
|
|
9
|
-
};
|
|
10
|
-
axios.get.mockResolvedValue(badStatus);
|
|
11
|
-
expect.assertions(1);
|
|
12
|
-
expect(pinList('test', 'test')).rejects.toEqual(Error(`unknown server response while attempting to retrieve user pin list: ${badStatus}`));
|
|
13
|
-
});
|
|
1
|
+
import axios from "axios";
|
|
2
|
+
import pinList from "./../../../../src/commands/data/pinList/pinList";
|
|
3
|
+
import {
|
|
4
|
+
APIData,
|
|
5
|
+
pinListAxiosMockPages,
|
|
6
|
+
fakeHeaders,
|
|
7
|
+
} from "../pinlist-sample-api";
|
|
14
8
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
9
|
+
jest.mock("axios");
|
|
10
|
+
|
|
11
|
+
describe("Get Files By Count", () => {
|
|
12
|
+
afterEach(() => {
|
|
13
|
+
jest.resetAllMocks();
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
test("Call two pages in a row", async () => {
|
|
17
|
+
axios.get
|
|
18
|
+
.mockResolvedValueOnce(pinListAxiosMockPages.firstPage.response)
|
|
19
|
+
.mockResolvedValueOnce(pinListAxiosMockPages.secondPage.response);
|
|
20
|
+
|
|
21
|
+
const resp = await pinList(
|
|
22
|
+
{
|
|
23
|
+
pinataApiKey: fakeHeaders.headers.pinata_api_key,
|
|
24
|
+
pinataSecretApiKey: fakeHeaders.headers.pinata_secret_api_key,
|
|
25
|
+
},
|
|
26
|
+
{ pageLimit: 10, pageOffset: 0 }
|
|
27
|
+
);
|
|
28
|
+
const resp2 = await pinList(
|
|
29
|
+
{
|
|
30
|
+
pinataApiKey: fakeHeaders.headers.pinata_api_key,
|
|
31
|
+
pinataSecretApiKey: fakeHeaders.headers.pinata_secret_api_key,
|
|
32
|
+
},
|
|
33
|
+
{ pageLimit: 10, pageOffset: 10 }
|
|
34
|
+
);
|
|
35
|
+
expect(resp).toEqual(pinListAxiosMockPages.firstPage.response.data);
|
|
36
|
+
expect(resp2).toEqual(pinListAxiosMockPages.secondPage.response.data);
|
|
37
|
+
|
|
38
|
+
expect(axios.get).toHaveBeenNthCalledWith(
|
|
39
|
+
1,
|
|
40
|
+
pinListAxiosMockPages.firstPage.url,
|
|
41
|
+
pinListAxiosMockPages.firstPage.headers
|
|
42
|
+
);
|
|
43
|
+
expect(axios.get).toHaveBeenNthCalledWith(
|
|
44
|
+
2,
|
|
45
|
+
pinListAxiosMockPages.secondPage.url,
|
|
46
|
+
pinListAxiosMockPages.secondPage.headers
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
expect(axios.get).toHaveBeenCalledTimes(2);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
test("Call empty page", async () => {
|
|
53
|
+
axios.get.mockResolvedValueOnce(
|
|
54
|
+
pinListAxiosMockPages.firstPageEmpty.response
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
const resp = await pinList(
|
|
58
|
+
{
|
|
59
|
+
pinataApiKey: fakeHeaders.headers.pinata_api_key,
|
|
60
|
+
pinataSecretApiKey: fakeHeaders.headers.pinata_secret_api_key,
|
|
61
|
+
},
|
|
62
|
+
{ pageLimit: 10, pageOffset: 0 }
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
expect(resp).toEqual({ rows: [] });
|
|
66
|
+
|
|
67
|
+
expect(axios.get).toHaveBeenNthCalledWith(
|
|
68
|
+
1,
|
|
69
|
+
pinListAxiosMockPages.firstPageEmpty.url,
|
|
70
|
+
pinListAxiosMockPages.firstPageEmpty.headers
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
expect(axios.get).toHaveBeenCalledTimes(1);
|
|
74
|
+
});
|
|
75
|
+
test("Result other than 200 status is returned", () => {
|
|
76
|
+
const badStatus = {
|
|
77
|
+
status: 700,
|
|
78
|
+
};
|
|
79
|
+
axios.get.mockResolvedValue(badStatus);
|
|
80
|
+
expect.assertions(1);
|
|
81
|
+
expect(pinList({ pinataApiKey: 'test', pinataSecretApiKey: 'test' })).rejects.toEqual(
|
|
82
|
+
Error(
|
|
83
|
+
`unknown server response while attempting to retrieve user pin list: ${badStatus}`
|
|
84
|
+
)
|
|
85
|
+
);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
test("200 status is returned", () => {
|
|
89
|
+
const goodStatus = {
|
|
90
|
+
status: 200,
|
|
91
|
+
data: "testData",
|
|
92
|
+
};
|
|
93
|
+
axios.get.mockResolvedValue(goodStatus);
|
|
94
|
+
expect.assertions(1);
|
|
95
|
+
expect(pinList({ pinataApiKey: 'test', pinataSecretApiKey: 'test' })).resolves.toEqual(goodStatus.data);
|
|
96
|
+
});
|
|
24
97
|
|
|
25
|
-
test(
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
98
|
+
test("Rejection handled", () => {
|
|
99
|
+
axios.get.mockRejectedValue("test error");
|
|
100
|
+
expect.assertions(1);
|
|
101
|
+
expect(pinList({ pinataApiKey: 'test', pinataSecretApiKey: 'test' })).rejects.toEqual("test error");
|
|
102
|
+
});
|
|
29
103
|
});
|