mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-11 11:06:16 -08:00
fix(settings): show the installed version without the GitHub release check (#1879)
The settings facade filled its version signal only inside the GitHub releases callback, so offline or under an api.github.com rate limit the installed version was missing from the sidebar's About item and the About page. The version is known locally from DataService, so the signal starts with it. The release check also gets an error handler: SettingsService already logs the failure, and without it the error resurfaced uncaught. The sidebar layout E2E no longer needs to stub the releases request; a new E2E aborts it and expects the version in both places. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
91e277e9ba
commit
039238b7bc
4 files changed
+72
-12
No files matched your search
@@ -0,0 +1,8 @@
|
||||
---
|
||||
type: fix
|
||||
area: settings
|
||||
---
|
||||
|
||||
Settings always show the installed version, also offline or when GitHub
|
||||
cannot be reached; before, it was missing from the sidebar and the About page
|
||||
until the update check answered.
|
||||
@@ -232,14 +232,6 @@ test.describe('Settings', () => {
|
||||
test('@settings @web About keeps its label and clears the window bottom', async ({
|
||||
page,
|
||||
}) => {
|
||||
// The sidebar shows the version only once the GitHub releases check
|
||||
// answers; CI runners are often rate-limited there, so answer locally
|
||||
// with an older release (no update badge replaces the version).
|
||||
await page.route('**/repos/4gray/iptvnator/releases*', (route) =>
|
||||
route.fulfill({
|
||||
json: [{ created_at: '2020-01-01T00:00:00Z', name: '0.0.1' }],
|
||||
})
|
||||
);
|
||||
await openSettings(page);
|
||||
const about = page.locator(
|
||||
'.settings-nav__footer [data-test-id="settings-section-about"]'
|
||||
@@ -279,6 +271,29 @@ test.describe('Settings', () => {
|
||||
).toBeGreaterThanOrEqual(12);
|
||||
});
|
||||
|
||||
test('@settings @web The installed version shows while GitHub is unreachable', async ({
|
||||
page,
|
||||
}) => {
|
||||
// Offline, or rate-limited by api.github.com: the release check never
|
||||
// answers, yet the installed version is known locally.
|
||||
await page.route('**/repos/4gray/iptvnator/releases*', (route) =>
|
||||
route.abort()
|
||||
);
|
||||
await openSettings(page);
|
||||
|
||||
const version = /\d+\.\d+\.\d+/;
|
||||
await expect(
|
||||
page.locator(
|
||||
'[data-test-id="settings-section-about"] [data-test-id="settings-nav-version"]'
|
||||
)
|
||||
).toHaveText(version);
|
||||
|
||||
await openSettingsSection(page, 'about');
|
||||
await expect(page.locator('[data-test-id="app-version"]')).toHaveText(
|
||||
version
|
||||
);
|
||||
});
|
||||
|
||||
test('@settings @web Esc leaves settings like the header Back', async ({
|
||||
page,
|
||||
}) => {
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
} from '@iptvnator/shared/interfaces';
|
||||
import { TranslateModule, TranslateService } from '@ngx-translate/core';
|
||||
import { MockProvider } from 'ng-mocks';
|
||||
import { of } from 'rxjs';
|
||||
import { NEVER, of, throwError } from 'rxjs';
|
||||
import { ElectronServiceStub } from '../services/electron.service.stub';
|
||||
import { SettingsService } from '../services/settings.service';
|
||||
import { AppUpdateReleaseNotesDialogComponent } from './app-update-release-notes-dialog.component';
|
||||
@@ -216,6 +216,34 @@ describe('SettingsAppUpdateFacade', () => {
|
||||
);
|
||||
});
|
||||
|
||||
describe('Installed version without the release check', () => {
|
||||
it('shows the installed version before GitHub answers', () => {
|
||||
(
|
||||
TestBed.inject(SettingsService).getAppVersion as jest.Mock
|
||||
).mockReturnValue(NEVER);
|
||||
|
||||
facade.checkAppVersion();
|
||||
|
||||
expect(facade.version()).toBe('1.0.0');
|
||||
expect(facade.updateMessage()).toBe('');
|
||||
});
|
||||
|
||||
it('keeps the installed version when GitHub cannot be reached', async () => {
|
||||
(
|
||||
TestBed.inject(SettingsService).getAppVersion as jest.Mock
|
||||
).mockReturnValue(
|
||||
throwError(() => new Error('rate limit exceeded'))
|
||||
);
|
||||
|
||||
facade.checkAppVersion();
|
||||
// An unhandled observable error is rethrown on a timer.
|
||||
await flush();
|
||||
|
||||
expect(facade.version()).toBe('1.0.0');
|
||||
expect(facade.updateMessage()).toBe('');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Version check', () => {
|
||||
const latestVersion = '1.0.0';
|
||||
const currentVersion = '0.1.0';
|
||||
|
||||
@@ -34,8 +34,12 @@ export class SettingsAppUpdateFacade {
|
||||
/** Latest updater status, polled once and then pushed by the backend */
|
||||
readonly status = signal<ElectronBridgeAppUpdateStatus | null>(null);
|
||||
|
||||
/** Current version of the app */
|
||||
readonly version = signal('');
|
||||
/**
|
||||
* Installed version of the app. Known locally from the start, so it does
|
||||
* not wait on (or vanish with) the GitHub releases check, which fails
|
||||
* offline and when api.github.com rate-limits the client.
|
||||
*/
|
||||
readonly version = signal(this.dataService.getAppVersion());
|
||||
|
||||
/** Outcome of the last version check, kept apart from its wording. */
|
||||
private readonly versionCheck = signal<{
|
||||
@@ -148,7 +152,12 @@ export class SettingsAppUpdateFacade {
|
||||
this.settingsService
|
||||
.getAppVersion()
|
||||
.pipe(take(1))
|
||||
.subscribe((version) => this.showVersionInformation(version));
|
||||
.subscribe({
|
||||
next: (version) => this.showVersionInformation(version),
|
||||
// SettingsService already logs the failure; without an
|
||||
// answer there is simply no update note to show.
|
||||
error: () => undefined,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in new issue
Block a user