PluginProbe
Extendify / 3.0.4
Extendify v3.0.4
3.2.1 3.2.0 3.1.6 3.1.5 3.1.4 3.1.3 3.1.2 3.1.1 3.1.0 3.0.6 3.0.5 3.0.4 trunk 0.1.0 0.10.0 0.10.1 0.10.2 0.11.0 0.11.1 0.2.0 0.3.0 0.3.1 0.4.0 0.5.0 0.6.0 All 127 releases
extendify / src / Launch / lib / __tests__ / upload-logo.test.js

upload-logo.test.js in Extendify 3.0.4, at src/Launch/lib/__tests__/upload-logo.test.js

243 lines 6.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import { getOption, updateOption } from '@launch/api/WPApi';
2 import { uploadLogo } from '@launch/lib/logo';
3 import { uploadMedia } from '@wordpress/media-utils';
4
5 // Mock the dependencies
6 jest.mock('@wordpress/media-utils', () => ({
7 uploadMedia: jest.fn(),
8 }));
9
10 jest.mock('@launch/api/WPApi', () => ({
11 getOption: jest.fn(),
12 updateOption: jest.fn(),
13 }));
14
15 describe('uploadLogo', () => {
16 // Setup and teardown
17 beforeEach(() => {
18 // Clear all mocks before each test
19 jest.clearAllMocks();
20
21 // Mock the fetch function
22 global.fetch = jest.fn();
23 global.File = class File {
24 constructor(bits, name, options) {
25 this.bits = bits;
26 this.name = name;
27 this.type = options?.type || '';
28 }
29 };
30 });
31
32 afterEach(() => {
33 // Restore fetch after each test
34 global.fetch.mockRestore();
35 delete global.File;
36 });
37
38 it('should not upload logo if one already exists', async () => {
39 // Mock existing logo
40 getOption.mockResolvedValue('123');
41
42 await uploadLogo('https://example.com/logo.png');
43
44 // Verify getOption was called
45 expect(getOption).toHaveBeenCalledWith('site_logo');
46
47 // Verify no other operations were performed
48 expect(global.fetch).not.toHaveBeenCalled();
49 expect(uploadMedia).not.toHaveBeenCalled();
50 expect(updateOption).not.toHaveBeenCalled();
51 });
52
53 it('should handle fetch errors gracefully', async () => {
54 // Mock no existing logo
55 getOption.mockResolvedValue('0');
56
57 // Mock fetch failure
58 global.fetch.mockResolvedValue({
59 ok: false,
60 text: () => Promise.resolve('Not found'),
61 });
62
63 console.error = jest.fn();
64
65 await uploadLogo('https://example.com/logo.png');
66
67 // Verify error was logged
68 expect(console.error).toHaveBeenCalled();
69 expect(uploadMedia).not.toHaveBeenCalled();
70 });
71
72 it('should successfully upload a logo when none exists', async () => {
73 // Mock no existing logo
74 getOption.mockResolvedValue('0');
75
76 // Mock successful fetch
77 const mockBlob = new Blob(['test'], { type: 'image/png' });
78 global.fetch.mockResolvedValue({
79 ok: true,
80 blob: () => Promise.resolve(mockBlob),
81 });
82
83 // Mock successful media upload
84 uploadMedia.mockImplementation(({ onFileChange }) => {
85 onFileChange([{ id: '456' }]);
86 return Promise.resolve();
87 });
88
89 await uploadLogo('https://example.com/logo.png');
90
91 // Verify the workflow
92 expect(getOption).toHaveBeenCalledWith('site_logo');
93 expect(global.fetch).toHaveBeenCalledWith('https://example.com/logo.png');
94 expect(uploadMedia).toHaveBeenCalled();
95 expect(updateOption).toHaveBeenCalledWith('site_logo', '456');
96 });
97
98 it('should handle upload errors gracefully', async () => {
99 // Mock no existing logo
100 getOption.mockResolvedValue('0');
101
102 // Mock successful fetch
103 const mockBlob = new Blob(['test'], { type: 'image/png' });
104 global.fetch.mockResolvedValue({
105 ok: true,
106 blob: () => Promise.resolve(mockBlob),
107 });
108
109 // Mock error in upload
110 console.error = jest.fn();
111 uploadMedia.mockImplementation(({ onError }) => {
112 onError(new Error('Upload failed'));
113 return Promise.resolve();
114 });
115
116 await uploadLogo('https://example.com/logo.png');
117
118 // Verify error was handled
119 expect(console.error).toHaveBeenCalled();
120 });
121
122 it('should force upload even if logo already exists when forceReplace is true', async () => {
123 getOption.mockResolvedValue('123');
124
125 const mockBlob = new Blob(['test'], { type: 'image/png' });
126 global.fetch.mockResolvedValue({
127 ok: true,
128 blob: () => Promise.resolve(mockBlob),
129 });
130
131 uploadMedia.mockImplementation(({ onFileChange }) => {
132 onFileChange([{ id: '789' }]);
133 return Promise.resolve();
134 });
135
136 await uploadLogo('https://example.com/logo.png', { forceReplace: true });
137
138 expect(getOption).toHaveBeenCalledWith('site_logo');
139 expect(global.fetch).toHaveBeenCalledWith('https://example.com/logo.png');
140 expect(uploadMedia).toHaveBeenCalled();
141 expect(updateOption).toHaveBeenCalledWith('site_logo', '789');
142 });
143
144 it('should upload logo with webp format correctly', async () => {
145 getOption.mockResolvedValue('0');
146 const mockBlob = new Blob(['test'], { type: 'image/webp' });
147 global.fetch.mockResolvedValue({
148 ok: true,
149 blob: () => Promise.resolve(mockBlob),
150 });
151
152 const FileSpy = jest.fn(function (_bits, name, options) {
153 this.name = name;
154 this.type = options?.type;
155 return this;
156 });
157 global.File = FileSpy;
158
159 uploadMedia.mockImplementation(({ onFileChange }) => {
160 onFileChange([{ id: '100' }]);
161 return Promise.resolve();
162 });
163
164 await uploadLogo('https://example.com/logo.webp');
165 expect(FileSpy).toHaveBeenCalledWith(
166 expect.anything(),
167 expect.stringMatching(/^ext-custom-logo-\d+\.webp$/),
168 expect.objectContaining({ type: 'image/webp' }),
169 );
170 });
171
172 it('should log error for unsupported MIME types like jpeg', async () => {
173 getOption.mockResolvedValue('0');
174 const mockBlob = new Blob(['test'], { type: 'image/jpeg' });
175
176 global.fetch.mockResolvedValue({
177 ok: true,
178 blob: () => Promise.resolve(mockBlob),
179 });
180
181 const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
182 await uploadLogo('https://example.com/logo.jpg');
183
184 expect(errorSpy).toHaveBeenCalledWith(
185 'Error uploading logo: ',
186 expect.any(Error),
187 );
188 expect(errorSpy.mock.calls[0][1].message).toMatch(/Unsupported image type/);
189 expect(uploadMedia).not.toHaveBeenCalled();
190
191 errorSpy.mockRestore();
192 });
193
194 it('should generate dynamic filename with correct extension', async () => {
195 getOption.mockResolvedValue('0');
196 const mockBlob = new Blob(['test'], { type: 'image/avif' });
197 global.fetch.mockResolvedValue({
198 ok: true,
199 blob: () => Promise.resolve(mockBlob),
200 });
201
202 const FileSpy = jest.fn(function (_bits, name, options) {
203 this.name = name;
204 this.type = options?.type;
205 return this;
206 });
207 global.File = FileSpy;
208
209 uploadMedia.mockImplementation(({ onFileChange }) => {
210 onFileChange([{ id: '200' }]);
211 return Promise.resolve();
212 });
213
214 await uploadLogo('https://example.com/blob-url', {
215 mimeType: 'image/avif',
216 });
217
218 expect(FileSpy).toHaveBeenCalledWith(
219 expect.anything(),
220 expect.stringMatching(/^ext-custom-logo-\d+\.avif$/),
221 expect.objectContaining({ type: 'image/avif' }),
222 );
223 });
224
225 it('should not call updateOption if fileObj.id is falsy', async () => {
226 getOption.mockResolvedValue('0');
227 const mockBlob = new Blob(['test'], { type: 'image/png' });
228 global.fetch.mockResolvedValue({
229 ok: true,
230 blob: () => Promise.resolve(mockBlob),
231 });
232
233 uploadMedia.mockImplementation(({ onFileChange }) => {
234 onFileChange([{}]);
235 return Promise.resolve();
236 });
237
238 await uploadLogo('https://example.com/logo.png');
239
240 expect(updateOption).not.toHaveBeenCalled();
241 });
242 });
243