@norskvideo/ctl-test-harness 0.1.1 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/studio-state.d.ts +3 -0
- package/studio-state.js +53 -1
package/package.json
CHANGED
package/studio-state.d.ts
CHANGED
|
@@ -7,6 +7,8 @@ export interface ComponentsResponse {
|
|
|
7
7
|
components: ComponentSummary[];
|
|
8
8
|
totalComponents: number;
|
|
9
9
|
}
|
|
10
|
+
export declare function applyTestHost(rawUrl: string): string;
|
|
11
|
+
export declare function mediaDirectUrl(rawUrl: string): string;
|
|
10
12
|
export declare function fetchComponents(studioHostPort: number): Promise<ComponentsResponse | null>;
|
|
11
13
|
export declare function fetchComponentState(studioHostPort: number, componentId: string): Promise<unknown | null>;
|
|
12
14
|
/** SRT-listener state shape — see
|
|
@@ -92,6 +94,7 @@ export declare function assertMultivariantHasRenditions(opts: {
|
|
|
92
94
|
expectedRenditionLabels: readonly string[];
|
|
93
95
|
timeoutMs?: number;
|
|
94
96
|
intervalMs?: number;
|
|
97
|
+
resolveFetchUrl?: (url: string) => string;
|
|
95
98
|
}): Promise<void>;
|
|
96
99
|
export declare function assertNoUnmapped(opts: {
|
|
97
100
|
studioHostPort: number;
|
package/studio-state.js
CHANGED
|
@@ -23,6 +23,57 @@
|
|
|
23
23
|
// alias: set NORSK_TEST_HOST=host.docker.internal there. Daemon-port fetches are
|
|
24
24
|
// deliberately left on localhost — the daemon runs in-process with the tests.
|
|
25
25
|
const STUDIO_HOST = process.env.NORSK_TEST_HOST ?? "localhost";
|
|
26
|
+
// Studio reports absolute playback URLs (the HLS multivariant, WHIP publish
|
|
27
|
+
// endpoints, ...) with the host it was configured with — loopback in a local
|
|
28
|
+
// run. In DooD CI the test process is inside a container and cannot reach that
|
|
29
|
+
// loopback; the published port lives on the host-gateway alias. Callers that
|
|
30
|
+
// fetch a server-reported URL verbatim must route it through here so a loopback
|
|
31
|
+
// host gets swapped for NORSK_TEST_HOST. No env / non-loopback host / unparseable
|
|
32
|
+
// input all pass through unchanged. Read from the env at call time (not the
|
|
33
|
+
// module-level STUDIO_HOST) so tests can toggle it.
|
|
34
|
+
export function applyTestHost(rawUrl) {
|
|
35
|
+
const testHost = process.env.NORSK_TEST_HOST;
|
|
36
|
+
if (!testHost)
|
|
37
|
+
return rawUrl;
|
|
38
|
+
try {
|
|
39
|
+
const u = new URL(rawUrl);
|
|
40
|
+
if (u.hostname === "localhost" || u.hostname === "127.0.0.1" || u.hostname === "::1") {
|
|
41
|
+
u.hostname = testHost;
|
|
42
|
+
return u.toString();
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
// not a parseable absolute URL — leave it for the caller's own error path
|
|
47
|
+
}
|
|
48
|
+
return rawUrl;
|
|
49
|
+
}
|
|
50
|
+
// The default norsk media HTTP port inside the container. The daemon's nginx
|
|
51
|
+
// proxies `/instance/<id>/media/*` here; whip-driver hits the same port direct.
|
|
52
|
+
const MEDIA_HTTP_PORT = 8080;
|
|
53
|
+
// Rewrite a daemon-proxy-routed media URL to a direct hit on the Norsk media
|
|
54
|
+
// container over the daemon's `norsk-net` bridge. Studio advertises playback
|
|
55
|
+
// URLs as `http://<publicHost>/instance/<id>/media/<native>` — that route is
|
|
56
|
+
// served ONLY by the daemon's nginx proxy. A harness that runs proxy-less (and
|
|
57
|
+
// whose runner has joined norsk-net) can instead reach the media container
|
|
58
|
+
// directly by its compose service name: `http://<id>-media-1:8080/<native>`.
|
|
59
|
+
// The `/instance/<id>/media` prefix is the proxy's routing concern; Norsk's
|
|
60
|
+
// native path is what follows it. Falls back to applyTestHost for URLs that
|
|
61
|
+
// don't carry the proxy prefix. Mirrors whip-driver's dockerNetUrl.
|
|
62
|
+
export function mediaDirectUrl(rawUrl) {
|
|
63
|
+
try {
|
|
64
|
+
const u = new URL(rawUrl);
|
|
65
|
+
const m = u.pathname.match(/^\/instance\/([^/]+)\/media(\/.*)?$/);
|
|
66
|
+
if (m) {
|
|
67
|
+
const id = m[1];
|
|
68
|
+
const rest = m[2] ?? "/";
|
|
69
|
+
return `http://${id}-media-1:${MEDIA_HTTP_PORT}${rest}${u.search}`;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
// not a parseable URL — fall through
|
|
74
|
+
}
|
|
75
|
+
return applyTestHost(rawUrl);
|
|
76
|
+
}
|
|
26
77
|
export async function fetchComponents(studioHostPort) {
|
|
27
78
|
const r = await fetch(`http://${STUDIO_HOST}:${studioHostPort}/live/api/components`, {
|
|
28
79
|
signal: AbortSignal.timeout(5000),
|
|
@@ -158,6 +209,7 @@ export async function assertSrtConnected(opts) {
|
|
|
158
209
|
* `#EXT-X-MEDIA:TYPE=AUDIO ... URI="<rendition>/norsk.m3u8"` line. The caller
|
|
159
210
|
* passes the set of expected labels; the body must reference every one. */
|
|
160
211
|
export async function assertMultivariantHasRenditions(opts) {
|
|
212
|
+
const resolveFetchUrl = opts.resolveFetchUrl ?? applyTestHost;
|
|
161
213
|
let lastState = null;
|
|
162
214
|
let lastBody = null;
|
|
163
215
|
let lastFetchStatus = null;
|
|
@@ -169,7 +221,7 @@ export async function assertMultivariantHasRenditions(opts) {
|
|
|
169
221
|
if (!state?.url)
|
|
170
222
|
return false;
|
|
171
223
|
try {
|
|
172
|
-
const r = await fetch(state.url, { signal: AbortSignal.timeout(5000) });
|
|
224
|
+
const r = await fetch(resolveFetchUrl(state.url), { signal: AbortSignal.timeout(5000) });
|
|
173
225
|
lastFetchStatus = r.status;
|
|
174
226
|
if (!r.ok)
|
|
175
227
|
return false;
|