rmapi-js 5.0.0 → 6.0.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 +32 -90
- package/dist/index.d.ts +101 -514
- package/dist/index.js +159 -706
- package/dist/rmapi-js.esm.min.js +1 -1
- package/package.json +14 -15
- package/dist/index.spec.d.ts +0 -1
- package/dist/index.spec.js +0 -800
- package/dist/test-utils.d.ts +0 -22
- package/dist/test-utils.js +0 -71
- package/dist/utils.d.ts +0 -6
- package/dist/utils.js +0 -22
- package/dist/utils.spec.d.ts +0 -1
- package/dist/utils.spec.js +0 -21
- package/dist/validate.d.ts +0 -3
- package/dist/validate.js +0 -8
- package/dist/validate.spec.d.ts +0 -1
- package/dist/validate.spec.js +0 -15
package/dist/index.spec.js
DELETED
|
@@ -1,800 +0,0 @@
|
|
|
1
|
-
import { describe, expect, test } from "bun:test";
|
|
2
|
-
import { GenerationError, ResponseError, register, remarkable, } from ".";
|
|
3
|
-
import { MockResponse, createMockFetch, resolveTo } from "./test-utils";
|
|
4
|
-
// make sure we can't use fetch
|
|
5
|
-
global.fetch = undefined;
|
|
6
|
-
const TIMESTAMP = "1985-04-12T23:20:50.52Z";
|
|
7
|
-
const GET_URL = JSON.stringify({
|
|
8
|
-
url: "get url",
|
|
9
|
-
method: "GET",
|
|
10
|
-
relative_path: "get path",
|
|
11
|
-
expires: TIMESTAMP,
|
|
12
|
-
});
|
|
13
|
-
const PUT_URL = JSON.stringify({
|
|
14
|
-
url: "put url",
|
|
15
|
-
method: "PUT",
|
|
16
|
-
relative_path: "put path",
|
|
17
|
-
expires: TIMESTAMP,
|
|
18
|
-
});
|
|
19
|
-
const PUT_URL_BYTES = JSON.stringify({
|
|
20
|
-
url: "put url",
|
|
21
|
-
method: "PUT",
|
|
22
|
-
relative_path: "put path",
|
|
23
|
-
expires: TIMESTAMP,
|
|
24
|
-
maxuploadsize_bytes: 1000000,
|
|
25
|
-
});
|
|
26
|
-
const PUT_COLLECTION_RESPONSES = [
|
|
27
|
-
// metadata
|
|
28
|
-
new MockResponse(PUT_URL),
|
|
29
|
-
new MockResponse(),
|
|
30
|
-
// content
|
|
31
|
-
new MockResponse(PUT_URL),
|
|
32
|
-
new MockResponse(),
|
|
33
|
-
// collection
|
|
34
|
-
new MockResponse(PUT_URL),
|
|
35
|
-
new MockResponse(),
|
|
36
|
-
];
|
|
37
|
-
const PUT_FILE_RESPONSES = [
|
|
38
|
-
// doc
|
|
39
|
-
new MockResponse(PUT_URL_BYTES),
|
|
40
|
-
new MockResponse(),
|
|
41
|
-
// rest
|
|
42
|
-
...PUT_COLLECTION_RESPONSES,
|
|
43
|
-
];
|
|
44
|
-
function encode(input) {
|
|
45
|
-
const encoder = new TextEncoder();
|
|
46
|
-
return encoder.encode(input).buffer;
|
|
47
|
-
}
|
|
48
|
-
describe("register()", () => {
|
|
49
|
-
test("success", async () => {
|
|
50
|
-
const fetch = createMockFetch(new MockResponse("custom device token"));
|
|
51
|
-
const token = await register("academic", { fetch });
|
|
52
|
-
expect(token).toBe("custom device token");
|
|
53
|
-
expect(fetch.pastRequests.length).toBe(1);
|
|
54
|
-
const [first] = fetch.pastRequests;
|
|
55
|
-
expect(first).toBeDefined();
|
|
56
|
-
});
|
|
57
|
-
test("invalid", async () => {
|
|
58
|
-
const fetch = createMockFetch();
|
|
59
|
-
// eslint-disable-next-line @typescript-eslint/await-thenable
|
|
60
|
-
await expect(register("", { fetch })).rejects.toThrow("code should be length 8, but was 0");
|
|
61
|
-
});
|
|
62
|
-
test("error", async () => {
|
|
63
|
-
const fetch = createMockFetch(new MockResponse("", 400, "custom error"));
|
|
64
|
-
// eslint-disable-next-line @typescript-eslint/await-thenable
|
|
65
|
-
await expect(register("academic", { fetch })).rejects.toThrow("couldn't register api");
|
|
66
|
-
});
|
|
67
|
-
test("default", async () => {
|
|
68
|
-
// can call with default syntax, even though this instance will fail
|
|
69
|
-
// eslint-disable-next-line @typescript-eslint/await-thenable
|
|
70
|
-
await expect(register("academic")).rejects.toThrow("fetch is not a function");
|
|
71
|
-
});
|
|
72
|
-
});
|
|
73
|
-
describe("remarkable", () => {
|
|
74
|
-
describe("remarkable()", () => {
|
|
75
|
-
test("success", async () => {
|
|
76
|
-
const fetch = createMockFetch(new MockResponse("custom user token"));
|
|
77
|
-
await remarkable("custom device token", { fetch });
|
|
78
|
-
expect(fetch.pastRequests.length).toBe(1);
|
|
79
|
-
const [first] = fetch.pastRequests;
|
|
80
|
-
expect(first?.headers?.["Authorization"]).toBe("Bearer custom device token");
|
|
81
|
-
});
|
|
82
|
-
test("error", async () => {
|
|
83
|
-
const fetch = createMockFetch(new MockResponse("", 400));
|
|
84
|
-
// eslint-disable-next-line @typescript-eslint/await-thenable
|
|
85
|
-
await expect(remarkable("", { fetch })).rejects.toThrow("couldn't fetch auth token");
|
|
86
|
-
});
|
|
87
|
-
test("subtle error", async () => {
|
|
88
|
-
const fetch = createMockFetch(new MockResponse("", 400));
|
|
89
|
-
// eslint-disable-next-line @typescript-eslint/await-thenable
|
|
90
|
-
await expect(remarkable("", { fetch, subtle: null })).rejects.toThrow("subtle was missing");
|
|
91
|
-
});
|
|
92
|
-
test("default", async () => {
|
|
93
|
-
// eslint-disable-next-line @typescript-eslint/await-thenable
|
|
94
|
-
await expect(remarkable("")).rejects.toThrow("fetch is not a function");
|
|
95
|
-
});
|
|
96
|
-
});
|
|
97
|
-
describe("#authedFetch()", () => {
|
|
98
|
-
test("error", async () => {
|
|
99
|
-
const fetch = createMockFetch(new MockResponse(), new MockResponse("", 400));
|
|
100
|
-
const api = await remarkable("", { fetch });
|
|
101
|
-
// eslint-disable-next-line @typescript-eslint/await-thenable
|
|
102
|
-
await expect(api.getRootHash()).rejects.toThrow("failed reMarkable request");
|
|
103
|
-
});
|
|
104
|
-
});
|
|
105
|
-
describe("#getRootHash()", () => {
|
|
106
|
-
test("success", async () => {
|
|
107
|
-
const fetch = createMockFetch(new MockResponse(), new MockResponse(GET_URL), new MockResponse("custom hash", 200, "", {
|
|
108
|
-
"x-goog-generation": "123",
|
|
109
|
-
}), new MockResponse(GET_URL), new MockResponse("new hash", 200, "", { "x-goog-generation": "124" }));
|
|
110
|
-
const api = await remarkable("", { fetch });
|
|
111
|
-
const [hash, gen] = await api.getRootHash();
|
|
112
|
-
expect(hash).toBe("custom hash");
|
|
113
|
-
expect(gen).toBe(123n);
|
|
114
|
-
// cached
|
|
115
|
-
const [chash, cgen] = await api.getRootHash();
|
|
116
|
-
expect(chash).toBe("custom hash");
|
|
117
|
-
expect(cgen).toBe(123n);
|
|
118
|
-
// not cached
|
|
119
|
-
const [shash, sgen] = await api.getRootHash({ cache: false });
|
|
120
|
-
expect(shash).toBe("new hash");
|
|
121
|
-
expect(sgen).toBe(124n);
|
|
122
|
-
});
|
|
123
|
-
test("no generation", async () => {
|
|
124
|
-
const fetch = createMockFetch(new MockResponse(), new MockResponse(GET_URL), new MockResponse("custom hash"));
|
|
125
|
-
const api = await remarkable("", { fetch });
|
|
126
|
-
// eslint-disable-next-line @typescript-eslint/await-thenable
|
|
127
|
-
await expect(api.getRootHash()).rejects.toThrow("no generation header");
|
|
128
|
-
});
|
|
129
|
-
test("triple cache", async () => {
|
|
130
|
-
// this should only make two requests, even though the first fails
|
|
131
|
-
const [failedGet, send] = resolveTo(new MockResponse("err", 500));
|
|
132
|
-
const fetch = createMockFetch(new MockResponse(), failedGet, new MockResponse(GET_URL), new MockResponse("custom hash", 200, "", {
|
|
133
|
-
"x-goog-generation": "123",
|
|
134
|
-
}));
|
|
135
|
-
const api = await remarkable("", { fetch });
|
|
136
|
-
const first = api.getRootHash(); // fails
|
|
137
|
-
const second = api.getRootHash(); // succeeds
|
|
138
|
-
const third = api.getRootHash(); // cached
|
|
139
|
-
send(); // resolve first others waiting
|
|
140
|
-
// eslint-disable-next-line @typescript-eslint/await-thenable
|
|
141
|
-
await expect(first).rejects.toThrow("failed reMarkable request: err");
|
|
142
|
-
const [shash, sgen] = await second;
|
|
143
|
-
expect(shash).toBe("custom hash");
|
|
144
|
-
expect(sgen).toBe(123n);
|
|
145
|
-
const [thash, tgen] = await third;
|
|
146
|
-
expect(thash).toBe("custom hash");
|
|
147
|
-
expect(tgen).toBe(123n);
|
|
148
|
-
});
|
|
149
|
-
});
|
|
150
|
-
describe("#signedFetch()", () => {
|
|
151
|
-
test("error", async () => {
|
|
152
|
-
const fetch = createMockFetch(new MockResponse(), new MockResponse(GET_URL), new MockResponse("custom error", 400, "bad request"));
|
|
153
|
-
const api = await remarkable("", { fetch });
|
|
154
|
-
// eslint-disable-next-line @typescript-eslint/await-thenable
|
|
155
|
-
await expect(api.getRootHash()).rejects.toThrow("custom error");
|
|
156
|
-
});
|
|
157
|
-
});
|
|
158
|
-
describe("#getUrl()", () => {
|
|
159
|
-
test("error", async () => {
|
|
160
|
-
const fetch = createMockFetch(new MockResponse(), new MockResponse("{}"));
|
|
161
|
-
const api = await remarkable("", { fetch });
|
|
162
|
-
// eslint-disable-next-line @typescript-eslint/await-thenable
|
|
163
|
-
await expect(api.getRootHash()).rejects.toThrow("couldn't validate schema:");
|
|
164
|
-
});
|
|
165
|
-
});
|
|
166
|
-
describe("#putRootHash()", () => {
|
|
167
|
-
test("success", async () => {
|
|
168
|
-
const fetch = createMockFetch(new MockResponse(), new MockResponse(PUT_URL), new MockResponse("custom hash", 200, "", {
|
|
169
|
-
"x-goog-generation": "123",
|
|
170
|
-
}));
|
|
171
|
-
const api = await remarkable("", { fetch });
|
|
172
|
-
const gen = await api.putRootHash("new hash", 0n);
|
|
173
|
-
expect(gen).toBe(123n);
|
|
174
|
-
});
|
|
175
|
-
test("http error", async () => {
|
|
176
|
-
const fetch = createMockFetch(new MockResponse(), new MockResponse(PUT_URL), new MockResponse("custom hash", 400));
|
|
177
|
-
const api = await remarkable("", { fetch });
|
|
178
|
-
// eslint-disable-next-line @typescript-eslint/await-thenable
|
|
179
|
-
await expect(api.putRootHash("", 0n)).rejects.toThrow(ResponseError);
|
|
180
|
-
});
|
|
181
|
-
test("generation error", async () => {
|
|
182
|
-
const fetch = createMockFetch(new MockResponse(), new MockResponse(PUT_URL), new MockResponse("custom hash", 412));
|
|
183
|
-
const api = await remarkable("", { fetch });
|
|
184
|
-
// eslint-disable-next-line @typescript-eslint/await-thenable
|
|
185
|
-
await expect(api.putRootHash("", 0n)).rejects.toThrow(GenerationError);
|
|
186
|
-
});
|
|
187
|
-
test("no generation", async () => {
|
|
188
|
-
const fetch = createMockFetch(new MockResponse(), new MockResponse(PUT_URL), new MockResponse("custom hash"));
|
|
189
|
-
const api = await remarkable("", { fetch });
|
|
190
|
-
// eslint-disable-next-line @typescript-eslint/await-thenable
|
|
191
|
-
await expect(api.putRootHash("", 0n)).rejects.toThrow("no generation header");
|
|
192
|
-
});
|
|
193
|
-
});
|
|
194
|
-
describe("#getText()", () => {
|
|
195
|
-
test("default", async () => {
|
|
196
|
-
const fetch = createMockFetch(new MockResponse(), new MockResponse(GET_URL), new MockResponse("custom text"), new MockResponse(GET_URL), new MockResponse("different text"));
|
|
197
|
-
const api = await remarkable("", { fetch, cacheLimitBytes: 0 });
|
|
198
|
-
const first = await api.getText("hash");
|
|
199
|
-
expect(first).toBe("custom text");
|
|
200
|
-
// no cache
|
|
201
|
-
const second = await api.getText("hash");
|
|
202
|
-
expect(second).toBe("different text");
|
|
203
|
-
});
|
|
204
|
-
test("cached", async () => {
|
|
205
|
-
const fetch = createMockFetch(new MockResponse(), new MockResponse(GET_URL), new MockResponse("custom text"), new MockResponse(GET_URL), new MockResponse("different text"));
|
|
206
|
-
const api = await remarkable("", { fetch });
|
|
207
|
-
const first = await api.getText("hash");
|
|
208
|
-
expect(first).toBe("custom text");
|
|
209
|
-
// cache, no requests
|
|
210
|
-
const second = await api.getText("hash");
|
|
211
|
-
expect(second).toBe("custom text");
|
|
212
|
-
// different key
|
|
213
|
-
const third = await api.getText("new hash");
|
|
214
|
-
expect(third).toBe("different text");
|
|
215
|
-
});
|
|
216
|
-
test("triple cache", async () => {
|
|
217
|
-
// this tests that three simultaneous requests with a failure has the
|
|
218
|
-
// appropriate behavior
|
|
219
|
-
const [failedGet, send] = resolveTo(new MockResponse("err", 500));
|
|
220
|
-
const fetch = createMockFetch(new MockResponse(), failedGet, new MockResponse(GET_URL), new MockResponse("custom text"));
|
|
221
|
-
const api = await remarkable("", { fetch });
|
|
222
|
-
const first = api.getText("hash"); // error
|
|
223
|
-
const second = api.getText("hash"); // succeed
|
|
224
|
-
const third = api.getText("hash"); // cache
|
|
225
|
-
send(); // finish first request
|
|
226
|
-
// eslint-disable-next-line @typescript-eslint/await-thenable
|
|
227
|
-
await expect(first).rejects.toThrow("failed reMarkable request: err");
|
|
228
|
-
// eslint-disable-next-line @typescript-eslint/await-thenable
|
|
229
|
-
await expect(second).resolves.toBe("custom text");
|
|
230
|
-
// eslint-disable-next-line @typescript-eslint/await-thenable
|
|
231
|
-
await expect(third).resolves.toBe("custom text");
|
|
232
|
-
});
|
|
233
|
-
});
|
|
234
|
-
describe("#getBuffer()", () => {
|
|
235
|
-
test("success", async () => {
|
|
236
|
-
const fetch = createMockFetch(new MockResponse(), new MockResponse(GET_URL), new MockResponse("custom text"));
|
|
237
|
-
const api = await remarkable("", { fetch });
|
|
238
|
-
const first = await api.getBuffer("hash");
|
|
239
|
-
const dec = new TextDecoder();
|
|
240
|
-
expect(dec.decode(first)).toBe("custom text");
|
|
241
|
-
});
|
|
242
|
-
test("no cache", async () => {
|
|
243
|
-
const dec = new TextDecoder();
|
|
244
|
-
const fetch = createMockFetch(new MockResponse(), new MockResponse(GET_URL), new MockResponse("custom text"), new MockResponse(GET_URL), new MockResponse("other text"));
|
|
245
|
-
const api = await remarkable("", { fetch, cacheLimitBytes: 0 });
|
|
246
|
-
const first = await api.getBuffer("hash");
|
|
247
|
-
expect(dec.decode(first)).toBe("custom text");
|
|
248
|
-
const second = await api.getBuffer("hash");
|
|
249
|
-
expect(dec.decode(second)).toBe("other text");
|
|
250
|
-
});
|
|
251
|
-
});
|
|
252
|
-
describe("#getMetadata()", () => {
|
|
253
|
-
test("success", async () => {
|
|
254
|
-
const fetch = createMockFetch(new MockResponse(), new MockResponse(GET_URL), new MockResponse(JSON.stringify({
|
|
255
|
-
type: "CollectionType",
|
|
256
|
-
visibleName: "title",
|
|
257
|
-
parent: "",
|
|
258
|
-
lastModified: TIMESTAMP,
|
|
259
|
-
version: 1,
|
|
260
|
-
synced: true,
|
|
261
|
-
})));
|
|
262
|
-
const api = await remarkable("", { fetch });
|
|
263
|
-
const meta = await api.getMetadata("hash");
|
|
264
|
-
expect(meta.visibleName).toBe("title");
|
|
265
|
-
});
|
|
266
|
-
test("issue #5", async () => {
|
|
267
|
-
const fetch = createMockFetch(new MockResponse(), new MockResponse(GET_URL), new MockResponse(JSON.stringify({
|
|
268
|
-
createdTime: "0",
|
|
269
|
-
lastModified: "1699795915954",
|
|
270
|
-
lastOpened: "1699795889468",
|
|
271
|
-
lastOpenedPage: 227,
|
|
272
|
-
// eslint-disable-next-line spellcheck/spell-checker
|
|
273
|
-
parent: "44b07ec7-8bd1-43a3-a1ba-cd32f3222585",
|
|
274
|
-
pinned: false,
|
|
275
|
-
type: "DocumentType",
|
|
276
|
-
visibleName: "Document",
|
|
277
|
-
})));
|
|
278
|
-
const api = await remarkable("", { fetch });
|
|
279
|
-
const meta = await api.getMetadata("hash");
|
|
280
|
-
expect(meta.visibleName).toBe("Document");
|
|
281
|
-
});
|
|
282
|
-
test("failure", async () => {
|
|
283
|
-
const fetch = createMockFetch(new MockResponse(), new MockResponse(GET_URL), new MockResponse(JSON.stringify({
|
|
284
|
-
type: "CollectionType",
|
|
285
|
-
})));
|
|
286
|
-
const api = await remarkable("", { fetch });
|
|
287
|
-
// eslint-disable-next-line @typescript-eslint/await-thenable
|
|
288
|
-
await expect(api.getMetadata("hash")).rejects.toThrow("couldn't validate schema");
|
|
289
|
-
});
|
|
290
|
-
});
|
|
291
|
-
describe("#getEntries()", () => {
|
|
292
|
-
test("success", async () => {
|
|
293
|
-
const fetch = createMockFetch(new MockResponse(), new MockResponse(GET_URL), new MockResponse("3\n" + "hash:0:id:0:1234\n" + "other_hash:80000000:other_id:4:0\n"));
|
|
294
|
-
const api = await remarkable("", { fetch });
|
|
295
|
-
const [first, second] = await api.getEntries("");
|
|
296
|
-
expect(first?.hash).toBe("hash");
|
|
297
|
-
expect(first?.documentId).toBe("id");
|
|
298
|
-
expect(first?.size).toBe(1234n);
|
|
299
|
-
expect(second?.hash).toBe("other_hash");
|
|
300
|
-
expect(second?.documentId).toBe("other_id");
|
|
301
|
-
expect(second?.subfiles).toBe(4);
|
|
302
|
-
});
|
|
303
|
-
test("root", async () => {
|
|
304
|
-
const fetch = createMockFetch(new MockResponse(), new MockResponse(GET_URL), new MockResponse("root hash", 200, "", {
|
|
305
|
-
"x-goog-generation": "123",
|
|
306
|
-
}), new MockResponse(GET_URL), new MockResponse("3\n" + "hash:0:id:0:1234\n" + "other_hash:80000000:other_id:4:0\n"));
|
|
307
|
-
const api = await remarkable("", { fetch });
|
|
308
|
-
const [first, second] = await api.getEntries();
|
|
309
|
-
expect(first?.hash).toBe("hash");
|
|
310
|
-
expect(first?.documentId).toBe("id");
|
|
311
|
-
expect(first?.size).toBe(1234n);
|
|
312
|
-
expect(second?.hash).toBe("other_hash");
|
|
313
|
-
expect(second?.documentId).toBe("other_id");
|
|
314
|
-
expect(second?.subfiles).toBe(4);
|
|
315
|
-
const [, , , req] = fetch.pastRequests;
|
|
316
|
-
expect(JSON.parse(req?.bodyText ?? "")
|
|
317
|
-
.relative_path).toBe("root hash");
|
|
318
|
-
});
|
|
319
|
-
test("invalid format", async () => {
|
|
320
|
-
const fetch = createMockFetch(new MockResponse(), new MockResponse(GET_URL), new MockResponse("3\nhash:0:id:0\n"));
|
|
321
|
-
const api = await remarkable("", { fetch });
|
|
322
|
-
// eslint-disable-next-line @typescript-eslint/await-thenable
|
|
323
|
-
await expect(api.getEntries("")).rejects.toThrow("didn't contain five fields");
|
|
324
|
-
});
|
|
325
|
-
test("invalid document", async () => {
|
|
326
|
-
const fetch = createMockFetch(new MockResponse(), new MockResponse(GET_URL), new MockResponse("3\nhash:0:id:3:2\n"));
|
|
327
|
-
const api = await remarkable("", { fetch });
|
|
328
|
-
// eslint-disable-next-line @typescript-eslint/await-thenable
|
|
329
|
-
await expect(api.getEntries("")).rejects.toThrow("file type entry had nonzero number of subfiles: 3");
|
|
330
|
-
});
|
|
331
|
-
test("invalid type", async () => {
|
|
332
|
-
const fetch = createMockFetch(new MockResponse(), new MockResponse(GET_URL), new MockResponse("3\nhash:1:id:3:2\n"));
|
|
333
|
-
const api = await remarkable("", { fetch });
|
|
334
|
-
// eslint-disable-next-line @typescript-eslint/await-thenable
|
|
335
|
-
await expect(api.getEntries("")).rejects.toThrow("contained invalid type: 1");
|
|
336
|
-
});
|
|
337
|
-
test("invalid schema", async () => {
|
|
338
|
-
const fetch = createMockFetch(new MockResponse(), new MockResponse(GET_URL), new MockResponse("4\nhash:1:id:3:2\n"));
|
|
339
|
-
const api = await remarkable("", { fetch });
|
|
340
|
-
// eslint-disable-next-line @typescript-eslint/await-thenable
|
|
341
|
-
await expect(api.getEntries("")).rejects.toThrow("unexpected schema version: 4");
|
|
342
|
-
});
|
|
343
|
-
});
|
|
344
|
-
describe("#putEntries()", () => {
|
|
345
|
-
test("normal", async () => {
|
|
346
|
-
const fetch = createMockFetch(new MockResponse(), new MockResponse(PUT_URL), new MockResponse());
|
|
347
|
-
const api = await remarkable("", { fetch });
|
|
348
|
-
const entry = await api.putEntries("doc id", [
|
|
349
|
-
{
|
|
350
|
-
type: "0",
|
|
351
|
-
hash: "hash",
|
|
352
|
-
documentId: "id",
|
|
353
|
-
subfiles: 0,
|
|
354
|
-
size: 1234n,
|
|
355
|
-
},
|
|
356
|
-
]);
|
|
357
|
-
expect(entry.documentId).toBe("doc id");
|
|
358
|
-
expect(entry.subfiles).toBe(1);
|
|
359
|
-
const [, , req] = fetch.pastRequests;
|
|
360
|
-
expect(req?.url).toBe("put url");
|
|
361
|
-
expect(req?.bodyText).toBe("3\nhash:0:id:0:1234\n");
|
|
362
|
-
});
|
|
363
|
-
test("cached", async () => {
|
|
364
|
-
const fetch = createMockFetch(new MockResponse(), new MockResponse(PUT_URL), new MockResponse());
|
|
365
|
-
const api = await remarkable("", { fetch });
|
|
366
|
-
const entry = {
|
|
367
|
-
type: "0",
|
|
368
|
-
hash: "hash",
|
|
369
|
-
documentId: "id",
|
|
370
|
-
subfiles: 0,
|
|
371
|
-
size: 1234n,
|
|
372
|
-
};
|
|
373
|
-
const { hash } = await api.putEntries("doc id", [entry]);
|
|
374
|
-
const [cached] = await api.getEntries(hash);
|
|
375
|
-
expect(cached).toEqual(entry);
|
|
376
|
-
});
|
|
377
|
-
});
|
|
378
|
-
test("#putBuffer()", async () => {
|
|
379
|
-
const fetch = createMockFetch(new MockResponse(), new MockResponse(PUT_URL), new MockResponse());
|
|
380
|
-
const api = await remarkable("", { fetch });
|
|
381
|
-
const buffer = new Uint8Array([0, 2, 5, 9, 100, 255]);
|
|
382
|
-
const entry = await api.putBuffer("doc id", buffer.buffer);
|
|
383
|
-
expect(entry.documentId).toBe("doc id");
|
|
384
|
-
expect(entry.size).toBe(6n);
|
|
385
|
-
const [, , req] = fetch.pastRequests;
|
|
386
|
-
expect(req?.url).toBe("put url");
|
|
387
|
-
const sent = new Uint8Array(req?.body);
|
|
388
|
-
for (const [i, v] of buffer.entries()) {
|
|
389
|
-
expect(sent[i]).toBe(v);
|
|
390
|
-
}
|
|
391
|
-
});
|
|
392
|
-
describe("#putText()", () => {
|
|
393
|
-
test("normal", async () => {
|
|
394
|
-
const fetch = createMockFetch(new MockResponse(), new MockResponse(PUT_URL), new MockResponse());
|
|
395
|
-
const api = await remarkable("", { fetch });
|
|
396
|
-
const entry = await api.putText("doc id", "custom text");
|
|
397
|
-
expect(entry.documentId).toBe("doc id");
|
|
398
|
-
expect(entry.size).toBe(11n);
|
|
399
|
-
const [, , req] = fetch.pastRequests;
|
|
400
|
-
expect(req?.url).toBe("put url");
|
|
401
|
-
expect(req?.bodyText).toBe("custom text");
|
|
402
|
-
});
|
|
403
|
-
test("cached", async () => {
|
|
404
|
-
const fetch = createMockFetch(new MockResponse(), new MockResponse(PUT_URL), new MockResponse());
|
|
405
|
-
const api = await remarkable("", { fetch });
|
|
406
|
-
const { hash } = await api.putText("doc id", "custom text");
|
|
407
|
-
const cached = await api.getText(hash);
|
|
408
|
-
expect(cached).toBe("custom text");
|
|
409
|
-
});
|
|
410
|
-
test("no cache", async () => {
|
|
411
|
-
const fetch = createMockFetch(new MockResponse(), new MockResponse(PUT_URL), new MockResponse(), new MockResponse(GET_URL), new MockResponse("different text"));
|
|
412
|
-
const api = await remarkable("", { fetch, cacheLimitBytes: 0 });
|
|
413
|
-
const { hash } = await api.putText("doc id", "custom text");
|
|
414
|
-
const result = await api.getText(hash);
|
|
415
|
-
expect(result).toBe("different text");
|
|
416
|
-
});
|
|
417
|
-
test("cache failure", async () => {
|
|
418
|
-
const [failedPut, send] = resolveTo(new MockResponse("err", 500));
|
|
419
|
-
const fetch = createMockFetch(new MockResponse(), failedPut, new MockResponse(PUT_URL), new MockResponse());
|
|
420
|
-
const api = await remarkable("", { fetch });
|
|
421
|
-
const first = api.putText("doc id", "custom text"); // fail
|
|
422
|
-
const second = api.putText("doc id", "custom text"); // send
|
|
423
|
-
const third = api.putText("doc id", "custom text"); // cached
|
|
424
|
-
send();
|
|
425
|
-
// eslint-disable-next-line @typescript-eslint/await-thenable
|
|
426
|
-
await expect(first).rejects.toThrow("failed reMarkable request: err");
|
|
427
|
-
await second;
|
|
428
|
-
await third;
|
|
429
|
-
// second failed
|
|
430
|
-
expect(fetch.pastRequests).toHaveLength(4);
|
|
431
|
-
});
|
|
432
|
-
});
|
|
433
|
-
test("#putCollection()", async () => {
|
|
434
|
-
const fetch = createMockFetch(new MockResponse(), ...PUT_COLLECTION_RESPONSES);
|
|
435
|
-
const api = await remarkable("", { fetch });
|
|
436
|
-
await api.putCollection("New Folder");
|
|
437
|
-
const [, , , metadata, , content] = fetch.pastRequests;
|
|
438
|
-
expect(JSON.parse(metadata?.bodyText ?? "")).toBeDefined();
|
|
439
|
-
expect(JSON.parse(content?.bodyText ?? "")).toBeDefined();
|
|
440
|
-
});
|
|
441
|
-
describe("#putEpub()", () => {
|
|
442
|
-
test("success", async () => {
|
|
443
|
-
const fetch = createMockFetch(new MockResponse(), ...PUT_FILE_RESPONSES);
|
|
444
|
-
const epub = "fake epub content";
|
|
445
|
-
const api = await remarkable("", { fetch });
|
|
446
|
-
await api.putEpub("doc name", encode(epub));
|
|
447
|
-
const [, , doc, , metadata, , content, , collection] = fetch.pastRequests;
|
|
448
|
-
expect(doc?.bodyText).toBe(epub);
|
|
449
|
-
expect(JSON.parse(metadata?.bodyText ?? "")).toBeDefined();
|
|
450
|
-
expect(JSON.parse(content?.bodyText ?? "")).toBeDefined();
|
|
451
|
-
expect(collection?.bodyText).toMatch(/^3\n/);
|
|
452
|
-
});
|
|
453
|
-
test("custom", async () => {
|
|
454
|
-
const fetch = createMockFetch(new MockResponse(), ...PUT_FILE_RESPONSES);
|
|
455
|
-
const epub = "fake epub content";
|
|
456
|
-
const api = await remarkable("", { fetch });
|
|
457
|
-
await api.putEpub("doc name", encode(epub), {
|
|
458
|
-
cover: "first",
|
|
459
|
-
lineHeight: "lg",
|
|
460
|
-
margins: "rr",
|
|
461
|
-
textScale: "sm",
|
|
462
|
-
});
|
|
463
|
-
const [, , , , , , content] = fetch.pastRequests;
|
|
464
|
-
expect(JSON.parse(content?.bodyText ?? "").margins).toEqual(180);
|
|
465
|
-
});
|
|
466
|
-
});
|
|
467
|
-
describe("#putPdf()", () => {
|
|
468
|
-
test("success", async () => {
|
|
469
|
-
const fetch = createMockFetch(new MockResponse(), ...PUT_FILE_RESPONSES);
|
|
470
|
-
const pdf = "fake pdf content";
|
|
471
|
-
const api = await remarkable("", { fetch });
|
|
472
|
-
await api.putPdf("doc name", encode(pdf));
|
|
473
|
-
const [, , doc, , metadata, , content, , collection] = fetch.pastRequests;
|
|
474
|
-
expect(doc?.bodyText).toBe(pdf);
|
|
475
|
-
expect(JSON.parse(metadata?.bodyText ?? "")).toBeDefined();
|
|
476
|
-
expect(JSON.parse(content?.bodyText ?? "")).toBeDefined();
|
|
477
|
-
expect(collection?.bodyText).toMatch(/^3\n/);
|
|
478
|
-
});
|
|
479
|
-
test("custom", async () => {
|
|
480
|
-
const fetch = createMockFetch(new MockResponse(), ...PUT_FILE_RESPONSES);
|
|
481
|
-
const pdf = "fake pdf content";
|
|
482
|
-
const api = await remarkable("", { fetch });
|
|
483
|
-
await api.putPdf("doc name", encode(pdf), {
|
|
484
|
-
cover: "visited",
|
|
485
|
-
});
|
|
486
|
-
const [, , , , , , content] = fetch.pastRequests;
|
|
487
|
-
expect(JSON.parse(content?.bodyText ?? "")
|
|
488
|
-
.coverPageNumber).toEqual(-1);
|
|
489
|
-
});
|
|
490
|
-
});
|
|
491
|
-
test("#syncComplete()", async () => {
|
|
492
|
-
const fetch = createMockFetch(new MockResponse(), new MockResponse());
|
|
493
|
-
const api = await remarkable("", { fetch });
|
|
494
|
-
await api.syncComplete(0n);
|
|
495
|
-
const [, req] = fetch.pastRequests;
|
|
496
|
-
expect(req?.url).toBe("https://internal.cloud.remarkable.com/sync/v2/sync-complete");
|
|
497
|
-
expect(JSON.parse(req?.bodyText ?? "")).toEqual({ generation: 0 });
|
|
498
|
-
});
|
|
499
|
-
describe("#create()", () => {
|
|
500
|
-
const CREATE_RESPONSES = [
|
|
501
|
-
// root hash
|
|
502
|
-
new MockResponse(GET_URL),
|
|
503
|
-
new MockResponse("custom hash", 200, "", {
|
|
504
|
-
"x-goog-generation": "123",
|
|
505
|
-
}),
|
|
506
|
-
// entries
|
|
507
|
-
new MockResponse(GET_URL),
|
|
508
|
-
new MockResponse("3\n" + "hash:0:id:0:1234\n" + "other_hash:80000000:other_id:4:0\n"),
|
|
509
|
-
// put entries
|
|
510
|
-
new MockResponse(PUT_URL),
|
|
511
|
-
new MockResponse(),
|
|
512
|
-
// put root hash
|
|
513
|
-
new MockResponse(PUT_URL),
|
|
514
|
-
new MockResponse("custom hash", 200, "", {
|
|
515
|
-
"x-goog-generation": "124",
|
|
516
|
-
}),
|
|
517
|
-
];
|
|
518
|
-
test("sync", async () => {
|
|
519
|
-
const fetch = createMockFetch(new MockResponse(), ...CREATE_RESPONSES, new MockResponse());
|
|
520
|
-
const api = await remarkable("", { fetch });
|
|
521
|
-
const res = await api.create({
|
|
522
|
-
type: "80000000",
|
|
523
|
-
hash: "create hash",
|
|
524
|
-
documentId: "docid",
|
|
525
|
-
subfiles: 3,
|
|
526
|
-
size: 0n,
|
|
527
|
-
});
|
|
528
|
-
expect(res).toBe(true);
|
|
529
|
-
const [, , , , , , ents, , , sync] = fetch.pastRequests;
|
|
530
|
-
expect(ents?.bodyText).toEqual("3\n" +
|
|
531
|
-
"create hash:80000000:docid:3:0\n" +
|
|
532
|
-
"hash:0:id:0:1234\n" +
|
|
533
|
-
"other_hash:80000000:other_id:4:0\n");
|
|
534
|
-
expect(JSON.parse(sync?.bodyText ?? "")).toEqual({ generation: 124 });
|
|
535
|
-
});
|
|
536
|
-
test("sync failure", async () => {
|
|
537
|
-
const fetch = createMockFetch(new MockResponse(), ...CREATE_RESPONSES,
|
|
538
|
-
// sync failure
|
|
539
|
-
new MockResponse("", 400));
|
|
540
|
-
const api = await remarkable("", { fetch });
|
|
541
|
-
const res = await api.create({
|
|
542
|
-
type: "80000000",
|
|
543
|
-
hash: "create hash",
|
|
544
|
-
documentId: "docid",
|
|
545
|
-
subfiles: 3,
|
|
546
|
-
size: 0n,
|
|
547
|
-
});
|
|
548
|
-
expect(res).toBe(false);
|
|
549
|
-
const [, , , , , , ents, , , sync] = fetch.pastRequests;
|
|
550
|
-
expect(ents?.bodyText).toEqual("3\n" +
|
|
551
|
-
"create hash:80000000:docid:3:0\n" +
|
|
552
|
-
"hash:0:id:0:1234\n" +
|
|
553
|
-
"other_hash:80000000:other_id:4:0\n");
|
|
554
|
-
expect(sync).toBeDefined();
|
|
555
|
-
});
|
|
556
|
-
test("no sync", async () => {
|
|
557
|
-
const fetch = createMockFetch(new MockResponse(), ...CREATE_RESPONSES);
|
|
558
|
-
const api = await remarkable("", { fetch });
|
|
559
|
-
const res = await api.create({
|
|
560
|
-
type: "80000000",
|
|
561
|
-
hash: "create hash",
|
|
562
|
-
documentId: "docid",
|
|
563
|
-
subfiles: 3,
|
|
564
|
-
size: 0n,
|
|
565
|
-
}, { sync: false });
|
|
566
|
-
expect(res).toBe(false);
|
|
567
|
-
const [, , , , , , ents, , , sync] = fetch.pastRequests;
|
|
568
|
-
expect(ents?.bodyText).toEqual("3\n" +
|
|
569
|
-
"create hash:80000000:docid:3:0\n" +
|
|
570
|
-
"hash:0:id:0:1234\n" +
|
|
571
|
-
"other_hash:80000000:other_id:4:0\n");
|
|
572
|
-
expect(sync).toBeUndefined();
|
|
573
|
-
});
|
|
574
|
-
});
|
|
575
|
-
describe("#move()", () => {
|
|
576
|
-
const MOVE_INIT_RESPONSES = [
|
|
577
|
-
// root hash
|
|
578
|
-
new MockResponse(GET_URL),
|
|
579
|
-
new MockResponse("old root hash", 200, "", {
|
|
580
|
-
"x-goog-generation": "123",
|
|
581
|
-
}),
|
|
582
|
-
// entries
|
|
583
|
-
new MockResponse(GET_URL),
|
|
584
|
-
new MockResponse("3\n" + "hash:80000000:id:1:0\n" + "other_hash:80000000:other_id:4:0\n"),
|
|
585
|
-
];
|
|
586
|
-
const MOVE_DEST_RESPONSES = [
|
|
587
|
-
// dest entries
|
|
588
|
-
new MockResponse(GET_URL),
|
|
589
|
-
new MockResponse("3\n" + "other_meta_hash:0:other_id.metadata:0:1234\n"),
|
|
590
|
-
// dest metadata
|
|
591
|
-
new MockResponse(GET_URL),
|
|
592
|
-
new MockResponse(JSON.stringify({
|
|
593
|
-
type: "CollectionType",
|
|
594
|
-
visibleName: "title",
|
|
595
|
-
parent: "",
|
|
596
|
-
lastModified: TIMESTAMP,
|
|
597
|
-
version: 1,
|
|
598
|
-
synced: true,
|
|
599
|
-
})),
|
|
600
|
-
];
|
|
601
|
-
const MOVE_FINAL_RESPONSES = [
|
|
602
|
-
// doc entries
|
|
603
|
-
new MockResponse(GET_URL),
|
|
604
|
-
new MockResponse("3\n" +
|
|
605
|
-
"meta_hash:0:id.metadata:0:1234\n" +
|
|
606
|
-
"content_hash:0:id.content:0:1234\n"),
|
|
607
|
-
// doc metadata
|
|
608
|
-
new MockResponse(GET_URL),
|
|
609
|
-
new MockResponse(JSON.stringify({
|
|
610
|
-
type: "DocumentType",
|
|
611
|
-
visibleName: "movie",
|
|
612
|
-
parent: "",
|
|
613
|
-
lastModified: TIMESTAMP,
|
|
614
|
-
version: 1,
|
|
615
|
-
synced: true,
|
|
616
|
-
})),
|
|
617
|
-
// put metadata
|
|
618
|
-
new MockResponse(PUT_URL),
|
|
619
|
-
new MockResponse(),
|
|
620
|
-
// put entries
|
|
621
|
-
new MockResponse(PUT_URL),
|
|
622
|
-
new MockResponse(),
|
|
623
|
-
// put entries
|
|
624
|
-
new MockResponse(PUT_URL),
|
|
625
|
-
new MockResponse(),
|
|
626
|
-
// put root hash
|
|
627
|
-
new MockResponse(PUT_URL),
|
|
628
|
-
new MockResponse("next root hash", 200, "", {
|
|
629
|
-
"x-goog-generation": "124",
|
|
630
|
-
}),
|
|
631
|
-
];
|
|
632
|
-
test("sync", async () => {
|
|
633
|
-
const fetch = createMockFetch(new MockResponse(), ...MOVE_INIT_RESPONSES, ...MOVE_DEST_RESPONSES, ...MOVE_FINAL_RESPONSES, new MockResponse());
|
|
634
|
-
const api = await remarkable("", { fetch });
|
|
635
|
-
const res = await api.move("id", "other_id");
|
|
636
|
-
expect(res).toBe(true);
|
|
637
|
-
const [meta, , docEnts, , rootEnts, , , sync] = fetch.pastRequests.slice(14);
|
|
638
|
-
expect(JSON.parse(meta?.bodyText ?? "").parent).toEqual("other_id");
|
|
639
|
-
expect(docEnts?.bodyText).toBe("3\n" +
|
|
640
|
-
"content_hash:0:id.content:0:1234\n" +
|
|
641
|
-
"f48bde1d019ee87cecfcd8ce6b92ba3a65618d43246db2e71d56467ec7285211:0:id.metadata:0:132\n");
|
|
642
|
-
expect(rootEnts?.bodyText).toBe("3\n" +
|
|
643
|
-
"bd1cd5d8bbccec925ef5c76f1777b7daa149764bfa5f3f900fc1692ea3a28de2:80000000:id:2:0\n" +
|
|
644
|
-
"other_hash:80000000:other_id:4:0\n");
|
|
645
|
-
expect(JSON.parse(sync?.bodyText ?? "")).toEqual({ generation: 124 });
|
|
646
|
-
});
|
|
647
|
-
test("no sync trash", async () => {
|
|
648
|
-
const fetch = createMockFetch(new MockResponse(), ...MOVE_INIT_RESPONSES, ...MOVE_FINAL_RESPONSES);
|
|
649
|
-
const api = await remarkable("", { fetch });
|
|
650
|
-
const res = await api.move("id", "trash", { sync: false });
|
|
651
|
-
expect(res).toBe(false);
|
|
652
|
-
const [meta, , docEnts, , rootEnts, , , sync] = fetch.pastRequests.slice(10);
|
|
653
|
-
expect(JSON.parse(meta?.bodyText ?? "").parent).toEqual("trash");
|
|
654
|
-
expect(docEnts?.bodyText).toBe("3\n" +
|
|
655
|
-
"content_hash:0:id.content:0:1234\n" +
|
|
656
|
-
"a1d5afcc058c7f895fc9f99c6bc1e207312943ceca158493d68c5ea0b7f2bd65:0:id.metadata:0:129\n");
|
|
657
|
-
expect(rootEnts?.bodyText).toBe("3\n" +
|
|
658
|
-
"f55aa7bd69ac2a173bf6e8270a506e9470cfc2b606c5716f2de8cb1e16894952:80000000:id:2:0\n" +
|
|
659
|
-
"other_hash:80000000:other_id:4:0\n");
|
|
660
|
-
expect(sync).toBeUndefined();
|
|
661
|
-
});
|
|
662
|
-
test("throws with missing dest", async () => {
|
|
663
|
-
const fetch = createMockFetch(new MockResponse(), ...MOVE_INIT_RESPONSES);
|
|
664
|
-
const api = await remarkable("", { fetch });
|
|
665
|
-
const res = api.move("id", "missing", { sync: false });
|
|
666
|
-
// eslint-disable-next-line @typescript-eslint/await-thenable
|
|
667
|
-
await expect(res).rejects.toThrow("destination id not found: missing");
|
|
668
|
-
});
|
|
669
|
-
test("throws with wrong destination type", async () => {
|
|
670
|
-
const fetch = createMockFetch(new MockResponse(),
|
|
671
|
-
// root hash
|
|
672
|
-
new MockResponse(GET_URL), new MockResponse("custom hash", 200, "", {
|
|
673
|
-
"x-goog-generation": "123",
|
|
674
|
-
}),
|
|
675
|
-
// entries
|
|
676
|
-
new MockResponse(GET_URL), new MockResponse("3\n" + "hash:80000000:id:1:0\n" + "other_hash:0:other_id:0:4\n"));
|
|
677
|
-
const api = await remarkable("", { fetch });
|
|
678
|
-
const res = api.move("id", "other_id", { sync: false });
|
|
679
|
-
// eslint-disable-next-line @typescript-eslint/await-thenable
|
|
680
|
-
await expect(res).rejects.toThrow("destination id was a raw file: other_id");
|
|
681
|
-
});
|
|
682
|
-
test("throws with no dest metadata", async () => {
|
|
683
|
-
const fetch = createMockFetch(new MockResponse(), ...MOVE_INIT_RESPONSES,
|
|
684
|
-
// dest entries
|
|
685
|
-
new MockResponse(GET_URL), new MockResponse("3\n" + "hash:0:other_id.content:0:1234\n"));
|
|
686
|
-
const api = await remarkable("", { fetch });
|
|
687
|
-
const res = api.move("id", "other_id", { sync: false });
|
|
688
|
-
// eslint-disable-next-line @typescript-eslint/await-thenable
|
|
689
|
-
await expect(res).rejects.toThrow("destination id didn't have metadata: other_id");
|
|
690
|
-
});
|
|
691
|
-
test("throws with file destination", async () => {
|
|
692
|
-
const fetch = createMockFetch(new MockResponse(), ...MOVE_INIT_RESPONSES,
|
|
693
|
-
// dest entries
|
|
694
|
-
new MockResponse(GET_URL), new MockResponse("3\n" + "hash:0:other_id.metadata:0:1234\n"),
|
|
695
|
-
// dest metadata
|
|
696
|
-
new MockResponse(GET_URL), new MockResponse(JSON.stringify({
|
|
697
|
-
type: "DocumentType",
|
|
698
|
-
visibleName: "title",
|
|
699
|
-
parent: "",
|
|
700
|
-
lastModified: TIMESTAMP,
|
|
701
|
-
version: 1,
|
|
702
|
-
synced: true,
|
|
703
|
-
})));
|
|
704
|
-
const api = await remarkable("", { fetch });
|
|
705
|
-
const res = api.move("id", "other_id", { sync: false });
|
|
706
|
-
// eslint-disable-next-line @typescript-eslint/await-thenable
|
|
707
|
-
await expect(res).rejects.toThrow("destination id wasn't a collection: other_id");
|
|
708
|
-
});
|
|
709
|
-
test("throws with missing document", async () => {
|
|
710
|
-
const fetch = createMockFetch(new MockResponse(), ...MOVE_INIT_RESPONSES);
|
|
711
|
-
const api = await remarkable("", { fetch });
|
|
712
|
-
const res = api.move("missing", "");
|
|
713
|
-
// eslint-disable-next-line @typescript-eslint/await-thenable
|
|
714
|
-
await expect(res).rejects.toThrow("document not found: missing");
|
|
715
|
-
});
|
|
716
|
-
test("throws with non-collection document", async () => {
|
|
717
|
-
const fetch = createMockFetch(new MockResponse(),
|
|
718
|
-
// root hash
|
|
719
|
-
new MockResponse(GET_URL), new MockResponse("custom hash", 200, "", {
|
|
720
|
-
"x-goog-generation": "123",
|
|
721
|
-
}),
|
|
722
|
-
// entries
|
|
723
|
-
new MockResponse(GET_URL), new MockResponse("3\n" + "hash:80000000:id:1:0\n" + "other_hash:0:other_id:0:4\n"));
|
|
724
|
-
const api = await remarkable("", { fetch });
|
|
725
|
-
const res = api.move("other_id", "");
|
|
726
|
-
// eslint-disable-next-line @typescript-eslint/await-thenable
|
|
727
|
-
await expect(res).rejects.toThrow("document was a raw file: other_id");
|
|
728
|
-
});
|
|
729
|
-
test("throws with no document metadata", async () => {
|
|
730
|
-
const fetch = createMockFetch(new MockResponse(), ...MOVE_INIT_RESPONSES,
|
|
731
|
-
// doc entries
|
|
732
|
-
new MockResponse(GET_URL), new MockResponse("3\n" + "content_hash:0:id.content:0:1234\n"));
|
|
733
|
-
const api = await remarkable("", { fetch });
|
|
734
|
-
const res = api.move("id", "");
|
|
735
|
-
// eslint-disable-next-line @typescript-eslint/await-thenable
|
|
736
|
-
await expect(res).rejects.toThrow("document didn't have metadata: id");
|
|
737
|
-
});
|
|
738
|
-
});
|
|
739
|
-
test("#getEntriesMetadata()", async () => {
|
|
740
|
-
const entries = [
|
|
741
|
-
{
|
|
742
|
-
type: "CollectionType",
|
|
743
|
-
id: "id",
|
|
744
|
-
hash: "hash",
|
|
745
|
-
visibleName: "name",
|
|
746
|
-
},
|
|
747
|
-
];
|
|
748
|
-
const fetch = createMockFetch(new MockResponse(), new MockResponse(JSON.stringify(entries)));
|
|
749
|
-
const api = await remarkable("", { fetch });
|
|
750
|
-
const res = await api.getEntriesMetadata();
|
|
751
|
-
expect(res).toEqual(entries);
|
|
752
|
-
});
|
|
753
|
-
test("#uploadEpub()", async () => {
|
|
754
|
-
const fetch = createMockFetch(new MockResponse(), new MockResponse(JSON.stringify({ docID: "epub id", hash: "epub hash" })));
|
|
755
|
-
const api = await remarkable("", { fetch });
|
|
756
|
-
const content = "my epub content";
|
|
757
|
-
const res = await api.uploadEpub("my epub title", encode(content));
|
|
758
|
-
expect(res.docID).toBe("epub id");
|
|
759
|
-
expect(res.hash).toBe("epub hash");
|
|
760
|
-
const [, req] = fetch.pastRequests;
|
|
761
|
-
expect(req?.bodyText).toBe("my epub content");
|
|
762
|
-
});
|
|
763
|
-
test("#uploadPdf()", async () => {
|
|
764
|
-
const fetch = createMockFetch(new MockResponse(), new MockResponse(JSON.stringify({ docID: "pdf id", hash: "pdf hash" })));
|
|
765
|
-
const api = await remarkable("", { fetch });
|
|
766
|
-
const content = "my pdf content";
|
|
767
|
-
const res = await api.uploadPdf("my pdf title", encode(content));
|
|
768
|
-
expect(res.docID).toBe("pdf id");
|
|
769
|
-
expect(res.hash).toBe("pdf hash");
|
|
770
|
-
const [, req] = fetch.pastRequests;
|
|
771
|
-
expect(req?.bodyText).toBe("my pdf content");
|
|
772
|
-
});
|
|
773
|
-
test("#getCache()", async () => {
|
|
774
|
-
let initCache;
|
|
775
|
-
{
|
|
776
|
-
const [failedGet, send] = resolveTo(new MockResponse("err", 500));
|
|
777
|
-
const fetch = createMockFetch(new MockResponse(), new MockResponse(GET_URL), new MockResponse("text"), failedGet);
|
|
778
|
-
const api = await remarkable("", { fetch });
|
|
779
|
-
const first = await api.getText("hash");
|
|
780
|
-
expect(first).toBe("text");
|
|
781
|
-
// this will throw when we try to get the cache
|
|
782
|
-
const second = api.getText("other hash");
|
|
783
|
-
const cache = api.getCache();
|
|
784
|
-
send(); // failed request resolves
|
|
785
|
-
initCache = await cache;
|
|
786
|
-
// eslint-disable-next-line @typescript-eslint/await-thenable
|
|
787
|
-
await expect(second).rejects.toThrow("failed reMarkable request: err");
|
|
788
|
-
}
|
|
789
|
-
{
|
|
790
|
-
const fetch = createMockFetch(new MockResponse(), new MockResponse(GET_URL), new MockResponse("different"));
|
|
791
|
-
const api = await remarkable("", { fetch, initCache });
|
|
792
|
-
// still in cache
|
|
793
|
-
const first = await api.getText("hash");
|
|
794
|
-
expect(first).toBe("text");
|
|
795
|
-
// not in cache since request failed
|
|
796
|
-
const second = await api.getText("other hash");
|
|
797
|
-
expect(second).toBe("different");
|
|
798
|
-
}
|
|
799
|
-
});
|
|
800
|
-
});
|