mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-09 17:36:15 -08:00
test(playback): stub the inline player in the VOD details spec (#1440)
`VodDetailsComponent` specs imported the real component tree, so every `createComponent` pulled in `PortalInlinePlayerComponent` -> `WebPlayerViewComponent` -> ArtPlayer, video.js and the embedded-MPV bridge, and instantiated all of it. The suite's slowest test measured 2521ms idle on a 10-core machine -- a 2.0x margin against Jest's 5000ms default, thin enough that a loaded worker failed tests that had no defect behind them. Swap the inline player for a stand-in that mirrors the selector and the template's bindings; the specs only assert what the host hands the player. Worst test drops 2521ms -> 306ms and the summed test time 3427ms -> 632ms. Assertions are unchanged. Also raise testTimeout to 15s for the shared web-ESM config. The 5s default is thin for Angular component specs generally: TestBed compiles and instantiates a real tree per test, and CI runners are much slower per-core than a dev machine. This is headroom, not a mute -- a spec that genuinely hangs still fails, just later. Attribution, full suite at --maxWorkers=48 on 10 cores: - forced back to 5000ms: VodDetails no longer fails (it did before this change); HtmlVideoPlayer still does, which is what the timeout covers - shipped 15000ms: 2/2 runs, 975/975 passing All six projects sharing the config pass: 1656 tests. Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
e94cc029eb
commit
7952e6444d
2 files changed
+63
-3
No files matched your search
@@ -13,6 +13,12 @@ export default {
|
||||
...angularEsmPreset,
|
||||
rootDir: '.',
|
||||
roots: ['<rootDir>/apps/web', '<rootDir>/libs'],
|
||||
// Jest's 5s default is thin for Angular component specs: TestBed compiles
|
||||
// and instantiates a real component tree per test, and CI runners are far
|
||||
// slower per-core than a dev machine. A starved worker then fails a test
|
||||
// that is merely slow, with no defect behind it. Raised as headroom only —
|
||||
// a spec that genuinely hangs still fails, just later.
|
||||
testTimeout: 15_000,
|
||||
setupFilesAfterEnv: ['<rootDir>/apps/web/src/test-setup.ts'],
|
||||
resolver: nxPreset.resolver,
|
||||
moduleFileExtensions: Array.from(
|
||||
|
||||
@@ -1,8 +1,21 @@
|
||||
import { signal } from '@angular/core';
|
||||
import { Component, input, output, signal } from '@angular/core';
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { By } from '@angular/platform-browser';
|
||||
import { Router } from '@angular/router';
|
||||
import { TranslateModule, TranslateService } from '@ngx-translate/core';
|
||||
import {
|
||||
TranslateModule,
|
||||
TranslatePipe,
|
||||
TranslateService,
|
||||
} from '@ngx-translate/core';
|
||||
import { MatIcon } from '@angular/material/icon';
|
||||
import { SafePipe } from '@iptvnator/pipes';
|
||||
import {
|
||||
DetailActionsTemplateDirective,
|
||||
DetailMetaTemplateDirective,
|
||||
DetailTagsTemplateDirective,
|
||||
PortalDetailShellComponent,
|
||||
ViewInPortalActionComponent,
|
||||
} from '@iptvnator/ui/components';
|
||||
import { PORTAL_EXTERNAL_PLAYBACK } from '@iptvnator/portal/shared/util';
|
||||
import {
|
||||
CrossPortalSimilarService,
|
||||
@@ -23,6 +36,29 @@ jest.unstable_mockModule('@yangkghjh/videojs-aspect-ratio-panel', () => ({}));
|
||||
jest.unstable_mockModule('videojs-contrib-quality-levels', () => ({}));
|
||||
jest.unstable_mockModule('videojs-quality-selector-hls', () => ({}));
|
||||
|
||||
/**
|
||||
* Stand-in for the inline player. The real one imports
|
||||
* `WebPlayerViewComponent`, which drags ArtPlayer, video.js and the
|
||||
* embedded-MPV bridge into this suite and instantiates that whole tree on
|
||||
* every `createComponent`. These specs only assert what the host *hands* the
|
||||
* player, so mirroring the selector and the template's bindings is enough —
|
||||
* and it keeps the per-test budget clear of Jest's timeout on slower CI
|
||||
* hardware.
|
||||
*/
|
||||
@Component({
|
||||
selector: 'app-portal-inline-player',
|
||||
template: '<div data-test-id="stub-portal-inline-player"></div>',
|
||||
})
|
||||
class StubPortalInlinePlayerComponent {
|
||||
readonly playbackSessionKey = input<string>('');
|
||||
readonly playback = input<unknown>(null);
|
||||
readonly timeUpdate = output<{ currentTime: number; duration: number }>();
|
||||
readonly closed = output<void>();
|
||||
readonly backClicked = output<void>();
|
||||
readonly streamUrlCopied = output<void>();
|
||||
readonly externalFallbackRequested = output<unknown>();
|
||||
}
|
||||
|
||||
const STALKER_VOD: VodDetailsItem = createStalkerVodItem(
|
||||
{
|
||||
id: '42',
|
||||
@@ -250,7 +286,25 @@ describe('VodDetailsComponent offline playback', () => {
|
||||
},
|
||||
},
|
||||
],
|
||||
}).compileComponents();
|
||||
})
|
||||
.overrideComponent(VodDetailsComponent, {
|
||||
// Same import list the component declares, with the inline
|
||||
// player swapped for the stub above.
|
||||
set: {
|
||||
imports: [
|
||||
DetailActionsTemplateDirective,
|
||||
DetailMetaTemplateDirective,
|
||||
DetailTagsTemplateDirective,
|
||||
MatIcon,
|
||||
PortalDetailShellComponent,
|
||||
ViewInPortalActionComponent,
|
||||
StubPortalInlinePlayerComponent,
|
||||
SafePipe,
|
||||
TranslatePipe,
|
||||
],
|
||||
},
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
const translate = TestBed.inject(TranslateService);
|
||||
translate.setTranslation('en', {
|
||||
|
||||
Reference in new issue
Block a user