mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-08-02 19:21:34 -07:00
feat(anime): add anime browser powered by Aniyomi extensions
- Add `subminer anime` / `--anime` and a tray entry to open a browser that searches installed Aniyomi extension sources, shows cover art and episodes, and plays into mpv with overlay/mining attached - Add an Extensions tab to add repos and install/update/remove sources, and per-source settings for sources needing config - Support searching all sources at once with streaming, per-source results and status - Prefer Japanese audio/subtitle tracks from the source and keep the primary subtitle slot reserved for Japanese - Fix window/tray/Dock handling so the browser and mpv can be switched between without quitting the app or losing the Dock icon - Add anime.repos, anime.extensionsDir, anime.preferredQuality config keys (no bundled repos or discovery)
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { describeInstalled, sourceOptionLabel, summarizeSearch } from './format';
|
||||
import type { AnimeBrowserSearchResult } from '../types/anime-browser';
|
||||
|
||||
const result = (
|
||||
entryCount: number,
|
||||
failures: AnimeBrowserSearchResult['failures'] = [],
|
||||
): AnimeBrowserSearchResult => ({
|
||||
entries: Array.from({ length: entryCount }, (_unused, index) => ({
|
||||
url: `/a/${index}`,
|
||||
title: `Anime ${index}`,
|
||||
thumbnailUrl: null,
|
||||
sourceId: 's',
|
||||
sourceName: 'Source',
|
||||
})),
|
||||
hasNextPage: false,
|
||||
failures,
|
||||
});
|
||||
|
||||
test('sourceOptionLabel omits the language for an all-language source', () => {
|
||||
assert.equal(sourceOptionLabel({ id: '1', name: 'Nyaa', lang: 'ja', pkg: 'p' }), 'Nyaa (ja)');
|
||||
assert.equal(sourceOptionLabel({ id: '2', name: 'Jellyfin', lang: 'all', pkg: 'p' }), 'Jellyfin');
|
||||
});
|
||||
|
||||
test('summarizeSearch counts results and singularizes one', () => {
|
||||
assert.equal(summarizeSearch(result(4)), '4 results');
|
||||
assert.equal(summarizeSearch(result(1)), '1 result');
|
||||
assert.equal(summarizeSearch(result(0)), '0 results');
|
||||
});
|
||||
|
||||
test('summarizeSearch names the sources that failed alongside the ones that answered', () => {
|
||||
const summary = summarizeSearch(
|
||||
result(6, [
|
||||
{ sourceId: 'a', sourceName: 'Alpha', error: 'login required' },
|
||||
{ sourceId: 'b', sourceName: 'Beta', error: 'timed out' },
|
||||
]),
|
||||
);
|
||||
assert.equal(summary, '6 results · 2 unavailable: Alpha, Beta');
|
||||
});
|
||||
|
||||
test('describeInstalled reports sources and languages when the extension loaded', () => {
|
||||
assert.equal(
|
||||
describeInstalled({
|
||||
pkg: 'multi',
|
||||
name: 'One, Two',
|
||||
langs: ['en', 'ja'],
|
||||
sourceCount: 2,
|
||||
error: null,
|
||||
}),
|
||||
'multi · 2 sources · en, ja',
|
||||
);
|
||||
});
|
||||
|
||||
test('describeInstalled falls back to the package alone when nothing loaded', () => {
|
||||
assert.equal(
|
||||
describeInstalled({ pkg: 'broken', name: 'broken', langs: [], sourceCount: 0, error: 'boom' }),
|
||||
'broken',
|
||||
);
|
||||
});
|
||||
Reference in New Issue
Block a user