Skip to content

Commit c10fda9

Browse files
committed
Add back assets utility class test
1 parent 0e18f50 commit c10fda9

File tree

2 files changed

+184
-0
lines changed

2 files changed

+184
-0
lines changed

.fernignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ src/api/types/OAuthScope.ts
88
src/index.ts
99
src/oauth.ts
1010
src/wrapper
11+
tests/wrapper
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
require('jest-fetch-mock').enableMocks();
2+
import { Client as AssetsUtilitiesClient } from "../../src/wrapper/AssetsUtilitiesClient";
3+
import * as Webflow from "../../src/api";
4+
import fetchMock from "jest-fetch-mock";
5+
import crypto from "crypto";
6+
import FormDataConstructor from 'form-data';
7+
8+
fetchMock.enableMocks();
9+
10+
describe("AssetsUtilitiesClient", () => {
11+
const mockOptions = {
12+
environment: () => ({
13+
base: "https://api.webflow.com/v2",
14+
dataApi: "https://api.webflow.com/v2",
15+
contentDeliveryApi: "https://api-cdn.webflow.com/v2",
16+
production: "https://api.webflow.com/v2",
17+
cdn: "https://api-cdn.webflow.com/v2",
18+
}),
19+
accessToken: () => "test-access-token",
20+
};
21+
22+
const siteId = "test-site-id";
23+
const mockUploadUrl = "https://mock-s3-upload-url.com";
24+
const mockFileName = "test-file.txt";
25+
const mockFileContent = "Hello, world!";
26+
const mockFileBuffer = Buffer.from(mockFileContent);
27+
const mockFileHash = crypto.createHash("md5").update(mockFileBuffer).digest("hex");
28+
29+
let client: AssetsUtilitiesClient;
30+
31+
beforeEach(() => {
32+
fetchMock.resetMocks();
33+
client = new AssetsUtilitiesClient(mockOptions);
34+
});
35+
36+
it("should throw an error if it cannot fetch the asset successfully", async () => {
37+
const invalidUrl = "https://invalid-url.com";
38+
39+
// Mock the fetch response to simulate a failure
40+
fetchMock.mockResponseOnce("", { status: 404, statusText: "Not Found" });
41+
42+
await expect(client["_getBufferFromUrl"](invalidUrl)).rejects.toThrow(
43+
"Failed to fetch asset from URL: https://invalid-url.com. Status: 404 Not Found"
44+
);
45+
46+
// Ensure fetch was called with the correct URL
47+
expect(fetchMock).toHaveBeenCalledWith(invalidUrl);
48+
});
49+
50+
it("should throw an error for invalid file input", async () => {
51+
await expect(client.createAndUpload(siteId, {
52+
fileName: mockFileName,
53+
file: null as unknown as ArrayBuffer, // Invalid file
54+
})).rejects.toThrow();
55+
});
56+
57+
it("should throw an error if it fails to create Webflow Asset metadata", async () => {
58+
// Mock the Webflow API to throw an error
59+
jest.spyOn(client, "create").mockRejectedValue(new Error("Webflow API error"));
60+
61+
await expect(client.createAndUpload(siteId, {
62+
fileName: mockFileName,
63+
file: mockFileBuffer.buffer, // Pass ArrayBuffer
64+
})).rejects.toThrow();
65+
66+
// Ensure the create method was called
67+
expect(client.create).toHaveBeenCalledWith(siteId, expect.objectContaining({
68+
fileName: mockFileName,
69+
fileHash: expect.any(String),
70+
}), undefined);
71+
});
72+
73+
it("should throw an error if it fails to upload to S3", async () => {
74+
// Mock the Webflow API response for creating asset metadata
75+
const mockCreateResponse = {
76+
uploadUrl: mockUploadUrl,
77+
uploadDetails: {
78+
"xAmzAlgorithm": "AWS4-HMAC-SHA256",
79+
"xAmzDate": "20231010T000000Z",
80+
"xAmzCredential": "mock-credential",
81+
"xAmzSignature": "mock-signature",
82+
"successActionStatus": "201",
83+
"contentType": "text/plain",
84+
},
85+
};
86+
jest.spyOn(client, "create").mockResolvedValue(mockCreateResponse as Webflow.AssetUpload);
87+
88+
// Mock the S3 upload response to fail
89+
fetchMock.mockResponseOnce("S3 upload error", { status: 500 });
90+
91+
await expect(client.createAndUpload(siteId, {
92+
fileName: mockFileName,
93+
file: mockFileBuffer.buffer, // Pass ArrayBuffer
94+
})).rejects.toThrow();
95+
96+
// Ensure the S3 upload was attempted
97+
expect(fetchMock).toHaveBeenCalledWith(mockUploadUrl, expect.objectContaining({
98+
method: "POST",
99+
body: expect.any(FormDataConstructor),
100+
}));
101+
});
102+
103+
it("should create and upload a file from an ArrayBuffer", async () => {
104+
// Mock the Webflow API response for creating asset metadata
105+
const mockCreateResponse = {
106+
uploadUrl: mockUploadUrl,
107+
uploadDetails: {
108+
"xAmzAlgorithm": "AWS4-HMAC-SHA256",
109+
"xAmzDate": "20231010T000000Z",
110+
"xAmzCredential": "mock-credential",
111+
"xAmzSignature": "mock-signature",
112+
"successActionStatus": "201",
113+
"contentType": "text/plain",
114+
},
115+
};
116+
jest.spyOn(client, "create").mockResolvedValue(mockCreateResponse as Webflow.AssetUpload);
117+
118+
// Mock the S3 upload response
119+
fetchMock.mockResponseOnce(JSON.stringify({ success: true }), { status: 201 });
120+
121+
const result = await client.createAndUpload(siteId, {
122+
fileName: mockFileName,
123+
file: mockFileBuffer.buffer, // Pass ArrayBuffer
124+
});
125+
126+
// Assertions
127+
expect(client.create).toHaveBeenCalledWith(siteId, expect.objectContaining({
128+
fileName: mockFileName,
129+
fileHash: expect.any(String),
130+
}), undefined);
131+
132+
expect(fetchMock).toHaveBeenCalledWith(mockUploadUrl, expect.objectContaining({
133+
method: "POST",
134+
body: expect.any(FormDataConstructor),
135+
}));
136+
137+
expect(result).toEqual(mockCreateResponse);
138+
});
139+
140+
it("should create and upload a file from a URL", async () => {
141+
// Mock the file fetch response (first fetch call)
142+
fetchMock.mockResponseOnce(mockFileContent);
143+
144+
// Mock the Webflow API response for creating asset metadata
145+
const mockCreateResponse = {
146+
uploadUrl: mockUploadUrl,
147+
uploadDetails: {
148+
"xAmzAlgorithm": "AWS4-HMAC-SHA256",
149+
"xAmzDate": "20231010T000000Z",
150+
"xAmzCredential": "mock-credential",
151+
"xAmzSignature": "mock-signature",
152+
"successActionStatus": "201",
153+
"contentType": "text/plain",
154+
},
155+
};
156+
jest.spyOn(client, "create").mockResolvedValue(mockCreateResponse as Webflow.AssetUpload);
157+
158+
// Mock the S3 upload response (second fetch call)
159+
fetchMock.mockResponseOnce(JSON.stringify({ success: true }), { status: 201 });
160+
161+
const result = await client.createAndUpload(siteId, {
162+
fileName: mockFileName,
163+
file: "https://mock-file-url.com", // Pass asset URL
164+
});
165+
166+
// Assertions for the file fetch
167+
expect(fetchMock).toHaveBeenNthCalledWith(1, "https://mock-file-url.com");
168+
169+
// Assertions for the Webflow API call
170+
expect(client.create).toHaveBeenCalledWith(siteId, {
171+
fileName: mockFileName,
172+
fileHash: mockFileHash,
173+
}, undefined);
174+
175+
// Assertions for the S3 upload
176+
expect(fetchMock).toHaveBeenNthCalledWith(2, mockUploadUrl, expect.objectContaining({
177+
method: "POST",
178+
body: expect.any(FormDataConstructor),
179+
}));
180+
181+
expect(result).toEqual(mockCreateResponse);
182+
});
183+
});

0 commit comments

Comments
 (0)