Files
jackwener__opencli/clis/douban/utils.test.js
jakevin d2974a9ff6 refactor(adapters): convert adapter layer from TypeScript to JavaScript (#928)
* refactor(adapters): convert adapter layer from TypeScript to JavaScript

Core framework stays TypeScript; adapter layer moves to JS-first.
Adapters are essentially "executable config + browser scripts" that
barely use TS features — this simplifies the build/distribution pipeline
by removing the dist/clis/ intermediate compilation step.

Changes:
- Convert all 753 adapter files in clis/ from .ts to .js
- Update tsconfig to exclude clis/ from compilation
- Simplify build-manifest to scan clis/*.js directly (no dist/clis/)
- Update discovery, main, fetch-adapters to load JS adapters from clis/
- Update generate-verified to output .js artifacts
- Update package.json files field: dist/clis/ → clis/
- Fix all test files for the .ts → .js transition

* fix(main): use findPackageRoot for BUILTIN_CLIS path

The previous relative path (../../clis from __dirname) only worked for
dist/src/main.js but broke dev mode (tsx src/main.ts) where __dirname
is <repo>/src — resolving to /clis instead of <repo>/clis.

Use findPackageRoot() which works for both dev and prod paths.
2026-04-10 14:52:18 +08:00

65 lines
3.6 KiB
JavaScript

import { describe, expect, it, vi } from 'vitest';
import { getDoubanPhotoExtension, loadDoubanSubjectPhotos, normalizeDoubanSubjectId, promoteDoubanPhotoUrl, resolveDoubanPhotoAssetUrl, } from './utils.js';
describe('douban utils', () => {
it('normalizes valid subject ids', () => {
expect(normalizeDoubanSubjectId(' 30382501 ')).toBe('30382501');
});
it('rejects invalid subject ids', () => {
expect(() => normalizeDoubanSubjectId('tt30382501')).toThrow('Invalid Douban subject ID');
});
it('promotes thumbnail urls to large photo urls', () => {
expect(promoteDoubanPhotoUrl('https://img1.doubanio.com/view/photo/m/public/p2913450214.webp')).toBe('https://img1.doubanio.com/view/photo/l/public/p2913450214.webp');
expect(promoteDoubanPhotoUrl('https://img9.doubanio.com/view/photo/s_ratio_poster/public/p2578474613.jpg')).toBe('https://img9.doubanio.com/view/photo/l/public/p2578474613.jpg');
});
it('rejects non-http photo urls during promotion', () => {
expect(promoteDoubanPhotoUrl('data:image/gif;base64,abc')).toBe('');
});
it('prefers lazy-loaded photo urls over data placeholders', () => {
expect(resolveDoubanPhotoAssetUrl([
'',
'https://img1.doubanio.com/view/photo/m/public/p2913450214.webp',
'data:image/gif;base64,abc',
], 'https://movie.douban.com/subject/30382501/photos?type=Rb')).toBe('https://img1.doubanio.com/view/photo/m/public/p2913450214.webp');
});
it('drops unsupported non-http photo urls when no real image url exists', () => {
expect(resolveDoubanPhotoAssetUrl(['data:image/gif;base64,abc', 'blob:https://movie.douban.com/example'], 'https://movie.douban.com/subject/30382501/photos?type=Rb')).toBe('');
});
it('removes the default photo cap when scanning for an exact photo id', async () => {
const evaluate = vi.fn()
.mockResolvedValueOnce({ blocked: false, title: 'Some Movie', href: 'https://movie.douban.com/subject/30382501/photos?type=Rb' })
.mockResolvedValueOnce({
subjectId: '30382501',
subjectTitle: 'The Wandering Earth 2',
type: 'Rb',
photos: [
{
index: 731,
photoId: '2913450215',
title: 'Character poster',
imageUrl: 'https://img1.doubanio.com/view/photo/l/public/p2913450215.jpg',
thumbUrl: 'https://img1.doubanio.com/view/photo/m/public/p2913450215.jpg',
detailUrl: 'https://movie.douban.com/photos/photo/2913450215/',
page: 25,
},
],
});
const page = {
goto: vi.fn().mockResolvedValue(undefined),
wait: vi.fn().mockResolvedValue(undefined),
evaluate,
};
await loadDoubanSubjectPhotos(page, '30382501', {
type: 'Rb',
targetPhotoId: '2913450215',
});
const scanScript = evaluate.mock.calls[1]?.[0];
expect(scanScript).toContain('const targetPhotoId = "2913450215";');
expect(scanScript).toContain(`const limit = ${Number.MAX_SAFE_INTEGER};`);
expect(scanScript).toContain('for (let pageIndex = 0; photos.length < limit; pageIndex += 1)');
});
it('keeps image extensions when download urls contain query params', () => {
expect(getDoubanPhotoExtension('https://img1.doubanio.com/view/photo/l/public/p2913450214.webp?foo=1')).toBe('.webp');
expect(getDoubanPhotoExtension('https://img1.doubanio.com/view/photo/l/public/p2913450214.jpeg')).toBe('.jpeg');
});
});