mirror of
https://github.com/movie-web/providers.git
synced 2025-09-13 13:33:25 +00:00
update deps, migrate to pnpm
This commit is contained in:
@@ -1,12 +1,12 @@
|
||||
import { buildProviders } from "@/entrypoint/builder";
|
||||
import { ScrapeMedia } from "@/entrypoint/utils/media";
|
||||
import { targets } from "@/entrypoint/utils/targets";
|
||||
import { makeStandardFetcher } from "@/fetchers/standardFetch";
|
||||
import { Embed, Sourcerer, SourcererEmbed } from "@/providers/base";
|
||||
import { TestTypes } from "./providerUtils";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { ProviderControls } from "@/entrypoint/controls";
|
||||
import { makeSimpleProxyFetcher } from "@/fetchers/simpleProxy";
|
||||
import { buildProviders } from '@/entrypoint/builder';
|
||||
import { ScrapeMedia } from '@/entrypoint/utils/media';
|
||||
import { targets } from '@/entrypoint/utils/targets';
|
||||
import { makeStandardFetcher } from '@/fetchers/standardFetch';
|
||||
import { Embed, Sourcerer, SourcererEmbed } from '@/providers/base';
|
||||
import { TestTypes } from './providerUtils';
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { ProviderControls } from '@/entrypoint/controls';
|
||||
import { makeSimpleProxyFetcher } from '@/fetchers/simpleProxy';
|
||||
|
||||
export interface TestEmbedOptions {
|
||||
embed: Embed;
|
||||
@@ -18,18 +18,16 @@ export interface TestEmbedOptions {
|
||||
embeds: number;
|
||||
streams?: number;
|
||||
error?: boolean;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function makeBaseEmbedProviders() {
|
||||
const builder = buildProviders()
|
||||
.setTarget(targets.ANY)
|
||||
.setFetcher(makeStandardFetcher(fetch));
|
||||
const builder = buildProviders().setTarget(targets.ANY).setFetcher(makeStandardFetcher(fetch));
|
||||
return builder;
|
||||
}
|
||||
|
||||
export function testEmbed(ops: TestEmbedOptions) {
|
||||
if (ops.testSuite.length === 0) throw new Error("Test suite must have at least one test");
|
||||
if (ops.testSuite.length === 0) throw new Error('Test suite must have at least one test');
|
||||
describe(`embed:${ops.source.id}:${ops.embed.id}`, () => {
|
||||
ops.testSuite.forEach((test) => {
|
||||
describe(`test ${test.title}`, async () => {
|
||||
@@ -37,8 +35,11 @@ export function testEmbed(ops: TestEmbedOptions) {
|
||||
const results = await providers.runSourceScraper({
|
||||
id: ops.source.id,
|
||||
media: test,
|
||||
})
|
||||
if (results.embeds.length !== ops.expect.embeds) throw new Error(`Embeds don't match expected amount of embeds (${ops.source.id}, ${ops.embed.id}, got ${results.embeds.length} but expected ${ops.expect.embeds})`);
|
||||
});
|
||||
if (results.embeds.length !== ops.expect.embeds)
|
||||
throw new Error(
|
||||
`Embeds don't match expected amount of embeds (${ops.source.id}, ${ops.embed.id}, got ${results.embeds.length} but expected ${ops.expect.embeds})`,
|
||||
);
|
||||
return results.embeds;
|
||||
}
|
||||
|
||||
@@ -49,7 +50,7 @@ export function testEmbed(ops: TestEmbedOptions) {
|
||||
const result = await providers.runEmbedScraper({
|
||||
id: ops.embed.id,
|
||||
url: embedUrl,
|
||||
})
|
||||
});
|
||||
if (ops.debug) console.log(result);
|
||||
streamCount = (result.stream ?? []).length;
|
||||
} catch (err) {
|
||||
@@ -62,12 +63,11 @@ export function testEmbed(ops: TestEmbedOptions) {
|
||||
|
||||
for (const t of ops.types) {
|
||||
const builder = makeBaseEmbedProviders().addSource(ops.source).addEmbed(ops.embed);
|
||||
if (t === 'standard') {}
|
||||
else if (t === 'ip:standard')
|
||||
builder.enableConsistentIpForRequests();
|
||||
if (t === 'standard') {
|
||||
} else if (t === 'ip:standard') builder.enableConsistentIpForRequests();
|
||||
else if (t === 'proxied') {
|
||||
if (!process.env.MOVIE_WEB_PROXY_URL)
|
||||
throw new Error("Cant use proxied test without setting MOVIE_WEB_PROXY_URL env");
|
||||
throw new Error('Cant use proxied test without setting MOVIE_WEB_PROXY_URL env');
|
||||
builder.setProxiedFetcher(makeSimpleProxyFetcher(process.env.MOVIE_WEB_PROXY_URL, fetch));
|
||||
}
|
||||
const providers = builder.build();
|
||||
@@ -76,15 +76,15 @@ export function testEmbed(ops: TestEmbedOptions) {
|
||||
embeds.forEach((embed, i) => {
|
||||
it(`${t} - embed ${i}`, async () => {
|
||||
await runTest(providers, embed.url);
|
||||
})
|
||||
})
|
||||
});
|
||||
});
|
||||
} catch (err) {
|
||||
it(`${t} - embed ??`, () => {
|
||||
throw new Error("Failed to get streams: " + err);
|
||||
})
|
||||
throw new Error('Failed to get streams: ' + err);
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@@ -1,13 +1,13 @@
|
||||
import dotenv from 'dotenv';
|
||||
import { febboxMp4Scraper } from "@/providers/embeds/febbox/mp4";
|
||||
import { testEmbed } from "./embedUtils";
|
||||
import { showboxScraper } from "@/providers/sources/showbox";
|
||||
import { testMedia } from "./testMedia";
|
||||
import { flixhqScraper } from "@/providers/sources/flixhq";
|
||||
import { upcloudScraper } from "@/providers/embeds/upcloud";
|
||||
import { goMoviesScraper } from "@/providers/sources/gomovies";
|
||||
import { smashyStreamScraper } from "@/providers/sources/smashystream";
|
||||
import { smashyStreamDScraper } from "@/providers/embeds/smashystream/dued";
|
||||
import { febboxMp4Scraper } from '@/providers/embeds/febbox/mp4';
|
||||
import { testEmbed } from './embedUtils';
|
||||
import { showboxScraper } from '@/providers/sources/showbox';
|
||||
import { testMedia } from './testMedia';
|
||||
import { flixhqScraper } from '@/providers/sources/flixhq';
|
||||
import { upcloudScraper } from '@/providers/embeds/upcloud';
|
||||
import { goMoviesScraper } from '@/providers/sources/gomovies';
|
||||
import { smashyStreamScraper } from '@/providers/sources/smashystream';
|
||||
import { smashyStreamDScraper } from '@/providers/embeds/smashystream/dued';
|
||||
import { vidsrcembedScraper } from '@/providers/embeds/vidsrc';
|
||||
import { vidsrcScraper } from '@/providers/sources/vidsrc';
|
||||
import { vidSrcToScraper } from '@/providers/sources/vidsrcto';
|
||||
@@ -26,8 +26,8 @@ testEmbed({
|
||||
expect: {
|
||||
embeds: 1,
|
||||
streams: 1,
|
||||
}
|
||||
})
|
||||
},
|
||||
});
|
||||
|
||||
testEmbed({
|
||||
embed: upcloudScraper,
|
||||
@@ -37,8 +37,8 @@ testEmbed({
|
||||
expect: {
|
||||
embeds: 1,
|
||||
streams: 1,
|
||||
}
|
||||
})
|
||||
},
|
||||
});
|
||||
|
||||
testEmbed({
|
||||
embed: upcloudScraper,
|
||||
@@ -48,8 +48,8 @@ testEmbed({
|
||||
expect: {
|
||||
embeds: 1,
|
||||
streams: 1,
|
||||
}
|
||||
})
|
||||
},
|
||||
});
|
||||
|
||||
testEmbed({
|
||||
embed: smashyStreamDScraper,
|
||||
@@ -59,8 +59,8 @@ testEmbed({
|
||||
expect: {
|
||||
embeds: 1,
|
||||
streams: 1,
|
||||
}
|
||||
})
|
||||
},
|
||||
});
|
||||
|
||||
testEmbed({
|
||||
embed: vidsrcembedScraper,
|
||||
@@ -70,8 +70,8 @@ testEmbed({
|
||||
expect: {
|
||||
embeds: 1,
|
||||
streams: 1,
|
||||
}
|
||||
})
|
||||
},
|
||||
});
|
||||
|
||||
testEmbed({
|
||||
embed: vidplayScraper,
|
||||
@@ -81,8 +81,8 @@ testEmbed({
|
||||
expect: {
|
||||
embeds: 1,
|
||||
streams: 1,
|
||||
}
|
||||
})
|
||||
},
|
||||
});
|
||||
|
||||
testEmbed({
|
||||
embed: fileMoonScraper,
|
||||
@@ -92,8 +92,8 @@ testEmbed({
|
||||
expect: {
|
||||
embeds: 1,
|
||||
streams: 1,
|
||||
}
|
||||
})
|
||||
},
|
||||
});
|
||||
|
||||
testEmbed({
|
||||
embed: upcloudScraper,
|
||||
@@ -103,8 +103,8 @@ testEmbed({
|
||||
expect: {
|
||||
embeds: 2,
|
||||
streams: 1,
|
||||
}
|
||||
})
|
||||
},
|
||||
});
|
||||
|
||||
testEmbed({
|
||||
embed: mixdropScraper,
|
||||
@@ -114,5 +114,5 @@ testEmbed({
|
||||
expect: {
|
||||
embeds: 2,
|
||||
streams: 1,
|
||||
}
|
||||
})
|
||||
},
|
||||
});
|
||||
|
@@ -1,13 +1,13 @@
|
||||
import { ScrapeMedia } from "@/entrypoint/utils/media";
|
||||
import { Embed, Sourcerer, SourcererEmbed } from "@/providers/base";
|
||||
import { buildProviders } from "@/entrypoint/builder";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { makeStandardFetcher } from "@/fetchers/standardFetch";
|
||||
import { ProviderControls } from "@/entrypoint/controls";
|
||||
import { NotFoundError } from "@/utils/errors";
|
||||
import { targets } from "@/entrypoint/utils/targets";
|
||||
import { getBuiltinEmbeds } from "@/entrypoint/providers";
|
||||
import { makeSimpleProxyFetcher } from "@/fetchers/simpleProxy";
|
||||
import { ScrapeMedia } from '@/entrypoint/utils/media';
|
||||
import { Embed, Sourcerer, SourcererEmbed } from '@/providers/base';
|
||||
import { buildProviders } from '@/entrypoint/builder';
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { makeStandardFetcher } from '@/fetchers/standardFetch';
|
||||
import { ProviderControls } from '@/entrypoint/controls';
|
||||
import { NotFoundError } from '@/utils/errors';
|
||||
import { targets } from '@/entrypoint/utils/targets';
|
||||
import { getBuiltinEmbeds } from '@/entrypoint/providers';
|
||||
import { makeSimpleProxyFetcher } from '@/fetchers/simpleProxy';
|
||||
|
||||
export type TestTypes = 'standard' | 'ip:standard' | 'proxied';
|
||||
|
||||
@@ -21,20 +21,18 @@ export interface TestSourceOptions {
|
||||
streams?: number;
|
||||
error?: boolean;
|
||||
notfound?: boolean;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function makeBaseProviders() {
|
||||
const builder = buildProviders()
|
||||
.setTarget(targets.ANY)
|
||||
.setFetcher(makeStandardFetcher(fetch));
|
||||
const builder = buildProviders().setTarget(targets.ANY).setFetcher(makeStandardFetcher(fetch));
|
||||
const embeds = getBuiltinEmbeds();
|
||||
embeds.forEach(embed => builder.addEmbed(embed));
|
||||
embeds.forEach((embed) => builder.addEmbed(embed));
|
||||
return builder;
|
||||
}
|
||||
|
||||
export function testSource(ops: TestSourceOptions) {
|
||||
if (ops.testSuite.length === 0) throw new Error("Test suite must have at least one test");
|
||||
if (ops.testSuite.length === 0) throw new Error('Test suite must have at least one test');
|
||||
describe(`source:${ops.source.id}`, () => {
|
||||
ops.testSuite.forEach((test) => {
|
||||
describe(`test ${test.title}`, () => {
|
||||
@@ -48,16 +46,14 @@ export function testSource(ops: TestSourceOptions) {
|
||||
const result = await providers.runSourceScraper({
|
||||
id: ops.source.id,
|
||||
media: test,
|
||||
})
|
||||
});
|
||||
if (ops.debug) console.log(result);
|
||||
streamCount = (result.stream ?? []).length;
|
||||
embedCount = result.embeds.length;
|
||||
} catch (err) {
|
||||
if (ops.debug) console.log(err);
|
||||
if (err instanceof NotFoundError)
|
||||
hasNotFound = true;
|
||||
else
|
||||
hasError = true;
|
||||
if (err instanceof NotFoundError) hasNotFound = true;
|
||||
else hasError = true;
|
||||
}
|
||||
expect(ops.expect.error ?? false).toBe(hasError);
|
||||
expect(ops.expect.notfound ?? false).toBe(hasNotFound);
|
||||
@@ -67,36 +63,30 @@ export function testSource(ops: TestSourceOptions) {
|
||||
|
||||
if (ops.types.includes('standard')) {
|
||||
it(`standard`, async () => {
|
||||
const providers = makeBaseProviders()
|
||||
.addSource(ops.source)
|
||||
.build();
|
||||
const providers = makeBaseProviders().addSource(ops.source).build();
|
||||
await runTest(providers);
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
if (ops.types.includes('ip:standard')) {
|
||||
it(`standard:ip`, async () => {
|
||||
const providers = makeBaseProviders()
|
||||
.addSource(ops.source)
|
||||
.enableConsistentIpForRequests()
|
||||
.build();
|
||||
const providers = makeBaseProviders().addSource(ops.source).enableConsistentIpForRequests().build();
|
||||
await runTest(providers);
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
if (ops.types.includes('proxied')) {
|
||||
it(`proxied`, async () => {
|
||||
if (!process.env.MOVIE_WEB_PROXY_URL)
|
||||
throw new Error("Cant use proxied test without setting MOVIE_WEB_PROXY_URL env");
|
||||
throw new Error('Cant use proxied test without setting MOVIE_WEB_PROXY_URL env');
|
||||
const providers = makeBaseProviders()
|
||||
.addSource(ops.source)
|
||||
.setProxiedFetcher(makeSimpleProxyFetcher(process.env.MOVIE_WEB_PROXY_URL, fetch))
|
||||
.build();
|
||||
await runTest(providers);
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
})
|
||||
})
|
||||
})
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@@ -1,15 +1,15 @@
|
||||
import { testSource } from "./providerUtils";
|
||||
import { lookmovieScraper } from "@/providers/sources/lookmovie";
|
||||
import { testMedia } from "./testMedia";
|
||||
import { showboxScraper } from "@/providers/sources/showbox";
|
||||
import { testSource } from './providerUtils';
|
||||
import { lookmovieScraper } from '@/providers/sources/lookmovie';
|
||||
import { testMedia } from './testMedia';
|
||||
import { showboxScraper } from '@/providers/sources/showbox';
|
||||
import dotenv from 'dotenv';
|
||||
import { flixhqScraper } from "@/providers/sources/flixhq";
|
||||
import { goMoviesScraper } from "@/providers/sources/gomovies";
|
||||
import { smashyStreamScraper } from "@/providers/sources/smashystream";
|
||||
import { vidsrcScraper } from "@/providers/sources/vidsrc";
|
||||
import { vidSrcToScraper } from "@/providers/sources/vidsrcto";
|
||||
import { zoechipScraper } from "@/providers/sources/zoechip";
|
||||
import { remotestreamScraper } from "@/providers/sources/remotestream";
|
||||
import { flixhqScraper } from '@/providers/sources/flixhq';
|
||||
import { goMoviesScraper } from '@/providers/sources/gomovies';
|
||||
import { smashyStreamScraper } from '@/providers/sources/smashystream';
|
||||
import { vidsrcScraper } from '@/providers/sources/vidsrc';
|
||||
import { vidSrcToScraper } from '@/providers/sources/vidsrcto';
|
||||
import { zoechipScraper } from '@/providers/sources/zoechip';
|
||||
import { remotestreamScraper } from '@/providers/sources/remotestream';
|
||||
|
||||
dotenv.config();
|
||||
|
||||
@@ -19,8 +19,8 @@ testSource({
|
||||
types: ['ip:standard'],
|
||||
expect: {
|
||||
streams: 1,
|
||||
}
|
||||
})
|
||||
},
|
||||
});
|
||||
|
||||
testSource({
|
||||
source: showboxScraper,
|
||||
@@ -28,8 +28,8 @@ testSource({
|
||||
types: ['standard', 'proxied'],
|
||||
expect: {
|
||||
embeds: 1,
|
||||
}
|
||||
})
|
||||
},
|
||||
});
|
||||
|
||||
testSource({
|
||||
source: flixhqScraper,
|
||||
@@ -37,8 +37,8 @@ testSource({
|
||||
types: ['standard', 'proxied'],
|
||||
expect: {
|
||||
embeds: 1,
|
||||
}
|
||||
})
|
||||
},
|
||||
});
|
||||
|
||||
testSource({
|
||||
source: goMoviesScraper,
|
||||
@@ -46,8 +46,8 @@ testSource({
|
||||
types: ['standard', 'proxied'],
|
||||
expect: {
|
||||
embeds: 1,
|
||||
}
|
||||
})
|
||||
},
|
||||
});
|
||||
|
||||
testSource({
|
||||
source: smashyStreamScraper,
|
||||
@@ -55,8 +55,8 @@ testSource({
|
||||
types: ['standard', 'proxied'],
|
||||
expect: {
|
||||
embeds: 1,
|
||||
}
|
||||
})
|
||||
},
|
||||
});
|
||||
|
||||
testSource({
|
||||
source: vidsrcScraper,
|
||||
@@ -64,8 +64,8 @@ testSource({
|
||||
types: ['standard', 'proxied'],
|
||||
expect: {
|
||||
embeds: 1,
|
||||
}
|
||||
})
|
||||
},
|
||||
});
|
||||
|
||||
testSource({
|
||||
source: vidSrcToScraper,
|
||||
@@ -73,8 +73,8 @@ testSource({
|
||||
types: ['standard', 'proxied'],
|
||||
expect: {
|
||||
embeds: 2,
|
||||
}
|
||||
})
|
||||
},
|
||||
});
|
||||
|
||||
testSource({
|
||||
source: zoechipScraper,
|
||||
@@ -82,8 +82,8 @@ testSource({
|
||||
types: ['standard', 'proxied'],
|
||||
expect: {
|
||||
embeds: 3,
|
||||
}
|
||||
})
|
||||
},
|
||||
});
|
||||
|
||||
testSource({
|
||||
source: remotestreamScraper,
|
||||
@@ -91,5 +91,5 @@ testSource({
|
||||
types: ['standard', 'proxied'],
|
||||
expect: {
|
||||
streams: 1,
|
||||
}
|
||||
})
|
||||
},
|
||||
});
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { ScrapeMedia } from "@/entrypoint/utils/media";
|
||||
import { ScrapeMedia } from '@/entrypoint/utils/media';
|
||||
|
||||
function makeMedia(media: ScrapeMedia): ScrapeMedia {
|
||||
return media;
|
||||
@@ -6,9 +6,9 @@ function makeMedia(media: ScrapeMedia): ScrapeMedia {
|
||||
|
||||
export const testMedia = {
|
||||
arcane: makeMedia({
|
||||
type: "show",
|
||||
title: "Arcane",
|
||||
tmdbId: "94605",
|
||||
type: 'show',
|
||||
title: 'Arcane',
|
||||
tmdbId: '94605',
|
||||
releaseYear: 2021,
|
||||
episode: {
|
||||
number: 1,
|
||||
@@ -18,13 +18,13 @@ export const testMedia = {
|
||||
number: 1,
|
||||
tmdbId: '134187',
|
||||
},
|
||||
imdbId: 'tt11126994'
|
||||
imdbId: 'tt11126994',
|
||||
}),
|
||||
hamilton: makeMedia({
|
||||
type: 'movie',
|
||||
tmdbId: '556574',
|
||||
imdbId: 'tt8503618',
|
||||
releaseYear: 2020,
|
||||
title: 'Hamilton'
|
||||
})
|
||||
}
|
||||
title: 'Hamilton',
|
||||
}),
|
||||
};
|
||||
|
@@ -1,39 +1,39 @@
|
||||
import { serializeBody } from "@/fetchers/body";
|
||||
import FormData from "form-data";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { serializeBody } from '@/fetchers/body';
|
||||
import FormData from 'form-data';
|
||||
import { describe, expect, it } from 'vitest';
|
||||
|
||||
describe("serializeBody()", () => {
|
||||
describe('serializeBody()', () => {
|
||||
it('should work with standard text', () => {
|
||||
expect(serializeBody("hello world")).toEqual({
|
||||
expect(serializeBody('hello world')).toEqual({
|
||||
headers: {},
|
||||
body: "hello world"
|
||||
})
|
||||
})
|
||||
body: 'hello world',
|
||||
});
|
||||
});
|
||||
|
||||
it('should work with objects', () => {
|
||||
expect(serializeBody({ hello: "world", a: 42 })).toEqual({
|
||||
expect(serializeBody({ hello: 'world', a: 42 })).toEqual({
|
||||
headers: {
|
||||
"Content-Type": "application/json"
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({ hello: "world", a: 42 })
|
||||
})
|
||||
})
|
||||
body: JSON.stringify({ hello: 'world', a: 42 }),
|
||||
});
|
||||
});
|
||||
|
||||
it('should work x-www-form-urlencoded', () => {
|
||||
const obj = new URLSearchParams()
|
||||
obj.set("a", "b");
|
||||
const obj = new URLSearchParams();
|
||||
obj.set('a', 'b');
|
||||
expect(serializeBody(obj)).toEqual({
|
||||
headers: {},
|
||||
body: obj
|
||||
})
|
||||
})
|
||||
|
||||
body: obj,
|
||||
});
|
||||
});
|
||||
|
||||
it('should work multipart/form-data', () => {
|
||||
const obj = new FormData()
|
||||
obj.append("a", "b");
|
||||
const obj = new FormData();
|
||||
obj.append('a', 'b');
|
||||
expect(serializeBody(obj)).toEqual({
|
||||
headers: {},
|
||||
body: obj
|
||||
})
|
||||
})
|
||||
})
|
||||
body: obj,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@@ -1,48 +1,62 @@
|
||||
import { makeFullUrl } from "@/fetchers/common";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { makeFullUrl } from '@/fetchers/common';
|
||||
import { describe, expect, it } from 'vitest';
|
||||
|
||||
describe("makeFullUrl()", () => {
|
||||
describe('makeFullUrl()', () => {
|
||||
it('should pass normal url if no options', () => {
|
||||
expect(makeFullUrl('https://example.com/hello/world')).toEqual("https://example.com/hello/world")
|
||||
expect(makeFullUrl('https://example.com/hello/world?a=b')).toEqual("https://example.com/hello/world?a=b")
|
||||
expect(makeFullUrl('https://example.com/hello/world?a=b#hello')).toEqual("https://example.com/hello/world?a=b#hello")
|
||||
expect(makeFullUrl('https://example.com/hello/world#hello')).toEqual("https://example.com/hello/world#hello")
|
||||
})
|
||||
expect(makeFullUrl('https://example.com/hello/world')).toEqual('https://example.com/hello/world');
|
||||
expect(makeFullUrl('https://example.com/hello/world?a=b')).toEqual('https://example.com/hello/world?a=b');
|
||||
expect(makeFullUrl('https://example.com/hello/world?a=b#hello')).toEqual(
|
||||
'https://example.com/hello/world?a=b#hello',
|
||||
);
|
||||
expect(makeFullUrl('https://example.com/hello/world#hello')).toEqual('https://example.com/hello/world#hello');
|
||||
});
|
||||
|
||||
it('should append baseurl correctly', () => {
|
||||
const correctResult = "https://example.com/hello/world";
|
||||
expect(makeFullUrl(correctResult, { baseUrl: '' })).toEqual(correctResult)
|
||||
expect(makeFullUrl('/hello/world', { baseUrl: 'https://example.com' })).toEqual(correctResult)
|
||||
expect(makeFullUrl('/hello/world', { baseUrl: 'https://example.com/' })).toEqual(correctResult)
|
||||
expect(makeFullUrl('hello/world', { baseUrl: 'https://example.com/' })).toEqual(correctResult)
|
||||
expect(makeFullUrl('hello/world', { baseUrl: 'https://example.com' })).toEqual(correctResult)
|
||||
expect(makeFullUrl('/world', { baseUrl: 'https://example.com/hello' })).toEqual(correctResult)
|
||||
expect(makeFullUrl('/world', { baseUrl: 'https://example.com/hello/' })).toEqual(correctResult)
|
||||
expect(makeFullUrl('world', { baseUrl: 'https://example.com/hello/' })).toEqual(correctResult)
|
||||
expect(makeFullUrl('world', { baseUrl: 'https://example.com/hello' })).toEqual(correctResult)
|
||||
expect(makeFullUrl('world?a=b', { baseUrl: 'https://example.com/hello' })).toEqual("https://example.com/hello/world?a=b")
|
||||
})
|
||||
const correctResult = 'https://example.com/hello/world';
|
||||
expect(makeFullUrl(correctResult, { baseUrl: '' })).toEqual(correctResult);
|
||||
expect(makeFullUrl('/hello/world', { baseUrl: 'https://example.com' })).toEqual(correctResult);
|
||||
expect(makeFullUrl('/hello/world', { baseUrl: 'https://example.com/' })).toEqual(correctResult);
|
||||
expect(makeFullUrl('hello/world', { baseUrl: 'https://example.com/' })).toEqual(correctResult);
|
||||
expect(makeFullUrl('hello/world', { baseUrl: 'https://example.com' })).toEqual(correctResult);
|
||||
expect(makeFullUrl('/world', { baseUrl: 'https://example.com/hello' })).toEqual(correctResult);
|
||||
expect(makeFullUrl('/world', { baseUrl: 'https://example.com/hello/' })).toEqual(correctResult);
|
||||
expect(makeFullUrl('world', { baseUrl: 'https://example.com/hello/' })).toEqual(correctResult);
|
||||
expect(makeFullUrl('world', { baseUrl: 'https://example.com/hello' })).toEqual(correctResult);
|
||||
expect(makeFullUrl('world?a=b', { baseUrl: 'https://example.com/hello' })).toEqual(
|
||||
'https://example.com/hello/world?a=b',
|
||||
);
|
||||
});
|
||||
|
||||
it('should throw with invalid baseurl combinations', () => {
|
||||
expect(() => makeFullUrl('example.com/hello/world', { baseUrl: '' })).toThrowError()
|
||||
expect(() => makeFullUrl('/hello/world', { baseUrl: 'example.com' })).toThrowError()
|
||||
expect(() => makeFullUrl('/hello/world', { baseUrl: 'tcp://example.com' })).toThrowError()
|
||||
expect(() => makeFullUrl('/hello/world', { baseUrl: 'tcp://example.com' })).toThrowError()
|
||||
})
|
||||
expect(() => makeFullUrl('example.com/hello/world', { baseUrl: '' })).toThrowError();
|
||||
expect(() => makeFullUrl('/hello/world', { baseUrl: 'example.com' })).toThrowError();
|
||||
expect(() => makeFullUrl('/hello/world', { baseUrl: 'tcp://example.com' })).toThrowError();
|
||||
expect(() => makeFullUrl('/hello/world', { baseUrl: 'tcp://example.com' })).toThrowError();
|
||||
});
|
||||
|
||||
it('should add/merge query parameters', () => {
|
||||
expect(makeFullUrl('https://example.com/hello/world', { query: { a: 'b' } })).toEqual("https://example.com/hello/world?a=b")
|
||||
expect(makeFullUrl('https://example.com/hello/world/', { query: { a: 'b' } })).toEqual("https://example.com/hello/world/?a=b")
|
||||
expect(makeFullUrl('https://example.com', { query: { a: 'b' } })).toEqual("https://example.com/?a=b")
|
||||
expect(makeFullUrl('https://example.com/', { query: { a: 'b' } })).toEqual("https://example.com/?a=b")
|
||||
expect(makeFullUrl('https://example.com/hello/world', { query: { a: 'b' } })).toEqual(
|
||||
'https://example.com/hello/world?a=b',
|
||||
);
|
||||
expect(makeFullUrl('https://example.com/hello/world/', { query: { a: 'b' } })).toEqual(
|
||||
'https://example.com/hello/world/?a=b',
|
||||
);
|
||||
expect(makeFullUrl('https://example.com', { query: { a: 'b' } })).toEqual('https://example.com/?a=b');
|
||||
expect(makeFullUrl('https://example.com/', { query: { a: 'b' } })).toEqual('https://example.com/?a=b');
|
||||
|
||||
expect(makeFullUrl('https://example.com/hello/world?c=d', { query: { a: 'b' } })).toEqual(
|
||||
'https://example.com/hello/world?c=d&a=b',
|
||||
);
|
||||
expect(makeFullUrl('https://example.com/hello/world?c=d', { query: {} })).toEqual(
|
||||
'https://example.com/hello/world?c=d',
|
||||
);
|
||||
expect(makeFullUrl('https://example.com/hello/world?c=d')).toEqual('https://example.com/hello/world?c=d');
|
||||
expect(makeFullUrl('https://example.com/hello/world?c=d', {})).toEqual('https://example.com/hello/world?c=d');
|
||||
});
|
||||
|
||||
expect(makeFullUrl('https://example.com/hello/world?c=d', { query: { a: 'b' } })).toEqual("https://example.com/hello/world?c=d&a=b")
|
||||
expect(makeFullUrl('https://example.com/hello/world?c=d', { query: {} })).toEqual("https://example.com/hello/world?c=d")
|
||||
expect(makeFullUrl('https://example.com/hello/world?c=d')).toEqual("https://example.com/hello/world?c=d")
|
||||
expect(makeFullUrl('https://example.com/hello/world?c=d', {})).toEqual("https://example.com/hello/world?c=d")
|
||||
})
|
||||
|
||||
it('should work with a mix of multiple options', () => {
|
||||
expect(makeFullUrl('/hello/world?c=d', { baseUrl: 'https://example.com/', query: { a: 'b' } })).toEqual("https://example.com/hello/world?c=d&a=b")
|
||||
})
|
||||
})
|
||||
expect(makeFullUrl('/hello/world?c=d', { baseUrl: 'https://example.com/', query: { a: 'b' } })).toEqual(
|
||||
'https://example.com/hello/world?c=d&a=b',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
@@ -1,138 +1,148 @@
|
||||
import { makeSimpleProxyFetcher } from "@/fetchers/simpleProxy";
|
||||
import { DefaultedFetcherOptions, FetcherOptions } from "@/fetchers/types";
|
||||
import { Headers } from "node-fetch";
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import { makeSimpleProxyFetcher } from '@/fetchers/simpleProxy';
|
||||
import { DefaultedFetcherOptions, FetcherOptions } from '@/fetchers/types';
|
||||
import { Headers } from 'node-fetch';
|
||||
import { afterEach, describe, expect, it, vi } from 'vitest';
|
||||
|
||||
describe("makeSimpleProxyFetcher()", () => {
|
||||
describe('makeSimpleProxyFetcher()', () => {
|
||||
const fetch = vi.fn();
|
||||
const fetcher = makeSimpleProxyFetcher("https://example.com/proxy", fetch);
|
||||
const fetcher = makeSimpleProxyFetcher('https://example.com/proxy', fetch);
|
||||
|
||||
afterEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
function setResult(type: "text" | "json", value: any) {
|
||||
if (type === 'text') return fetch.mockResolvedValueOnce({
|
||||
headers: new Headers({
|
||||
"content-type": "text/plain",
|
||||
}),
|
||||
status: 204,
|
||||
url: "test123",
|
||||
text() {
|
||||
return Promise.resolve(value);
|
||||
},
|
||||
});
|
||||
if (type === 'json') return fetch.mockResolvedValueOnce({
|
||||
headers: new Headers({
|
||||
"content-type": "application/json",
|
||||
}),
|
||||
status: 204,
|
||||
url: "test123",
|
||||
json() {
|
||||
return Promise.resolve(value);
|
||||
},
|
||||
});
|
||||
function setResult(type: 'text' | 'json', value: any) {
|
||||
if (type === 'text')
|
||||
return fetch.mockResolvedValueOnce({
|
||||
headers: new Headers({
|
||||
'content-type': 'text/plain',
|
||||
}),
|
||||
status: 204,
|
||||
url: 'test123',
|
||||
text() {
|
||||
return Promise.resolve(value);
|
||||
},
|
||||
});
|
||||
if (type === 'json')
|
||||
return fetch.mockResolvedValueOnce({
|
||||
headers: new Headers({
|
||||
'content-type': 'application/json',
|
||||
}),
|
||||
status: 204,
|
||||
url: 'test123',
|
||||
json() {
|
||||
return Promise.resolve(value);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function expectFetchCall(ops: { inputUrl: string, input: DefaultedFetcherOptions, outputUrl?: string, output: any, outputBody: any }) {
|
||||
function expectFetchCall(ops: {
|
||||
inputUrl: string;
|
||||
input: DefaultedFetcherOptions;
|
||||
outputUrl?: string;
|
||||
output: any;
|
||||
outputBody: any;
|
||||
}) {
|
||||
const prom = fetcher(ops.inputUrl, ops.input);
|
||||
expect((async () => (await prom).body)()).resolves.toEqual(ops.outputBody);
|
||||
expect((async () => (await prom).headers.entries())()).resolves.toEqual((new Headers()).entries());
|
||||
expect((async () => Array.from((await prom).headers.entries()))()).resolves.toEqual(
|
||||
Array.from(new Headers().entries()),
|
||||
);
|
||||
expect((async () => (await prom).statusCode)()).resolves.toEqual(204);
|
||||
expect((async () => (await prom).finalUrl)()).resolves.toEqual("test123");
|
||||
expect((async () => (await prom).finalUrl)()).resolves.toEqual('test123');
|
||||
expect(fetch).toBeCalledWith(ops.outputUrl ?? ops.inputUrl, ops.output);
|
||||
vi.clearAllMocks();
|
||||
}
|
||||
|
||||
it('should pass options through', () => {
|
||||
setResult("text", "hello world");
|
||||
setResult('text', 'hello world');
|
||||
expectFetchCall({
|
||||
inputUrl: "https://google.com",
|
||||
inputUrl: 'https://google.com',
|
||||
input: {
|
||||
method: "GET",
|
||||
method: 'GET',
|
||||
query: {},
|
||||
readHeaders: [],
|
||||
headers: {
|
||||
"X-Hello": "world",
|
||||
'X-Hello': 'world',
|
||||
},
|
||||
},
|
||||
outputUrl: `https://example.com/proxy?destination=${encodeURIComponent('https://google.com/')}`,
|
||||
output: {
|
||||
method: "GET",
|
||||
method: 'GET',
|
||||
headers: {
|
||||
"X-Hello": "world",
|
||||
'X-Hello': 'world',
|
||||
},
|
||||
},
|
||||
outputBody: "hello world"
|
||||
})
|
||||
setResult("text", "hello world");
|
||||
outputBody: 'hello world',
|
||||
});
|
||||
setResult('text', 'hello world');
|
||||
expectFetchCall({
|
||||
inputUrl: "https://google.com",
|
||||
inputUrl: 'https://google.com',
|
||||
input: {
|
||||
method: "GET",
|
||||
method: 'GET',
|
||||
headers: {},
|
||||
readHeaders: [],
|
||||
query: {
|
||||
"a": 'b',
|
||||
}
|
||||
a: 'b',
|
||||
},
|
||||
},
|
||||
outputUrl: `https://example.com/proxy?destination=${encodeURIComponent('https://google.com/?a=b')}`,
|
||||
output: {
|
||||
method: "GET",
|
||||
method: 'GET',
|
||||
headers: {},
|
||||
},
|
||||
outputBody: "hello world"
|
||||
})
|
||||
setResult("text", "hello world");
|
||||
outputBody: 'hello world',
|
||||
});
|
||||
setResult('text', 'hello world');
|
||||
expectFetchCall({
|
||||
inputUrl: "https://google.com",
|
||||
inputUrl: 'https://google.com',
|
||||
input: {
|
||||
method: "GET",
|
||||
method: 'GET',
|
||||
query: {},
|
||||
readHeaders: [],
|
||||
headers: {},
|
||||
},
|
||||
outputUrl: `https://example.com/proxy?destination=${encodeURIComponent('https://google.com/')}`,
|
||||
output: {
|
||||
method: "GET",
|
||||
method: 'GET',
|
||||
headers: {},
|
||||
},
|
||||
outputBody: "hello world"
|
||||
})
|
||||
outputBody: 'hello world',
|
||||
});
|
||||
});
|
||||
|
||||
it('should parse response correctly', () => {
|
||||
setResult("text", "hello world");
|
||||
setResult('text', 'hello world');
|
||||
expectFetchCall({
|
||||
inputUrl: "https://google.com/",
|
||||
inputUrl: 'https://google.com/',
|
||||
input: {
|
||||
method: "POST",
|
||||
method: 'POST',
|
||||
query: {},
|
||||
readHeaders: [],
|
||||
headers: {},
|
||||
},
|
||||
outputUrl: `https://example.com/proxy?destination=${encodeURIComponent('https://google.com/')}`,
|
||||
output: {
|
||||
method: "POST",
|
||||
method: 'POST',
|
||||
headers: {},
|
||||
},
|
||||
outputBody: "hello world"
|
||||
})
|
||||
setResult("json", { hello: 42 });
|
||||
expectFetchCall({
|
||||
inputUrl: "https://google.com/",
|
||||
input: {
|
||||
method: "POST",
|
||||
query: {},
|
||||
readHeaders: [],
|
||||
headers: {},
|
||||
},
|
||||
outputUrl: `https://example.com/proxy?destination=${encodeURIComponent('https://google.com/')}`,
|
||||
output: {
|
||||
method: "POST",
|
||||
headers: {},
|
||||
},
|
||||
outputBody: { hello: 42 }
|
||||
})
|
||||
outputBody: 'hello world',
|
||||
});
|
||||
// setResult("json", { hello: 42 });
|
||||
// expectFetchCall({
|
||||
// inputUrl: "https://google.com/",
|
||||
// input: {
|
||||
// method: "POST",
|
||||
// query: {},
|
||||
// readHeaders: [],
|
||||
// headers: {},
|
||||
// },
|
||||
// outputUrl: `https://example.com/proxy?destination=${encodeURIComponent('https://google.com/')}`,
|
||||
// output: {
|
||||
// method: "POST",
|
||||
// headers: {},
|
||||
// },
|
||||
// outputBody: { hello: 42 }
|
||||
// })
|
||||
});
|
||||
});
|
||||
|
@@ -1,9 +1,9 @@
|
||||
import { makeStandardFetcher } from "@/fetchers/standardFetch";
|
||||
import { DefaultedFetcherOptions } from "@/fetchers/types";
|
||||
import { Headers } from "node-fetch";
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import { makeStandardFetcher } from '@/fetchers/standardFetch';
|
||||
import { DefaultedFetcherOptions } from '@/fetchers/types';
|
||||
import { Headers } from 'node-fetch';
|
||||
import { afterEach, describe, expect, it, vi } from 'vitest';
|
||||
|
||||
describe("makeStandardFetcher()", () => {
|
||||
describe('makeStandardFetcher()', () => {
|
||||
const fetch = vi.fn();
|
||||
const fetcher = makeStandardFetcher(fetch);
|
||||
|
||||
@@ -11,129 +11,139 @@ describe("makeStandardFetcher()", () => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
function setResult(type: "text" | "json", value: any) {
|
||||
if (type === 'text') return fetch.mockResolvedValueOnce({
|
||||
headers: new Headers({
|
||||
"content-type": "text/plain",
|
||||
}),
|
||||
status: 204,
|
||||
url: "test123",
|
||||
text() {
|
||||
return Promise.resolve(value);
|
||||
},
|
||||
});
|
||||
if (type === 'json') return fetch.mockResolvedValueOnce({
|
||||
headers: new Headers({
|
||||
"content-type": "application/json",
|
||||
}),
|
||||
status: 204,
|
||||
url: "test123",
|
||||
json() {
|
||||
return Promise.resolve(value);
|
||||
},
|
||||
});
|
||||
function setResult(type: 'text' | 'json', value: any) {
|
||||
if (type === 'text')
|
||||
return fetch.mockResolvedValueOnce({
|
||||
headers: new Headers({
|
||||
'content-type': 'text/plain',
|
||||
}),
|
||||
status: 204,
|
||||
url: 'test123',
|
||||
text() {
|
||||
return Promise.resolve(value);
|
||||
},
|
||||
});
|
||||
if (type === 'json')
|
||||
return fetch.mockResolvedValueOnce({
|
||||
headers: new Headers({
|
||||
'content-type': 'application/json',
|
||||
}),
|
||||
status: 204,
|
||||
url: 'test123',
|
||||
json() {
|
||||
return Promise.resolve(value);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function expectFetchCall(ops: { inputUrl: string, input: DefaultedFetcherOptions, outputUrl?: string, output: any, outputBody: any }) {
|
||||
function expectFetchCall(ops: {
|
||||
inputUrl: string;
|
||||
input: DefaultedFetcherOptions;
|
||||
outputUrl?: string;
|
||||
output: any;
|
||||
outputBody: any;
|
||||
}) {
|
||||
const prom = fetcher(ops.inputUrl, ops.input);
|
||||
expect((async () => (await prom).body)()).resolves.toEqual(ops.outputBody);
|
||||
expect((async () => (await prom).headers.entries())()).resolves.toEqual((new Headers()).entries());
|
||||
expect((async () => Array.from((await prom).headers.entries()))()).resolves.toEqual(
|
||||
Array.from(new Headers().entries()),
|
||||
);
|
||||
expect((async () => (await prom).statusCode)()).resolves.toEqual(204);
|
||||
expect((async () => (await prom).finalUrl)()).resolves.toEqual("test123");
|
||||
expect((async () => (await prom).finalUrl)()).resolves.toEqual('test123');
|
||||
expect(fetch).toBeCalledWith(ops.outputUrl ?? ops.inputUrl, ops.output);
|
||||
vi.clearAllMocks();
|
||||
}
|
||||
|
||||
it('should pass options through', () => {
|
||||
setResult("text", "hello world");
|
||||
setResult('text', 'hello world');
|
||||
expectFetchCall({
|
||||
inputUrl: "https://google.com",
|
||||
inputUrl: 'https://google.com',
|
||||
input: {
|
||||
method: "GET",
|
||||
method: 'GET',
|
||||
query: {},
|
||||
readHeaders: [],
|
||||
headers: {
|
||||
"X-Hello": "world",
|
||||
'X-Hello': 'world',
|
||||
},
|
||||
},
|
||||
outputUrl: "https://google.com/",
|
||||
outputUrl: 'https://google.com/',
|
||||
output: {
|
||||
method: "GET",
|
||||
method: 'GET',
|
||||
headers: {
|
||||
"X-Hello": "world",
|
||||
'X-Hello': 'world',
|
||||
},
|
||||
body: undefined,
|
||||
},
|
||||
outputBody: "hello world"
|
||||
})
|
||||
setResult("text", "hello world");
|
||||
outputBody: 'hello world',
|
||||
});
|
||||
setResult('text', 'hello world');
|
||||
expectFetchCall({
|
||||
inputUrl: "https://google.com",
|
||||
inputUrl: 'https://google.com',
|
||||
input: {
|
||||
method: "GET",
|
||||
method: 'GET',
|
||||
headers: {},
|
||||
readHeaders: [],
|
||||
query: {
|
||||
"a": 'b',
|
||||
}
|
||||
a: 'b',
|
||||
},
|
||||
},
|
||||
outputUrl: "https://google.com/?a=b",
|
||||
outputUrl: 'https://google.com/?a=b',
|
||||
output: {
|
||||
method: "GET",
|
||||
method: 'GET',
|
||||
headers: {},
|
||||
},
|
||||
outputBody: "hello world"
|
||||
})
|
||||
setResult("text", "hello world");
|
||||
outputBody: 'hello world',
|
||||
});
|
||||
setResult('text', 'hello world');
|
||||
expectFetchCall({
|
||||
inputUrl: "https://google.com",
|
||||
inputUrl: 'https://google.com',
|
||||
input: {
|
||||
query: {},
|
||||
headers: {},
|
||||
readHeaders: [],
|
||||
method: "GET"
|
||||
method: 'GET',
|
||||
},
|
||||
outputUrl: "https://google.com/",
|
||||
outputUrl: 'https://google.com/',
|
||||
output: {
|
||||
method: "GET",
|
||||
method: 'GET',
|
||||
headers: {},
|
||||
},
|
||||
outputBody: "hello world"
|
||||
})
|
||||
outputBody: 'hello world',
|
||||
});
|
||||
});
|
||||
|
||||
it('should parse response correctly', () => {
|
||||
setResult("text", "hello world");
|
||||
setResult('text', 'hello world');
|
||||
expectFetchCall({
|
||||
inputUrl: "https://google.com/",
|
||||
inputUrl: 'https://google.com/',
|
||||
input: {
|
||||
query: {},
|
||||
headers: {},
|
||||
readHeaders: [],
|
||||
method: "POST"
|
||||
method: 'POST',
|
||||
},
|
||||
outputUrl: "https://google.com/",
|
||||
outputUrl: 'https://google.com/',
|
||||
output: {
|
||||
method: "POST",
|
||||
method: 'POST',
|
||||
headers: {},
|
||||
},
|
||||
outputBody: "hello world"
|
||||
})
|
||||
setResult("json", { hello: 42 });
|
||||
outputBody: 'hello world',
|
||||
});
|
||||
setResult('json', { hello: 42 });
|
||||
expectFetchCall({
|
||||
inputUrl: "https://google.com/",
|
||||
inputUrl: 'https://google.com/',
|
||||
input: {
|
||||
query: {},
|
||||
headers: {},
|
||||
readHeaders: [],
|
||||
method: "POST"
|
||||
method: 'POST',
|
||||
},
|
||||
outputUrl: "https://google.com/",
|
||||
outputUrl: 'https://google.com/',
|
||||
output: {
|
||||
method: "POST",
|
||||
method: 'POST',
|
||||
headers: {},
|
||||
},
|
||||
outputBody: { hello: 42 }
|
||||
})
|
||||
outputBody: { hello: 42 },
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@@ -9,8 +9,8 @@ vi.mock('@/providers/all', () => mocks);
|
||||
|
||||
const features: FeatureMap = {
|
||||
requires: [],
|
||||
disallowed: []
|
||||
}
|
||||
disallowed: [],
|
||||
};
|
||||
|
||||
describe('getProviders()', () => {
|
||||
afterEach(() => {
|
||||
@@ -20,10 +20,12 @@ describe('getProviders()', () => {
|
||||
it('should return providers', () => {
|
||||
mocks.gatherAllEmbeds.mockReturnValue([mockEmbeds.embedD]);
|
||||
mocks.gatherAllSources.mockReturnValue([mockSources.sourceA, mockSources.sourceB]);
|
||||
expect(getProviders(features, {
|
||||
embeds: getBuiltinEmbeds(),
|
||||
sources: getBuiltinSources(),
|
||||
})).toEqual({
|
||||
expect(
|
||||
getProviders(features, {
|
||||
embeds: getBuiltinEmbeds(),
|
||||
sources: getBuiltinSources(),
|
||||
}),
|
||||
).toEqual({
|
||||
sources: [mockSources.sourceA, mockSources.sourceB],
|
||||
embeds: [mockEmbeds.embedD],
|
||||
});
|
||||
@@ -32,10 +34,12 @@ describe('getProviders()', () => {
|
||||
it('should filter out disabled providers', () => {
|
||||
mocks.gatherAllEmbeds.mockReturnValue([mockEmbeds.embedD, mockEmbeds.embedEDisabled]);
|
||||
mocks.gatherAllSources.mockReturnValue([mockSources.sourceA, mockSources.sourceCDisabled, mockSources.sourceB]);
|
||||
expect(getProviders(features,{
|
||||
embeds: getBuiltinEmbeds(),
|
||||
sources: getBuiltinSources(),
|
||||
})).toEqual({
|
||||
expect(
|
||||
getProviders(features, {
|
||||
embeds: getBuiltinEmbeds(),
|
||||
sources: getBuiltinSources(),
|
||||
}),
|
||||
).toEqual({
|
||||
sources: [mockSources.sourceA, mockSources.sourceB],
|
||||
embeds: [mockEmbeds.embedD],
|
||||
});
|
||||
@@ -44,46 +48,56 @@ describe('getProviders()', () => {
|
||||
it('should throw on duplicate ids in sources', () => {
|
||||
mocks.gatherAllEmbeds.mockReturnValue([]);
|
||||
mocks.gatherAllSources.mockReturnValue([mockSources.sourceAHigherRank, mockSources.sourceA, mockSources.sourceB]);
|
||||
expect(() => getProviders(features,{
|
||||
embeds: getBuiltinEmbeds(),
|
||||
sources: getBuiltinSources(),
|
||||
})).toThrowError();
|
||||
expect(() =>
|
||||
getProviders(features, {
|
||||
embeds: getBuiltinEmbeds(),
|
||||
sources: getBuiltinSources(),
|
||||
}),
|
||||
).toThrowError();
|
||||
});
|
||||
|
||||
it('should throw on duplicate ids in embeds', () => {
|
||||
mocks.gatherAllEmbeds.mockReturnValue([mockEmbeds.embedD, mockEmbeds.embedDHigherRank, mockEmbeds.embedA]);
|
||||
mocks.gatherAllSources.mockReturnValue([]);
|
||||
expect(() => getProviders(features,{
|
||||
embeds: getBuiltinEmbeds(),
|
||||
sources: getBuiltinSources(),
|
||||
})).toThrowError();
|
||||
expect(() =>
|
||||
getProviders(features, {
|
||||
embeds: getBuiltinEmbeds(),
|
||||
sources: getBuiltinSources(),
|
||||
}),
|
||||
).toThrowError();
|
||||
});
|
||||
|
||||
it('should throw on duplicate ids between sources and embeds', () => {
|
||||
mocks.gatherAllEmbeds.mockReturnValue([mockEmbeds.embedD, mockEmbeds.embedA]);
|
||||
mocks.gatherAllSources.mockReturnValue([mockSources.sourceA, mockSources.sourceB]);
|
||||
expect(() => getProviders(features,{
|
||||
embeds: getBuiltinEmbeds(),
|
||||
sources: getBuiltinSources(),
|
||||
})).toThrowError();
|
||||
expect(() =>
|
||||
getProviders(features, {
|
||||
embeds: getBuiltinEmbeds(),
|
||||
sources: getBuiltinSources(),
|
||||
}),
|
||||
).toThrowError();
|
||||
});
|
||||
|
||||
it('should throw on duplicate rank between sources and embeds', () => {
|
||||
mocks.gatherAllEmbeds.mockReturnValue([mockEmbeds.embedD, mockEmbeds.embedA]);
|
||||
mocks.gatherAllSources.mockReturnValue([mockSources.sourceA, mockSources.sourceB]);
|
||||
expect(() => getProviders(features,{
|
||||
embeds: getBuiltinEmbeds(),
|
||||
sources: getBuiltinSources(),
|
||||
})).toThrowError();
|
||||
expect(() =>
|
||||
getProviders(features, {
|
||||
embeds: getBuiltinEmbeds(),
|
||||
sources: getBuiltinSources(),
|
||||
}),
|
||||
).toThrowError();
|
||||
});
|
||||
|
||||
it('should not throw with same rank between sources and embeds', () => {
|
||||
mocks.gatherAllEmbeds.mockReturnValue([mockEmbeds.embedD, mockEmbeds.embedHSameRankAsSourceA]);
|
||||
mocks.gatherAllSources.mockReturnValue([mockSources.sourceA, mockSources.sourceB]);
|
||||
expect(getProviders(features,{
|
||||
embeds: getBuiltinEmbeds(),
|
||||
sources: getBuiltinSources(),
|
||||
})).toEqual({
|
||||
expect(
|
||||
getProviders(features, {
|
||||
embeds: getBuiltinEmbeds(),
|
||||
sources: getBuiltinSources(),
|
||||
}),
|
||||
).toEqual({
|
||||
sources: [mockSources.sourceA, mockSources.sourceB],
|
||||
embeds: [mockEmbeds.embedD, mockEmbeds.embedHSameRankAsSourceA],
|
||||
});
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import { FeatureMap, Flags, flags, flagsAllowedInFeatures } from "@/entrypoint/utils/targets";
|
||||
import { describe, it, expect } from "vitest";
|
||||
import { FeatureMap, Flags, flags, flagsAllowedInFeatures } from '@/entrypoint/utils/targets';
|
||||
import { describe, it, expect } from 'vitest';
|
||||
|
||||
describe('flagsAllowedInFeatures()', () => {
|
||||
function checkFeatures(featureMap: FeatureMap, flags: Flags[], output: boolean) {
|
||||
@@ -7,71 +7,131 @@ describe('flagsAllowedInFeatures()', () => {
|
||||
}
|
||||
|
||||
it('should check required correctly', () => {
|
||||
checkFeatures({
|
||||
requires: [],
|
||||
disallowed: []
|
||||
}, [], true);
|
||||
checkFeatures({
|
||||
requires: [flags.CORS_ALLOWED],
|
||||
disallowed: []
|
||||
}, [flags.CORS_ALLOWED], true);
|
||||
checkFeatures({
|
||||
requires: [flags.CORS_ALLOWED],
|
||||
disallowed: []
|
||||
}, [], false);
|
||||
checkFeatures({
|
||||
requires: [flags.CORS_ALLOWED, flags.IP_LOCKED],
|
||||
disallowed: []
|
||||
}, [flags.CORS_ALLOWED, flags.IP_LOCKED], true);
|
||||
checkFeatures({
|
||||
requires: [flags.IP_LOCKED],
|
||||
disallowed: []
|
||||
}, [flags.CORS_ALLOWED], false);
|
||||
checkFeatures({
|
||||
requires: [flags.IP_LOCKED],
|
||||
disallowed: []
|
||||
}, [], false);
|
||||
checkFeatures(
|
||||
{
|
||||
requires: [],
|
||||
disallowed: [],
|
||||
},
|
||||
[],
|
||||
true,
|
||||
);
|
||||
checkFeatures(
|
||||
{
|
||||
requires: [flags.CORS_ALLOWED],
|
||||
disallowed: [],
|
||||
},
|
||||
[flags.CORS_ALLOWED],
|
||||
true,
|
||||
);
|
||||
checkFeatures(
|
||||
{
|
||||
requires: [flags.CORS_ALLOWED],
|
||||
disallowed: [],
|
||||
},
|
||||
[],
|
||||
false,
|
||||
);
|
||||
checkFeatures(
|
||||
{
|
||||
requires: [flags.CORS_ALLOWED, flags.IP_LOCKED],
|
||||
disallowed: [],
|
||||
},
|
||||
[flags.CORS_ALLOWED, flags.IP_LOCKED],
|
||||
true,
|
||||
);
|
||||
checkFeatures(
|
||||
{
|
||||
requires: [flags.IP_LOCKED],
|
||||
disallowed: [],
|
||||
},
|
||||
[flags.CORS_ALLOWED],
|
||||
false,
|
||||
);
|
||||
checkFeatures(
|
||||
{
|
||||
requires: [flags.IP_LOCKED],
|
||||
disallowed: [],
|
||||
},
|
||||
[],
|
||||
false,
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
it('should check disallowed correctly', () => {
|
||||
checkFeatures({
|
||||
requires: [],
|
||||
disallowed: []
|
||||
}, [], true);
|
||||
checkFeatures({
|
||||
requires: [],
|
||||
disallowed: [flags.CORS_ALLOWED]
|
||||
}, [], true);
|
||||
checkFeatures({
|
||||
requires: [],
|
||||
disallowed: [flags.CORS_ALLOWED]
|
||||
}, [flags.CORS_ALLOWED], false);
|
||||
checkFeatures({
|
||||
requires: [],
|
||||
disallowed: [flags.CORS_ALLOWED]
|
||||
}, [flags.IP_LOCKED], true);
|
||||
checkFeatures({
|
||||
requires: [],
|
||||
disallowed: [flags.CORS_ALLOWED, flags.IP_LOCKED]
|
||||
}, [flags.CORS_ALLOWED], false);
|
||||
checkFeatures(
|
||||
{
|
||||
requires: [],
|
||||
disallowed: [],
|
||||
},
|
||||
[],
|
||||
true,
|
||||
);
|
||||
checkFeatures(
|
||||
{
|
||||
requires: [],
|
||||
disallowed: [flags.CORS_ALLOWED],
|
||||
},
|
||||
[],
|
||||
true,
|
||||
);
|
||||
checkFeatures(
|
||||
{
|
||||
requires: [],
|
||||
disallowed: [flags.CORS_ALLOWED],
|
||||
},
|
||||
[flags.CORS_ALLOWED],
|
||||
false,
|
||||
);
|
||||
checkFeatures(
|
||||
{
|
||||
requires: [],
|
||||
disallowed: [flags.CORS_ALLOWED],
|
||||
},
|
||||
[flags.IP_LOCKED],
|
||||
true,
|
||||
);
|
||||
checkFeatures(
|
||||
{
|
||||
requires: [],
|
||||
disallowed: [flags.CORS_ALLOWED, flags.IP_LOCKED],
|
||||
},
|
||||
[flags.CORS_ALLOWED],
|
||||
false,
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
it('should pass mixed tests', () => {
|
||||
checkFeatures({
|
||||
requires: [flags.CORS_ALLOWED],
|
||||
disallowed: [flags.IP_LOCKED]
|
||||
}, [], false);
|
||||
checkFeatures({
|
||||
requires: [flags.CORS_ALLOWED],
|
||||
disallowed: [flags.IP_LOCKED]
|
||||
}, [flags.CORS_ALLOWED], true);
|
||||
checkFeatures({
|
||||
requires: [flags.CORS_ALLOWED],
|
||||
disallowed: [flags.IP_LOCKED]
|
||||
}, [flags.IP_LOCKED], false);
|
||||
checkFeatures({
|
||||
requires: [flags.CORS_ALLOWED],
|
||||
disallowed: [flags.IP_LOCKED]
|
||||
}, [flags.IP_LOCKED, flags.CORS_ALLOWED], false);
|
||||
checkFeatures(
|
||||
{
|
||||
requires: [flags.CORS_ALLOWED],
|
||||
disallowed: [flags.IP_LOCKED],
|
||||
},
|
||||
[],
|
||||
false,
|
||||
);
|
||||
checkFeatures(
|
||||
{
|
||||
requires: [flags.CORS_ALLOWED],
|
||||
disallowed: [flags.IP_LOCKED],
|
||||
},
|
||||
[flags.CORS_ALLOWED],
|
||||
true,
|
||||
);
|
||||
checkFeatures(
|
||||
{
|
||||
requires: [flags.CORS_ALLOWED],
|
||||
disallowed: [flags.IP_LOCKED],
|
||||
},
|
||||
[flags.IP_LOCKED],
|
||||
false,
|
||||
);
|
||||
checkFeatures(
|
||||
{
|
||||
requires: [flags.CORS_ALLOWED],
|
||||
disallowed: [flags.IP_LOCKED],
|
||||
},
|
||||
[flags.IP_LOCKED, flags.CORS_ALLOWED],
|
||||
false,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
@@ -1,16 +1,16 @@
|
||||
import { reorderOnIdList } from "@/utils/list";
|
||||
import { describe, it, expect } from "vitest";
|
||||
import { reorderOnIdList } from '@/utils/list';
|
||||
import { describe, it, expect } from 'vitest';
|
||||
|
||||
function list(def: string) {
|
||||
return def.split(",").map(v=>({
|
||||
return def.split(',').map((v) => ({
|
||||
rank: parseInt(v),
|
||||
id: v,
|
||||
}))
|
||||
}));
|
||||
}
|
||||
|
||||
function expectListToEqual(l1: ReturnType<typeof list>, l2: ReturnType<typeof list>) {
|
||||
function flatten(l: ReturnType<typeof list>) {
|
||||
return l.map(v=>v.id).join(",");
|
||||
return l.map((v) => v.id).join(',');
|
||||
}
|
||||
expect(flatten(l1)).toEqual(flatten(l2));
|
||||
}
|
||||
@@ -18,36 +18,36 @@ function expectListToEqual(l1: ReturnType<typeof list>, l2: ReturnType<typeof li
|
||||
describe('reorderOnIdList()', () => {
|
||||
it('should reorder based on rank', () => {
|
||||
const l = list('2,1,4,3');
|
||||
const sortedList = list('4,3,2,1')
|
||||
const sortedList = list('4,3,2,1');
|
||||
expectListToEqual(reorderOnIdList([], l), sortedList);
|
||||
});
|
||||
|
||||
it('should work with empty input', () => {
|
||||
expectListToEqual(reorderOnIdList([], []), []);
|
||||
});
|
||||
|
||||
|
||||
it('should reorder based on id list', () => {
|
||||
const l = list('4,2,1,3');
|
||||
const sortedList = list('4,3,2,1')
|
||||
expectListToEqual(reorderOnIdList(["4","3","2","1"], l), sortedList);
|
||||
const sortedList = list('4,3,2,1');
|
||||
expectListToEqual(reorderOnIdList(['4', '3', '2', '1'], l), sortedList);
|
||||
});
|
||||
|
||||
|
||||
it('should reorder based on id list and rank second', () => {
|
||||
const l = list('4,2,1,3');
|
||||
const sortedList = list('4,3,2,1')
|
||||
expectListToEqual(reorderOnIdList(["4","3"], l), sortedList);
|
||||
const sortedList = list('4,3,2,1');
|
||||
expectListToEqual(reorderOnIdList(['4', '3'], l), sortedList);
|
||||
});
|
||||
|
||||
|
||||
it('should work with only one item', () => {
|
||||
const l = list('1');
|
||||
const sortedList = list('1')
|
||||
expectListToEqual(reorderOnIdList(["1"], l), sortedList);
|
||||
const sortedList = list('1');
|
||||
expectListToEqual(reorderOnIdList(['1'], l), sortedList);
|
||||
expectListToEqual(reorderOnIdList([], l), sortedList);
|
||||
});
|
||||
|
||||
it('should not affect original list', () => {
|
||||
const l = list('4,3,2,1');
|
||||
const unsortedList = list('4,3,2,1')
|
||||
const unsortedList = list('4,3,2,1');
|
||||
reorderOnIdList([], l);
|
||||
expectListToEqual(l, unsortedList);
|
||||
});
|
||||
|
@@ -1,65 +1,71 @@
|
||||
import { makeStandardFetcher } from "@/fetchers/standardFetch";
|
||||
import { makeProviders } from "@/main/builder";
|
||||
import { targets } from "@/main/targets";
|
||||
import { isValidStream } from "@/utils/valid";
|
||||
import fetch from "node-fetch";
|
||||
import { describe, it, expect } from "vitest";
|
||||
import { isValidStream } from '@/utils/valid';
|
||||
import { describe, it, expect } from 'vitest';
|
||||
|
||||
describe('isValidStream()', () => {
|
||||
it('should pass valid streams', () => {
|
||||
expect(isValidStream({
|
||||
type: "file",
|
||||
id: "a",
|
||||
flags: [],
|
||||
captions: [],
|
||||
qualities: {
|
||||
"1080": {
|
||||
type: "mp4",
|
||||
url: "hello-world"
|
||||
}
|
||||
}
|
||||
})).toBe(true);
|
||||
expect(isValidStream({
|
||||
type: "hls",
|
||||
id: "a",
|
||||
flags: [],
|
||||
captions: [],
|
||||
playlist: "hello-world"
|
||||
})).toBe(true);
|
||||
expect(
|
||||
isValidStream({
|
||||
type: 'file',
|
||||
id: 'a',
|
||||
flags: [],
|
||||
captions: [],
|
||||
qualities: {
|
||||
'1080': {
|
||||
type: 'mp4',
|
||||
url: 'hello-world',
|
||||
},
|
||||
},
|
||||
}),
|
||||
).toBe(true);
|
||||
expect(
|
||||
isValidStream({
|
||||
type: 'hls',
|
||||
id: 'a',
|
||||
flags: [],
|
||||
captions: [],
|
||||
playlist: 'hello-world',
|
||||
}),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it('should detect empty qualities', () => {
|
||||
expect(isValidStream({
|
||||
type: "file",
|
||||
id: "a",
|
||||
flags: [],
|
||||
captions: [],
|
||||
qualities: {}
|
||||
})).toBe(false);
|
||||
expect(
|
||||
isValidStream({
|
||||
type: 'file',
|
||||
id: 'a',
|
||||
flags: [],
|
||||
captions: [],
|
||||
qualities: {},
|
||||
}),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
|
||||
it('should detect empty stream urls', () => {
|
||||
expect(isValidStream({
|
||||
type: "file",
|
||||
id: "a",
|
||||
flags: [],
|
||||
captions: [],
|
||||
qualities: {
|
||||
"1080": {
|
||||
type: "mp4",
|
||||
url: "",
|
||||
}
|
||||
}
|
||||
})).toBe(false);
|
||||
expect(
|
||||
isValidStream({
|
||||
type: 'file',
|
||||
id: 'a',
|
||||
flags: [],
|
||||
captions: [],
|
||||
qualities: {
|
||||
'1080': {
|
||||
type: 'mp4',
|
||||
url: '',
|
||||
},
|
||||
},
|
||||
}),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
|
||||
it('should detect emtpy HLS playlists', () => {
|
||||
expect(isValidStream({
|
||||
type: "hls",
|
||||
id: "a",
|
||||
flags: [],
|
||||
captions: [],
|
||||
playlist: "",
|
||||
})).toBe(false);
|
||||
expect(
|
||||
isValidStream({
|
||||
type: 'hls',
|
||||
id: 'a',
|
||||
flags: [],
|
||||
captions: [],
|
||||
playlist: '',
|
||||
}),
|
||||
).toBe(false);
|
||||
});
|
||||
});
|
||||
|
@@ -179,7 +179,11 @@ async function runCommandLine() {
|
||||
}
|
||||
|
||||
if (process.argv.length === 2) {
|
||||
runQuestions().catch(() => console.error('Exited.'));
|
||||
runQuestions()
|
||||
.catch(() => console.error('Exited.'))
|
||||
.finally(() => process.exit(0));
|
||||
} else {
|
||||
runCommandLine().catch(() => console.error('Exited.'));
|
||||
runCommandLine()
|
||||
.catch(() => console.error('Exited.'))
|
||||
.finally(() => process.exit(0));
|
||||
}
|
||||
|
@@ -19,7 +19,7 @@ async function runBrowserScraping(
|
||||
source: MetaOutput,
|
||||
options: CommandLineArguments,
|
||||
) {
|
||||
if (!existsSync(join(__dirname, '../../lib/index.mjs')))
|
||||
if (!existsSync(join(__dirname, '../../lib/index.js')))
|
||||
throw new Error('Please compile before running cli in browser mode');
|
||||
const config = getConfig();
|
||||
if (!config.proxyUrl)
|
||||
@@ -37,13 +37,15 @@ async function runBrowserScraping(
|
||||
root,
|
||||
});
|
||||
browser = await puppeteer.launch({
|
||||
headless: 'new',
|
||||
headless: true,
|
||||
args: ['--no-sandbox', '--disable-setuid-sandbox'],
|
||||
});
|
||||
const page = await browser.newPage();
|
||||
// This is the dev cli, so we can use console.log
|
||||
// eslint-disable-next-line no-console
|
||||
page.on('console', (message) => console.log(`${message.type().slice(0, 3).toUpperCase()} ${message.text()}`));
|
||||
|
||||
if (!server.resolvedUrls?.local.length) throw new Error('Server did not start');
|
||||
await page.goto(server.resolvedUrls.local[0]);
|
||||
await page.waitForFunction('!!window.scrape', { timeout: 5000 });
|
||||
|
||||
|
@@ -146,13 +146,16 @@ export const streamsbScraper = makeEmbed({
|
||||
|
||||
ctx.progress(80);
|
||||
|
||||
const qualities = dls.reduce((a, v) => {
|
||||
a[v.quality] = {
|
||||
type: 'mp4',
|
||||
url: v.url as string,
|
||||
};
|
||||
return a;
|
||||
}, {} as Record<string, StreamFile>);
|
||||
const qualities = dls.reduce(
|
||||
(a, v) => {
|
||||
a[v.quality] = {
|
||||
type: 'mp4',
|
||||
url: v.url as string,
|
||||
};
|
||||
return a;
|
||||
},
|
||||
{} as Record<string, StreamFile>,
|
||||
);
|
||||
|
||||
return {
|
||||
stream: [
|
||||
|
Reference in New Issue
Block a user