@zennomi/mangadex-full-api
Version:
A MangaDex api based around the official API.
172 lines (148 loc) • 6.51 kB
text/typescript
import { Chapter, Cover, Manga, Tag } from '../src/index';
import type Relationship from '../src/internal/Relationship';
import { ensureLogin, expectEqualIds } from './testutil';
beforeAll(async () => {
await ensureLogin();
});
test('getByQuery() and search()', async () => {
const query = { title: 'isekai' };
const queriedManga = await Manga.getByQuery(query);
const searchedManga = await Manga.search(query);
expect(queriedManga).not.toBeNull();
expect(searchedManga.length).toBeGreaterThan(0);
expect(searchedManga[0]).toBeInstanceOf(Manga);
expect(queriedManga!.id).toEqual(searchedManga[0].id);
});
test('getMultiple() and search() with a high limit', async () => {
const searchManga = await Manga.search({ limit: 200 });
expect(searchManga.length).toBeGreaterThan(0);
const searchIds = searchManga.map((m) => m.id);
const multipleManga = await Manga.getMultiple(searchIds);
expectEqualIds(multipleManga, searchManga);
});
test('get() and search()', async () => {
const searchManga = await Manga.search({ limit: 1 });
expect(searchManga.length).toEqual(1);
const mangaId = searchManga[0].id;
const manga = await Manga.get(mangaId);
expect(manga).toEqual(searchManga[0]);
expect(manga).toBeInstanceOf(Manga);
});
test('getRandom() and localizations', async () => {
const manga = await Manga.getRandom();
expect(manga).toBeInstanceOf(Manga);
expect(manga.localTitle).toEqual(manga.title.localString);
expect(manga.localDescription).toEqual(manga.description.localString);
expect(manga.localAltTitles).toEqual(manga.altTitles.map((t) => t.localString));
});
test('getFeed()', async () => {
const manga = await Manga.getByQuery({ hasAvailableChapters: true });
expect(manga).not.toBeNull();
const feed = await manga!.getFeed();
expect(feed.length).toBeGreaterThan(0);
expect(feed[0].manga.id).toEqual(manga!.id);
expect(feed[0]).toBeInstanceOf(Chapter);
});
test('getCovers()', async () => {
const manga = await Manga.getRandom();
const covers = await manga.getCovers();
expect(covers.length).toBeGreaterThan(0);
expect(covers[0]).toBeInstanceOf(Cover);
expect(covers[0].manga.id).toEqual(manga.id);
});
test('getRelations()', async () => {
// Find a manga with the most relations
const searchedManga = await Manga.search({ includedTags: [await Tag.getByName('Fan Colored')], limit: 100 });
searchedManga.sort(
(a, b) => Object.values(b.relatedManga).flat().length - Object.values(a.relatedManga).flat().length,
);
const manga = searchedManga[0];
expect(manga).toBeDefined();
// Check if the requested relations are cached and that they match the given relations
const requestedRelations = await manga!.getRelations(true);
const givenRelations = manga!.relatedManga as Record<string, Relationship<Manga>[]>;
for (const [relType, relatedManga] of Object.entries(requestedRelations)) {
for (const related of relatedManga) {
// Sometimes the related manga don't exist, so if they're not cached, resolving should cause an error
if (!related.cached) {
expect(related.resolve()).rejects.not.toBeNull();
}
}
const ids1 = relatedManga.map((m) => m.id);
const ids2 = givenRelations[relType].map((m) => m.id);
ids1.sort();
ids2.sort();
expect(ids1).toEqual(ids2);
}
});
test('getStatistics()', async () => {
const manga = await Manga.getRandom();
const stats = await manga.getStatistics();
expect(stats).toBeDefined();
});
test('getAggregate()', async () => {
const manga = await Manga.getByQuery({ hasAvailableChapters: true, order: { followedCount: 'desc' } });
expect(manga).not.toBeNull();
// Get chapter to look for in aggregate
const feed = await manga!.getFeed({ limit: 1 });
const testChapter = feed[0];
expect(testChapter).toBeDefined();
const testGroup = testChapter.groups[0].id;
const testLang = testChapter.translatedLanguage;
expect(testGroup).toBeDefined();
expect(testLang).toBeDefined();
const aggregate = await manga!.getAggregate([testGroup], [testLang]);
const chapterIds: string[] = Object.values(aggregate).flatMap((vol) =>
Object.values(vol.chapters).map((c) => c.id),
);
expect(chapterIds).toContain(testChapter.id);
});
test('getTotalSearchResults()', async () => {
const amount = await Manga.getTotalSearchResults({ title: 'isekai' });
expect(amount).toBeGreaterThan(0);
});
test('getFollowedManga() and getReadChapters()', async () => {
const followedManga = await Manga.getFollowedManga({ limit: 101 });
if (followedManga.length === 0) {
console.warn('No followed manga found, skipping test');
return;
}
expect(followedManga[0]).toBeInstanceOf(Manga);
const chapters = await Manga.getReadChapters(followedManga.map((m) => m.id));
const readChapters = Object.values(chapters);
readChapters.sort((a, b) => b.length - a.length)[0];
if (readChapters[0].length === 0) {
console.warn('No read chapters found, skipping test');
return;
}
const mostReadManga = await readChapters[0][0].manga.resolve();
const mostReadMangaChapters = await mostReadManga.getReadChapters();
expect(mostReadMangaChapters.map((m) => m.id).sort()).toEqual(readChapters[0].map((m) => m.id).sort());
});
test('getUserRating() and getRandom()', async () => {
const manga = await Manga.getRandom();
expect(manga).toBeInstanceOf(Manga);
const rating = await manga.getUserRating();
if (rating !== null) {
expect(typeof rating).toBe('number');
}
});
test('getFollowedFeed()', async () => {
const feed = await Manga.getFollowedFeed();
for (const chapter of feed) {
expect(chapter).toBeInstanceOf(Chapter);
}
});
test('getReadingStatus() and getAllReadingStatus()', async () => {
const statuses = await Manga.getAllReadingStatus();
expect(statuses).toBeDefined();
const markedMangaIds = Object.keys(statuses);
if (markedMangaIds.length === 0) {
console.warn('No reading statuses found, skipping test');
return;
}
const mangaId = markedMangaIds[0];
const manga = await Manga.get(mangaId); // Inefficient, but it tests 2 functions at once
const mangaStatus = await manga.getReadingStatus();
expect(statuses[mangaId]).toEqual(mangaStatus);
});