Skip to content

Commit 5e95cb5

Browse files
committed
improve ut
1 parent 4e032b7 commit 5e95cb5

File tree

1 file changed

+162
-3
lines changed

1 file changed

+162
-3
lines changed

tests/diff.test.ts

Lines changed: 162 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { afterEach, beforeEach, describe, expect, test } from 'bun:test';
22
import fs from 'fs';
33
import os from 'os';
44
import path from 'path';
5+
import { npm, yarn } from 'global-dirs';
56
import { ZipFile as YazlZipFile } from 'yazl';
67
import { diffCommands, enumZipEntries, readEntry } from '../src/diff';
78
import type { CommandContext } from '../src/types';
@@ -12,9 +13,9 @@ type ZipContent = {
1213
};
1314

1415
type DiffContextOptions = {
15-
output: string;
16-
customDiff: (oldSource?: Buffer, newSource?: Buffer) => Buffer;
17-
};
16+
output?: unknown;
17+
customDiff?: (oldSource?: Buffer, newSource?: Buffer) => Buffer;
18+
} & Record<string, unknown>;
1819

1920
function mkTempDir(prefix: string): string {
2021
return fs.mkdtempSync(path.join(os.tmpdir(), prefix));
@@ -72,6 +73,15 @@ function createContext(
7273
};
7374
}
7475

