From e51dbd995edad6bbf897f11c4d50fd99df198dee Mon Sep 17 00:00:00 2001 From: 4gray Date: Fri, 22 May 2026 03:14:09 +0300 Subject: [PATCH] refactor(import): use runtime capability for url hint --- .../url-upload/url-upload.component.spec.ts | 30 +++++++++++++++++++ .../lib/url-upload/url-upload.component.ts | 4 ++- 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/libs/playlist/import/feature/src/lib/url-upload/url-upload.component.spec.ts b/libs/playlist/import/feature/src/lib/url-upload/url-upload.component.spec.ts index a4c54469b..db23e51f0 100644 --- a/libs/playlist/import/feature/src/lib/url-upload/url-upload.component.spec.ts +++ b/libs/playlist/import/feature/src/lib/url-upload/url-upload.component.spec.ts @@ -4,13 +4,21 @@ import { MatFormFieldModule } from '@angular/material/form-field'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { TranslateModule } from '@ngx-translate/core'; import { MockModule } from 'ng-mocks'; +import { RuntimeCapabilitiesService } from '@iptvnator/services'; import { UrlUploadComponent } from './url-upload.component'; describe('UrlUploadComponent', () => { let component: UrlUploadComponent; let fixture: ComponentFixture; + let runtime: { + isElectron: boolean; + }; beforeEach(waitForAsync(() => { + runtime = { + isElectron: true, + }; + TestBed.configureTestingModule({ imports: [ UrlUploadComponent, @@ -20,6 +28,12 @@ describe('UrlUploadComponent', () => { TranslateModule.forRoot(), NoopAnimationsModule, ], + providers: [ + { + provide: RuntimeCapabilitiesService, + useValue: runtime, + }, + ], }).compileComponents(); })); @@ -33,6 +47,22 @@ describe('UrlUploadComponent', () => { expect(component).toBeTruthy(); }); + it('shows the CORS note only when Electron is unavailable', () => { + expect( + (fixture.nativeElement as HTMLElement).querySelector('.cors-note') + ).toBeNull(); + + fixture.destroy(); + runtime.isElectron = false; + fixture = TestBed.createComponent(UrlUploadComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + + expect( + (fixture.nativeElement as HTMLElement).querySelector('.cors-note') + ).not.toBeNull(); + }); + it('accepts an optional playlist name without affecting url validation', () => { const testUrl = 'http://example.org/playlist.m3u'; diff --git a/libs/playlist/import/feature/src/lib/url-upload/url-upload.component.ts b/libs/playlist/import/feature/src/lib/url-upload/url-upload.component.ts index f9762a4a5..7f14d9cd3 100644 --- a/libs/playlist/import/feature/src/lib/url-upload/url-upload.component.ts +++ b/libs/playlist/import/feature/src/lib/url-upload/url-upload.component.ts @@ -9,6 +9,7 @@ import { import { MatFormFieldModule } from '@angular/material/form-field'; import { MatInputModule } from '@angular/material/input'; import { TranslatePipe } from '@ngx-translate/core'; +import { RuntimeCapabilitiesService } from '@iptvnator/services'; @Component({ selector: 'app-url-upload', @@ -22,12 +23,13 @@ import { TranslatePipe } from '@ngx-translate/core'; }) export class UrlUploadComponent implements OnInit { private readonly fb = inject(FormBuilder); + private readonly runtime = inject(RuntimeCapabilitiesService); form!: FormGroup<{ playlistName: FormControl; playlistUrl: FormControl; }>; - readonly isDesktop = !!window.electron; + readonly isDesktop = this.runtime.isElectron; ngOnInit(): void { const urlRegex = '(https?://.*?)';