fix(tooling): repair test, i18n and docs verification gates (#3331)

This commit is contained in:
Hampus authored and GitHub committed 2026-10-09 01:38:34 +02:00
1 parent ece622e800
commit f390e610b9
107 files changed
+5144 -3004

No files matched your search

@@ -33,7 +33,9 @@ test('an unreachable instance offers a retry and never a reset of app data', ()
"Error invoking remote method 'desktop-runtime-config:resolve': DesktopRuntimeDiscoveryUnreachableError: No usable instance discovery document was served",
);
const markup = renderToStaticMarkup(<BootstrapErrorScreen error={error} />);
const markup = renderToStaticMarkup(
<BootstrapErrorScreen error={error} data-flx="app.bootstrap-error-screen-test.bootstrap-error-screen" />,
);
expect(markup).toContain(RETRY_BUTTON);
expect(markup).not.toContain(RESET_BUTTON);
@@ -45,7 +47,9 @@ test('an unreachable instance keeps the raw error out of the page and offers it
"Error invoking remote method 'desktop-runtime-config:resolve': DesktopRuntimeDiscoveryUnreachableError: connect ECONNREFUSED 127.0.0.1:9",
);
const markup = renderToStaticMarkup(<BootstrapErrorScreen error={error} />);
const markup = renderToStaticMarkup(
<BootstrapErrorScreen error={error} data-flx="app.bootstrap-error-screen-test.bootstrap-error-screen--2" />,
);
expect(markup).not.toContain('DesktopRuntimeDiscoveryUnreachableError');
expect(markup).not.toContain('ECONNREFUSED');
@@ -55,13 +59,23 @@ test('an unreachable instance keeps the raw error out of the page and offers it
test('a failure while the device is offline never offers a reset of app data', () => {
vi.spyOn(navigator, 'onLine', 'get').mockReturnValue(false);
const markup = renderToStaticMarkup(<BootstrapErrorScreen error={new Error('Stored account record is malformed')} />);
const markup = renderToStaticMarkup(
<BootstrapErrorScreen
error={new Error('Stored account record is malformed')}
data-flx="app.bootstrap-error-screen-test.bootstrap-error-screen--3"
/>,
);
expect(markup).not.toContain(RESET_BUTTON);
});
test('a local startup failure still offers the reset of app data', () => {
const markup = renderToStaticMarkup(<BootstrapErrorScreen error={new Error('Stored account record is malformed')} />);
const markup = renderToStaticMarkup(
<BootstrapErrorScreen
error={new Error('Stored account record is malformed')}
data-flx="app.bootstrap-error-screen-test.bootstrap-error-screen--4"
/>,
);
expect(markup).toContain(RETRY_BUTTON);
expect(markup).toContain(RESET_BUTTON);
@@ -265,8 +265,15 @@ export const AllSettingsRenderer: React.FC<AllSettingsRendererProps> = observer(
>
<div className={styles.resultsHeader} data-flx="app.all-settings-renderer.results-header">
<Trans>
Found <Plural value={resultCount} one="# result" other="# results" /> in{' '}
<Plural value={categoryCount} one="# category" other="# categories" />
Found{' '}
<Plural value={resultCount} one="# result" other="# results" data-flx="app.all-settings-renderer.plural" />{' '}
in{' '}
<Plural
value={categoryCount}
one="# category"
other="# categories"
data-flx="app.all-settings-renderer.plural--2"
/>
</Trans>
</div>
{searchResults.map((result) => (
@@ -38,7 +38,7 @@ interface ControlIconProps {
const ControlIcon: React.FC<ControlIconProps> = ({icon, 'data-flx': dataFlx}) => (
<svg viewBox="0 0 256 256" fill="currentColor" xmlns="http://www.w3.org/2000/svg" data-flx={dataFlx}>
<path d={NATIVE_TITLEBAR_CONTROL_ICON_PATH[icon]} />
<path d={NATIVE_TITLEBAR_CONTROL_ICON_PATH[icon]} data-flx="app.native-window-controls.control-icon.path" />
</svg>
);
@@ -650,7 +650,12 @@ export const SignInMethodStep = observer(
)}
{!usernameSignIn && (
<div className={styles.usernameStyle} data-flx="app.self-hosted-setup-wizard-gate.username-style">
<h3 className={styles.usernameStyleTitle}>{i18n._(TAG_STYLE_TITLE_DESCRIPTOR)}</h3>
<h3
className={styles.usernameStyleTitle}
data-flx="app.setup.setup-wizard-steps.sign-in-method-step.username-style-title"
>
{i18n._(TAG_STYLE_TITLE_DESCRIPTOR)}
</h3>
<RadioGroup
options={tagStyleOptions}
value={tagStyle}
@@ -62,7 +62,7 @@ afterEach(() => {
test('closing a sheet by hand steps back over its history entry', () => {
const history = requireHistory();
const back = vi.spyOn(history, 'back');
act(() => root?.render(<Sheet />));
act(() => root?.render(<Sheet data-flx="app.use-bottom-sheet-back-handler-test.sheet" />));
expect(sheetMarker()).toBeTypeOf('string');
act(() => closeSheet?.());
expect(back).toHaveBeenCalledTimes(1);
@@ -73,7 +73,7 @@ test('closing a sheet by hand steps back over its history entry', () => {
test('a sheet dismissed by an account switch leaves navigation to the switch', async () => {
const history = requireHistory();
const back = vi.spyOn(history, 'back');
act(() => root?.render(<Sheet />));
act(() => root?.render(<Sheet data-flx="app.use-bottom-sheet-back-handler-test.sheet--2" />));
expect(sheetMarker()).toBeTypeOf('string');
(globalThis as {IS_REACT_ACT_ENVIRONMENT?: boolean}).IS_REACT_ACT_ENVIRONMENT = false;
await AccountScopedWork.runSuspended(AccountScopedWorkTransitionReason.ACCOUNT_SWITCH, async () => {
+43 -26
View File
@@ -16,15 +16,7 @@ import {
isElectron,
openExternalUrl,
} from '@app/features/ui/utils/NativeUtils';
import {
pushDesktopUpdateAvailableModal,
pushDesktopUpdateDownloadFailedModal,
pushManualUpdateAvailableModal,
pushUnsupportedUpdateModal,
pushUpdateAvailableModal,
pushUpdateCheckFailedModal,
pushUpToDateModal,
} from '@app/features/updater/commands/UpdaterModalCommands';
import type * as UpdaterModalCommands from '@app/features/updater/commands/UpdaterModalCommands';
import {
createUpdaterMachineSnapshot,
getUpdaterDisplayVersion,
@@ -61,6 +53,16 @@ const ALLOWED_WEB_UPDATE_HOSTS = new Set([
'canary.fluxer.com',
]);
function loadUpdaterModals(): Promise<typeof UpdaterModalCommands> {
return import('@app/features/updater/commands/UpdaterModalCommands');
}
function showUpdaterModal(show: (modals: typeof UpdaterModalCommands) => void): void {
void loadUpdaterModals().then(show, (error) => {
logger.warn('Failed to load the updater modals', error);
});
}
async function dropCachedAppShell(): Promise<void> {
const browserCaches = getProtectedCacheStorage();
if (!browserCaches) return;
@@ -251,6 +253,9 @@ class Updater {
logger.warn('Failed to read desktop info', error);
}
this.subscribeToNativeEvents();
void loadUpdaterModals().catch((error) => {
logger.debug('Failed to preload the updater modals', error);
});
}
private async bootstrapDesktopUpdate(): Promise<void> {
@@ -399,7 +404,7 @@ class Updater {
}
this.transition({type: 'native.error'});
if (isUserCheck) {
pushUpdateCheckFailedModal();
showUpdaterModal((modals) => modals.pushUpdateCheckFailedModal());
}
break;
case 'unsupported':
@@ -410,7 +415,9 @@ class Updater {
now: Date.now(),
});
if (shouldShowImmediateUserResult) {
pushUnsupportedUpdateModal(event.reason ?? 'platform', event.downloadUrl ?? null);
const reason = event.reason ?? 'platform';
const downloadUrl = event.downloadUrl ?? null;
showUpdaterModal((modals) => modals.pushUnsupportedUpdateModal(reason, downloadUrl));
}
break;
}
@@ -505,7 +512,7 @@ class Updater {
failed = true;
logger.debug('Update check failed silently:', err);
if (userInitiated) {
pushUpdateCheckFailedModal();
showUpdaterModal((modals) => modals.pushUpdateCheckFailedModal());
}
} finally {
this.checkInProgress = false;
@@ -576,7 +583,7 @@ class Updater {
return;
}
if (this.isNative && this.nativeUnsupported?.reason === 'managed-package' && !this.updateInfo.web.available) {
pushUnsupportedUpdateModal('managed-package');
showUpdaterModal((modals) => modals.pushUnsupportedUpdateModal('managed-package'));
return;
}
if (this.isNative && this.nativeManualUpdateAvailable && !this.nativeUnsupported) {
@@ -595,7 +602,8 @@ class Updater {
if (url) {
await openExternalUrl(url);
} else if (this.nativeUnsupported) {
pushUnsupportedUpdateModal(this.nativeUnsupported.reason, this.nativeUnsupported.downloadUrl);
const {reason, downloadUrl} = this.nativeUnsupported;
showUpdaterModal((modals) => modals.pushUnsupportedUpdateModal(reason, downloadUrl));
} else {
await openExternalUrl(DESKTOP_DOWNLOAD_URL);
}
@@ -604,7 +612,7 @@ class Updater {
private showCurrentUpdateState(): void {
if (this.desktopUpdateAvailable) {
pushDesktopUpdateAvailableModal(() => this.startDesktopUpdate());
showUpdaterModal((modals) => modals.pushDesktopUpdateAvailableModal(() => this.startDesktopUpdate()));
return;
}
if (this.nativeManualUpdateAvailable) {
@@ -615,10 +623,12 @@ class Updater {
return;
}
if (this.nativeUnsupported) {
pushUnsupportedUpdateModal(this.nativeUnsupported.reason, this.nativeUnsupported.downloadUrl);
const {reason, downloadUrl} = this.nativeUnsupported;
showUpdaterModal((modals) => modals.pushUnsupportedUpdateModal(reason, downloadUrl));
return;
}
pushUpToDateModal(this.currentVersion);
const currentVersion = this.currentVersion;
showUpdaterModal((modals) => modals.pushUpToDateModal(currentVersion));
}
private getManualUpdateSuggestedName(url: string): string {
@@ -633,17 +643,24 @@ class Updater {
}
private showManualNativeUpdateModal(): void {
if (this.nativeManualDownloadOptions.length > 0) {
pushManualUpdateAvailableModal({
currentVersion: this.currentVersion,
version: this.updateInfo.native.version,
options: this.nativeManualDownloadOptions,
onDownload: (option) => this.downloadManualNativeUpdateOption(option),
});
const version = this.updateInfo.native.version;
const options = this.nativeManualDownloadOptions;
if (options.length > 0) {
const currentVersion = this.currentVersion;
showUpdaterModal((modals) =>
modals.pushManualUpdateAvailableModal({
currentVersion,
version,
options,
onDownload: (option) => this.downloadManualNativeUpdateOption(option),
}),
);
return;
}
const url = this.nativeManualDownloadUrl ?? this.nativeUnsupported?.downloadUrl ?? DESKTOP_DOWNLOAD_URL;
pushUpdateAvailableModal(this.updateInfo.native.version, () => this.downloadManualNativeUpdateOrOpen(url));
showUpdaterModal((modals) =>
modals.pushUpdateAvailableModal(version, () => this.downloadManualNativeUpdateOrOpen(url)),
);
}
private async refreshManualNativeDownloadOption(option: UpdaterDownloadOption): Promise<UpdaterDownloadOption> {
@@ -704,7 +721,7 @@ class Updater {
}
if (outcome === 'checksum-mismatch') {
logger.error('Native manual update download did not match its published checksum', {url});
pushDesktopUpdateDownloadFailedModal();
showUpdaterModal((modals) => modals.pushDesktopUpdateDownloadFailedModal());
return;
}
logger.warn('Native manual update download unavailable; opening update URL externally', {outcome});