76+
function hasDiffModule(pkgName: string): boolean {
77+
try {
78+
require.resolve(pkgName, { paths: ['.', npm.packages, yarn.packages] });
79+
return true;
80+
} catch {
81+
return false;
82+
}
83+
}
84+
7585
describe('diff commands', () => {
7686
let tempRoot = '';
7787

@@ -217,4 +227,153 @@ describe('diff commands', () => {
217227
expect(diffMeta.copies['assets/icon.png']).toBe('');
218228
expect(diffMeta.copies['assets/new-name.png']).toBe('assets/old-name.png');
219229
});
230+
231+
test('diff supports explicit next directories and avoids duplicate additions', async () => {
232+
const originPath = path.join(tempRoot, 'origin-dir.ppk');
233+
const nextPath = path.join(tempRoot, 'next-dir.ppk');
234+
const outputPath = path.join(tempRoot, 'out', 'dir-diff.ppk');
235+
236+
await createZip(originPath, {
237+
'index.bundlejs': 'old-bundle',
238+
});
239+
await createZip(nextPath, {
240+
'index.bundlejs': 'new-bundle',
241+
'extra/': '',
242+
'extra/new.txt': 'new-file',
243+
});
244+
245+
await diffCommands.diff(
246+
createContext([originPath, nextPath], {
247+
output: outputPath,
248+
customDiff: () => Buffer.from('patch'),
249+
}),
250+
);
251+
252+
const result = await readZipContent(outputPath);
253+
const extraDirCount = result.entries.filter(
254+
(entry) => entry === 'extra/',
255+
).length;
256+
expect(extraDirCount).toBe(1);
257+
expect(result.files['extra/new.txt']?.toString('utf-8')).toBe('new-file');
258+
});
259+
260+
test('diffFromApk throws when origin package bundle is missing', async () => {
261+
const originPath = path.join(tempRoot, 'origin-missing-bundle.apk');
262+
const nextPath = path.join(tempRoot, 'next-for-apk.ppk');
263+
const outputPath = path.join(tempRoot, 'out', 'apk-missing-bundle.ppk');
264+
265+
await createZip(originPath, {
266+
'assets/other.txt': 'no-bundle',
267+
});
268+
await createZip(nextPath, {
269+
'index.bundlejs': 'new-bundle',
270+
});
271+
272+
await expect(
273+
diffCommands.diffFromApk(
274+
createContext([originPath, nextPath], {
275+
output: outputPath,
276+
customDiff: () => Buffer.from('patch'),
277+
}),
278+
),
279+
).rejects.toThrow();
280+
});
281+
282+
test('diffFromApk writes directory entries from next package', async () => {
283+
const originPath = path.join(tempRoot, 'origin-dir.apk');
284+
const nextPath = path.join(tempRoot, 'next-dir-apk.ppk');
285+
const outputPath = path.join(tempRoot, 'out', 'apk-dir-diff.ppk');
286+
287+
await createZip(originPath, {
288+
'assets/index.android.bundle': 'old-bundle',
289+
});
290+
await createZip(nextPath, {
291+
'index.bundlejs': 'new-bundle',
292+
'assets/': '',
293+
'assets/new.txt': 'new-file',
294+
});
295+
296+
await diffCommands.diffFromApk(
297+
createContext([originPath, nextPath], {
298+
output: outputPath,
299+
customDiff: (oldSource, newSource) =>
300+
Buffer.from(
301+
`patch:${oldSource?.toString('utf-8')}:${newSource?.toString('utf-8')}`,
302+
),
303+
}),
304+
);
305+
306+
const result = await readZipContent(outputPath);
307+
expect(result.entries).toContain('assets/');
308+
expect(result.files['assets/new.txt']?.toString('utf-8')).toBe('new-file');
309+
});
310+
311+
test('diffFromIpa ignores non-payload files when resolving origin package path', async () => {
312+
const originPath = path.join(tempRoot, 'origin-non-payload.ipa');
313+
const nextPath = path.join(tempRoot, 'next-non-payload.ppk');
314+
const outputPath = path.join(tempRoot, 'out', 'non-payload-diff.ppk');
315+
316+
await createZip(originPath, {
317+
'Random/ignored.txt': 'ignored',
318+
'Payload/MyApp.app/main.jsbundle': 'old-bundle',
319+
'Payload/MyApp.app/assets/icon.png': 'same-icon',
320+
});
321+
await createZip(nextPath, {
322+
'index.bundlejs': 'new-bundle',
323+
'assets/icon.png': 'same-icon',
324+
});
325+
326+
await diffCommands.diffFromIpa(
327+
createContext([originPath, nextPath], {
328+
output: outputPath,
329+
customDiff: () => Buffer.from('patch'),
330+
}),
331+
);
332+
333+
const result = await readZipContent(outputPath);
334+
const diffMeta = JSON.parse(
335+
result.files['__diff.json'].toString('utf-8'),
336+
) as {
337+
copies: Record<string, string>;
338+
};
339+
expect(diffMeta.copies['assets/icon.png']).toBe('');
340+
});
341+
342+
test('diff throws when output option is not string', async () => {
343+
await expect(
344+
diffCommands.diff(
345+
createContext(['origin.ppk', 'next.ppk'], {
346+
output: 123,
347+
customDiff: () => Buffer.from('patch'),
348+
}),
349+
),
350+
).rejects.toThrow('Output path is required.');
351+
});
352+
353+
test('hdiff/diff require engine modules when customDiff is not provided', async () => {
354+
const hasHdiff = hasDiffModule('node-hdiffpatch');
355+
const hasBsdiff = hasDiffModule('node-bsdiff');
356+
357+
if (!hasHdiff) {
358+
await expect(
359+
diffCommands.hdiff(
360+
createContext(['origin.ppk', 'next.ppk'], {
361+
output: path.join(tempRoot, 'out', 'hdiff.ppk'),
362+
}),
363+
),
364+
).rejects.toThrow(/node-hdiffpatch/);
365+
}
366+
367+
if (!hasBsdiff) {
368+
await expect(
369+
diffCommands.diff(
370+
createContext(['origin.ppk', 'next.ppk'], {
371+
output: path.join(tempRoot, 'out', 'diff.ppk'),
372+
}),
373+
),
374+
).rejects.toThrow(/node-bsdiff/);
375+
}
376+
377+
expect(true).toBe(true);
378+
});
220379
});

0 commit comments

Comments
 (0)