mirror of
https://github.com/Syngnat/GoNavi.git
synced 2026-07-12 16:02:48 +08:00
✨ feat(updater): 优化关于页更新信息展示
- 关于页直接进入 GoNavi 内容详情,减少二次点击 - 将更新通道改为分段选择器并优化描述布局 - 保留后端发布发布时间元数据并在版本信息中展示
This commit is contained in:
@@ -743,3 +743,63 @@ body[data-ui-version="legacy"] .ant-layout-sider {
|
||||
min-width: 232px !important;
|
||||
max-width: min(960px, calc(100vw - 360px)) !important;
|
||||
}
|
||||
|
||||
body .gonavi-about-update-channel.ant-segmented.ant-segmented {
|
||||
height: 42px !important;
|
||||
padding: 4px !important;
|
||||
border: 1px solid rgba(15, 23, 42, 0.10) !important;
|
||||
border-radius: 12px !important;
|
||||
background: rgba(15, 23, 42, 0.035) !important;
|
||||
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.72) !important;
|
||||
}
|
||||
|
||||
body .gonavi-about-update-channel .ant-segmented-group {
|
||||
gap: 3px;
|
||||
}
|
||||
|
||||
body .gonavi-about-update-channel .ant-segmented-item {
|
||||
border-radius: 9px !important;
|
||||
}
|
||||
|
||||
body .gonavi-about-update-channel .ant-segmented-item-label {
|
||||
min-height: 32px !important;
|
||||
padding: 0 14px !important;
|
||||
color: rgba(15, 23, 42, 0.62) !important;
|
||||
font-size: 14px !important;
|
||||
font-weight: 700 !important;
|
||||
line-height: 32px !important;
|
||||
}
|
||||
|
||||
body .gonavi-about-update-channel .ant-segmented-item-selected,
|
||||
body .gonavi-about-update-channel .ant-segmented-thumb {
|
||||
background: rgba(255, 255, 255, 0.98) !important;
|
||||
box-shadow: 0 8px 18px rgba(15, 23, 42, 0.12) !important;
|
||||
}
|
||||
|
||||
body .gonavi-about-update-channel .ant-segmented-item-selected .ant-segmented-item-label {
|
||||
color: #0f172a !important;
|
||||
}
|
||||
|
||||
body .gonavi-about-update-channel.ant-segmented-disabled {
|
||||
opacity: 0.58;
|
||||
}
|
||||
|
||||
body[data-theme='dark'] .gonavi-about-update-channel.ant-segmented.ant-segmented {
|
||||
border-color: rgba(148, 163, 184, 0.22) !important;
|
||||
background: rgba(15, 23, 42, 0.55) !important;
|
||||
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.08) !important;
|
||||
}
|
||||
|
||||
body[data-theme='dark'] .gonavi-about-update-channel .ant-segmented-item-label {
|
||||
color: rgba(226, 232, 240, 0.62) !important;
|
||||
}
|
||||
|
||||
body[data-theme='dark'] .gonavi-about-update-channel .ant-segmented-item-selected,
|
||||
body[data-theme='dark'] .gonavi-about-update-channel .ant-segmented-thumb {
|
||||
background: rgba(30, 41, 59, 0.98) !important;
|
||||
box-shadow: 0 8px 18px rgba(0, 0, 0, 0.26) !important;
|
||||
}
|
||||
|
||||
body[data-theme='dark'] .gonavi-about-update-channel .ant-segmented-item-selected .ant-segmented-item-label {
|
||||
color: #f8fafc !important;
|
||||
}
|
||||
|
||||
@@ -87,6 +87,13 @@ describe('settings center layout', () => {
|
||||
expect(appSource).toContain('renderSettingsCenterAboutPane()');
|
||||
});
|
||||
|
||||
it('opens the about group directly instead of showing a one-item list', () => {
|
||||
expect(appSource).toContain('const resolveSettingsCenterGroupInitialPane = (group: SettingsCenterGroupKey): SettingsCenterPaneState | null => (');
|
||||
expect(appSource).toContain("group === 'about' ? { key: 'about-go-navi', group: 'about' } : null");
|
||||
expect(appSource).toContain('setActiveSettingsCenterPane(resolveSettingsCenterGroupInitialPane(group));');
|
||||
expect(appSource).toContain('setActiveSettingsCenterPane(resolveSettingsCenterGroupInitialPane(group.key));');
|
||||
});
|
||||
|
||||
it('renders the settings center about page with the reference card layout', () => {
|
||||
expect(appSource).toContain('const renderSettingsCenterAboutPane = () => {');
|
||||
expect(appSource).toContain('const renderSettingsCenterAboutProjectEntry = ({');
|
||||
@@ -94,6 +101,14 @@ describe('settings center layout', () => {
|
||||
expect(appSource).toContain('width: 64');
|
||||
expect(appSource).toContain('height: 64');
|
||||
expect(appSource).toContain('minWidth: 260');
|
||||
expect(appSource).toContain('const releaseTimeText = formatAboutReleaseTime(lastUpdateInfo?.releasePublishedAt);');
|
||||
expect(appSource).toContain("[t('app.about.version.release_time'), releaseTimeText]");
|
||||
expect(appSource).toContain("gridTemplateColumns: 'minmax(0, 1fr) minmax(220px, 260px)'");
|
||||
expect(appSource).toContain('className="gonavi-about-update-channel"');
|
||||
expect(appSource).toContain('<Segmented');
|
||||
expect(appSource).toContain('maxWidth: 360');
|
||||
expect(appSource).toContain("alignItems: 'start'");
|
||||
expect(appSource).toContain("overflowWrap: 'anywhere'");
|
||||
expect(appSource).toContain("t('app.about.version_update.title')");
|
||||
expect(appSource).toContain("t('app.about.project.github.title')");
|
||||
expect(appSource).toContain("t('app.about.project.issues.title')");
|
||||
|
||||
@@ -226,6 +226,10 @@ type SettingsCenterPaneState = {
|
||||
group: SettingsCenterGroupKey;
|
||||
};
|
||||
|
||||
const resolveSettingsCenterGroupInitialPane = (group: SettingsCenterGroupKey): SettingsCenterPaneState | null => (
|
||||
group === 'about' ? { key: 'about-go-navi', group: 'about' } : null
|
||||
);
|
||||
|
||||
const DEFAULT_GLOBAL_PROXY_TEST_URL = 'https://api.github.com/';
|
||||
|
||||
type GlobalProxyTestResultState = {
|
||||
@@ -271,6 +275,18 @@ const formatAboutCheckedAt = (value: Date): string => {
|
||||
return `${value.getFullYear()}-${pad(value.getMonth() + 1)}-${pad(value.getDate())} ${pad(value.getHours())}:${pad(value.getMinutes())}`;
|
||||
};
|
||||
|
||||
const formatAboutReleaseTime = (value: string | undefined): string => {
|
||||
const text = String(value || '').trim();
|
||||
if (!text) {
|
||||
return '-';
|
||||
}
|
||||
const date = new Date(text);
|
||||
if (Number.isNaN(date.getTime())) {
|
||||
return '-';
|
||||
}
|
||||
return formatAboutCheckedAt(date);
|
||||
};
|
||||
|
||||
type ConnectionPackageDialogState = {
|
||||
open: boolean;
|
||||
mode: ConnectionPackageDialogMode;
|
||||
@@ -2592,7 +2608,7 @@ function App() {
|
||||
}, []);
|
||||
const handleOpenSettingsModal = useCallback((group: SettingsCenterGroupKey = 'preferences') => {
|
||||
setActiveSettingsCenterGroupKey(group);
|
||||
setActiveSettingsCenterPane(null);
|
||||
setActiveSettingsCenterPane(resolveSettingsCenterGroupInitialPane(group));
|
||||
setIsSettingsModalOpen(true);
|
||||
}, []);
|
||||
const handleOpenSettingsCenterPane = useCallback((group: SettingsCenterGroupKey, key: SettingsCenterPaneKey) => {
|
||||
@@ -3975,6 +3991,7 @@ function App() {
|
||||
: (lastUpdateInfo ? t('app.about.hero.no_update') : t('app.about.update_status.not_checked'));
|
||||
const currentVersionText = lastUpdateInfo?.currentVersion || aboutDisplayVersion;
|
||||
const releaseNotesText = lastUpdateInfo?.releaseName || (hasUpdate ? t('app.about.release_notes.fallback') : '-');
|
||||
const releaseTimeText = formatAboutReleaseTime(lastUpdateInfo?.releasePublishedAt);
|
||||
const cardBorder = darkMode ? 'rgba(255,255,255,0.10)' : 'rgba(16,24,40,0.11)';
|
||||
const cardBg = darkMode ? 'rgba(255,255,255,0.03)' : 'rgba(255,255,255,0.82)';
|
||||
const mutedText = utilityMutedTextStyle.color;
|
||||
@@ -3982,7 +3999,7 @@ function App() {
|
||||
const versionRows = [
|
||||
[t('app.about.version.current'), currentVersionText],
|
||||
[t('app.about.version.latest'), latestVersionText],
|
||||
[t('app.about.version.release_time'), '-'],
|
||||
[t('app.about.version.release_time'), releaseTimeText],
|
||||
[t('app.about.version.release_notes'), releaseNotesText],
|
||||
];
|
||||
|
||||
@@ -4071,36 +4088,37 @@ function App() {
|
||||
{t('app.about.version_update.title')}
|
||||
</div>
|
||||
<div style={{ borderTop: `1px solid ${dividerColor}`, padding: '18px 24px' }}>
|
||||
<div style={{ display: 'grid', gridTemplateColumns: 'minmax(0, 1fr) 210px', alignItems: 'center', gap: 16 }}>
|
||||
<div>
|
||||
<div style={{ display: 'grid', gap: 8 }}>
|
||||
<div style={{ display: 'grid', gridTemplateColumns: 'minmax(0, 1fr) minmax(220px, 260px)', alignItems: 'center', gap: 16 }}>
|
||||
<div style={{ fontSize: 15, fontWeight: 600, color: overlayTheme.titleText }}>{t('app.about.field.update_channel')}</div>
|
||||
<div style={{ ...utilityMutedTextStyle, marginTop: 6 }}>{t('app.about.version_update.channel_hint')}</div>
|
||||
<Segmented
|
||||
className="gonavi-about-update-channel"
|
||||
value={updateChannel}
|
||||
options={[
|
||||
{ value: 'latest', label: t('app.about.update_channel.latest') },
|
||||
{ value: 'dev', label: t('app.about.update_channel.dev') },
|
||||
]}
|
||||
onChange={(value) => {
|
||||
void changeUpdateChannel(String(value));
|
||||
}}
|
||||
disabled={
|
||||
isUpdateChannelLoading
|
||||
|| isUpdateChannelSaving
|
||||
|| updateDownloadProgress.status === 'start'
|
||||
|| updateDownloadProgress.status === 'downloading'
|
||||
}
|
||||
block
|
||||
style={{ width: '100%' }}
|
||||
/>
|
||||
</div>
|
||||
<Select
|
||||
value={updateChannel}
|
||||
options={[
|
||||
{ value: 'latest', label: t('app.about.update_channel.latest') },
|
||||
{ value: 'dev', label: t('app.about.update_channel.dev') },
|
||||
]}
|
||||
onChange={(value) => {
|
||||
void changeUpdateChannel(String(value));
|
||||
}}
|
||||
loading={isUpdateChannelLoading}
|
||||
disabled={
|
||||
isUpdateChannelLoading
|
||||
|| isUpdateChannelSaving
|
||||
|| updateDownloadProgress.status === 'start'
|
||||
|| updateDownloadProgress.status === 'downloading'
|
||||
}
|
||||
style={{ width: '100%' }}
|
||||
/>
|
||||
<div style={{ ...utilityMutedTextStyle, lineHeight: 1.55, maxWidth: 360 }}>{t('app.about.version_update.channel_hint')}</div>
|
||||
</div>
|
||||
<div style={{ height: 1, background: dividerColor, margin: '18px 0' }} />
|
||||
<div style={{ display: 'grid', gap: 13 }}>
|
||||
{versionRows.map(([label, value]) => (
|
||||
<div key={label} style={{ display: 'grid', gridTemplateColumns: '150px minmax(0, 1fr)', gap: 16, alignItems: 'baseline' }}>
|
||||
<div style={{ fontWeight: 600, color: overlayTheme.titleText }}>{label}</div>
|
||||
<div style={{ color: label === t('app.about.version.latest') && hasUpdate ? (darkMode ? '#86efac' : '#16a34a') : mutedText, fontWeight: label === t('app.about.version.latest') && hasUpdate ? 700 : 500 }}>
|
||||
<div key={label} style={{ display: 'grid', gridTemplateColumns: '150px minmax(0, 1fr)', gap: 16, alignItems: 'start' }}>
|
||||
<div style={{ fontWeight: 600, color: overlayTheme.titleText, lineHeight: 1.45 }}>{label}</div>
|
||||
<div style={{ color: label === t('app.about.version.latest') && hasUpdate ? (darkMode ? '#86efac' : '#16a34a') : mutedText, fontWeight: label === t('app.about.version.latest') && hasUpdate ? 700 : 500, lineHeight: 1.45, minWidth: 0, overflowWrap: 'anywhere' }}>
|
||||
{value}
|
||||
</div>
|
||||
</div>
|
||||
@@ -6165,7 +6183,7 @@ function App() {
|
||||
title={`${group.title} - ${group.description}`}
|
||||
onClick={() => {
|
||||
setActiveSettingsCenterGroupKey(group.key);
|
||||
setActiveSettingsCenterPane(null);
|
||||
setActiveSettingsCenterPane(resolveSettingsCenterGroupInitialPane(group.key));
|
||||
}}
|
||||
style={{
|
||||
position: 'relative',
|
||||
|
||||
@@ -221,6 +221,30 @@ describe('useAppUpdateManager', () => {
|
||||
expect(hook?.lastUpdateInfo?.channel).toBe('dev');
|
||||
});
|
||||
|
||||
it('keeps release metadata from the backend update response', async () => {
|
||||
backendApp.CheckForUpdates.mockResolvedValue({
|
||||
success: true,
|
||||
data: {
|
||||
hasUpdate: true,
|
||||
currentVersion: '0.8.1',
|
||||
latestVersion: '0.8.2',
|
||||
releaseName: 'Dev Build (dev-22fab86)',
|
||||
releasePublishedAt: '2026-07-08T11:15:00Z',
|
||||
releaseNotesUrl: 'https://github.com/Syngnat/GoNavi/releases/tag/dev-latest',
|
||||
},
|
||||
});
|
||||
|
||||
renderHook();
|
||||
|
||||
await act(async () => {
|
||||
await hook?.checkForUpdates(false);
|
||||
});
|
||||
|
||||
expect(hook?.lastUpdateInfo?.releaseName).toBe('Dev Build (dev-22fab86)');
|
||||
expect(hook?.lastUpdateInfo?.releasePublishedAt).toBe('2026-07-08T11:15:00Z');
|
||||
expect(hook?.lastUpdateInfo?.releaseNotesUrl).toBe('https://github.com/Syngnat/GoNavi/releases/tag/dev-latest');
|
||||
});
|
||||
|
||||
it('opens the downloaded update directory when a package is already downloaded', async () => {
|
||||
backendApp.CheckForUpdates.mockResolvedValue({
|
||||
success: true,
|
||||
|
||||
@@ -13,6 +13,7 @@ export type UpdateInfo = {
|
||||
currentVersion: string;
|
||||
latestVersion: string;
|
||||
releaseName?: string;
|
||||
releasePublishedAt?: string;
|
||||
releaseNotesUrl?: string;
|
||||
assetName?: string;
|
||||
assetUrl?: string;
|
||||
|
||||
@@ -76,6 +76,9 @@ const importMain = async () => {
|
||||
ExportConnectionsPackage: (options?: { includeSecrets?: boolean; filePassword?: string }) => Promise<{ success: boolean; message?: string }>;
|
||||
ApplyDataRootDirectory: (path: string) => Promise<{ success: boolean; message?: string; data?: { path?: string } }>;
|
||||
SaveQuery: (input: { id?: string; name?: string; sql?: string }) => Promise<{ name: string; sql: string }>;
|
||||
CheckForUpdates: () => Promise<{ success: boolean; data?: Record<string, unknown> }>;
|
||||
CheckForUpdatesSilently: () => Promise<{ success: boolean; data?: Record<string, unknown> }>;
|
||||
SetUpdateChannel: (channel: string) => Promise<{ success: boolean; data?: { channel?: string } }>;
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -124,6 +127,34 @@ describe('main browser mock', () => {
|
||||
});
|
||||
}, 10000);
|
||||
|
||||
it('includes release metadata in browser mock update checks', async () => {
|
||||
const app = await importMain();
|
||||
|
||||
await expect(app!.CheckForUpdates()).resolves.toMatchObject({
|
||||
success: true,
|
||||
data: {
|
||||
channel: 'latest',
|
||||
releaseName: 'Browser Mock Release',
|
||||
releasePublishedAt: '2026-07-08T11:15:00Z',
|
||||
releaseNotesUrl: 'https://github.com/Syngnat/GoNavi/releases/latest',
|
||||
},
|
||||
});
|
||||
|
||||
await expect(app!.SetUpdateChannel('dev')).resolves.toMatchObject({
|
||||
success: true,
|
||||
data: { channel: 'dev' },
|
||||
});
|
||||
await expect(app!.CheckForUpdatesSilently()).resolves.toMatchObject({
|
||||
success: true,
|
||||
data: {
|
||||
channel: 'dev',
|
||||
releaseName: 'Dev Build (dev-browser-mock)',
|
||||
releasePublishedAt: '2026-07-08T11:15:00Z',
|
||||
releaseNotesUrl: 'https://github.com/Syngnat/GoNavi/releases/tag/dev-latest',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('rejects non-array payloads with the localized browser mock import limitation', async () => {
|
||||
const app = await importMain();
|
||||
const { t } = await import('./i18n');
|
||||
|
||||
@@ -106,6 +106,18 @@ if (
|
||||
let mockSkills: any[] = [];
|
||||
let mockGlobalProxy: any = { enabled: false, type: 'socks5', host: '', port: 1080, user: '', password: '', hasPassword: false };
|
||||
let mockUpdateChannel: 'latest' | 'dev' = 'latest';
|
||||
const mockReleasePublishedAt = '2026-07-08T11:15:00Z';
|
||||
const buildMockUpdateInfo = () => ({
|
||||
hasUpdate: false,
|
||||
channel: mockUpdateChannel,
|
||||
currentVersion: '0.0.0',
|
||||
latestVersion: mockUpdateChannel === 'dev' ? 'dev-browser-mock' : '0.0.0',
|
||||
releaseName: mockUpdateChannel === 'dev' ? 'Dev Build (dev-browser-mock)' : 'Browser Mock Release',
|
||||
releasePublishedAt: mockReleasePublishedAt,
|
||||
releaseNotesUrl: mockUpdateChannel === 'dev'
|
||||
? 'https://github.com/Syngnat/GoNavi/releases/tag/dev-latest'
|
||||
: 'https://github.com/Syngnat/GoNavi/releases/latest',
|
||||
});
|
||||
let mockDataRootInfo: any = {
|
||||
path: 'C:/mock/.gonavi',
|
||||
defaultPath: 'C:/mock/.gonavi',
|
||||
@@ -350,21 +362,11 @@ if (
|
||||
GetDataRootDirectoryInfo: async () => ({ success: true, data: cloneBrowserMockValue(mockDataRootInfo) }),
|
||||
CheckForUpdates: async () => ({
|
||||
success: true,
|
||||
data: {
|
||||
hasUpdate: false,
|
||||
channel: mockUpdateChannel,
|
||||
currentVersion: '0.0.0',
|
||||
latestVersion: mockUpdateChannel === 'dev' ? 'dev-browser-mock' : '0.0.0',
|
||||
},
|
||||
data: buildMockUpdateInfo(),
|
||||
}),
|
||||
CheckForUpdatesSilently: async () => ({
|
||||
success: true,
|
||||
data: {
|
||||
hasUpdate: false,
|
||||
channel: mockUpdateChannel,
|
||||
currentVersion: '0.0.0',
|
||||
latestVersion: mockUpdateChannel === 'dev' ? 'dev-browser-mock' : '0.0.0',
|
||||
},
|
||||
data: buildMockUpdateInfo(),
|
||||
}),
|
||||
GetUpdateChannel: async () => ({ success: true, data: { channel: mockUpdateChannel } }),
|
||||
OpenDownloadedUpdateDirectory: async () => ({ success: false }),
|
||||
|
||||
@@ -51,18 +51,19 @@ type updateState struct {
|
||||
}
|
||||
|
||||
type UpdateInfo struct {
|
||||
HasUpdate bool `json:"hasUpdate"`
|
||||
Channel string `json:"channel"`
|
||||
CurrentVersion string `json:"currentVersion"`
|
||||
LatestVersion string `json:"latestVersion"`
|
||||
ReleaseName string `json:"releaseName"`
|
||||
ReleaseNotesURL string `json:"releaseNotesUrl"`
|
||||
AssetName string `json:"assetName"`
|
||||
AssetURL string `json:"assetUrl"`
|
||||
AssetSize int64 `json:"assetSize"`
|
||||
SHA256 string `json:"sha256"`
|
||||
Downloaded bool `json:"downloaded"`
|
||||
DownloadPath string `json:"downloadPath,omitempty"`
|
||||
HasUpdate bool `json:"hasUpdate"`
|
||||
Channel string `json:"channel"`
|
||||
CurrentVersion string `json:"currentVersion"`
|
||||
LatestVersion string `json:"latestVersion"`
|
||||
ReleaseName string `json:"releaseName"`
|
||||
ReleasePublishedAt string `json:"releasePublishedAt,omitempty"`
|
||||
ReleaseNotesURL string `json:"releaseNotesUrl"`
|
||||
AssetName string `json:"assetName"`
|
||||
AssetURL string `json:"assetUrl"`
|
||||
AssetSize int64 `json:"assetSize"`
|
||||
SHA256 string `json:"sha256"`
|
||||
Downloaded bool `json:"downloaded"`
|
||||
DownloadPath string `json:"downloadPath,omitempty"`
|
||||
}
|
||||
|
||||
type AppInfo struct {
|
||||
@@ -108,11 +109,12 @@ type updatePathCandidate struct {
|
||||
}
|
||||
|
||||
type githubRelease struct {
|
||||
TagName string `json:"tag_name"`
|
||||
Name string `json:"name"`
|
||||
HTMLURL string `json:"html_url"`
|
||||
Prerelease bool `json:"prerelease"`
|
||||
Assets []githubAsset `json:"assets"`
|
||||
TagName string `json:"tag_name"`
|
||||
Name string `json:"name"`
|
||||
HTMLURL string `json:"html_url"`
|
||||
PublishedAt string `json:"published_at"`
|
||||
Prerelease bool `json:"prerelease"`
|
||||
Assets []githubAsset `json:"assets"`
|
||||
}
|
||||
|
||||
type githubAsset struct {
|
||||
@@ -458,12 +460,13 @@ func fetchLatestUpdateInfo(channel updateChannel) (UpdateInfo, error) {
|
||||
}
|
||||
if !hasUpdate {
|
||||
return UpdateInfo{
|
||||
HasUpdate: false,
|
||||
Channel: string(channel),
|
||||
CurrentVersion: currentVersion,
|
||||
LatestVersion: latestVersion,
|
||||
ReleaseName: release.Name,
|
||||
ReleaseNotesURL: release.HTMLURL,
|
||||
HasUpdate: false,
|
||||
Channel: string(channel),
|
||||
CurrentVersion: currentVersion,
|
||||
LatestVersion: latestVersion,
|
||||
ReleaseName: release.Name,
|
||||
ReleasePublishedAt: strings.TrimSpace(release.PublishedAt),
|
||||
ReleaseNotesURL: release.HTMLURL,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -492,16 +495,17 @@ func fetchLatestUpdateInfo(channel updateChannel) (UpdateInfo, error) {
|
||||
return UpdateInfo{}, localizedUpdateError{key: "app.update.backend.error.sha256_missing_current_package"}
|
||||
}
|
||||
return UpdateInfo{
|
||||
HasUpdate: hasUpdate,
|
||||
Channel: string(channel),
|
||||
CurrentVersion: currentVersion,
|
||||
LatestVersion: latestVersion,
|
||||
ReleaseName: release.Name,
|
||||
ReleaseNotesURL: release.HTMLURL,
|
||||
AssetName: asset.Name,
|
||||
AssetURL: asset.BrowserDownloadURL,
|
||||
AssetSize: asset.Size,
|
||||
SHA256: sha256Value,
|
||||
HasUpdate: hasUpdate,
|
||||
Channel: string(channel),
|
||||
CurrentVersion: currentVersion,
|
||||
LatestVersion: latestVersion,
|
||||
ReleaseName: release.Name,
|
||||
ReleasePublishedAt: strings.TrimSpace(release.PublishedAt),
|
||||
ReleaseNotesURL: release.HTMLURL,
|
||||
AssetName: asset.Name,
|
||||
AssetURL: asset.BrowserDownloadURL,
|
||||
AssetSize: asset.Size,
|
||||
SHA256: sha256Value,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -30,9 +30,10 @@ func TestFetchLatestUpdateInfoSkipsChecksumWhenCurrentVersionIsAlreadyLatest(t *
|
||||
restoreRelease := swapUpdateFetchLatestRelease(func() (*githubRelease, error) {
|
||||
releaseCalled = true
|
||||
return &githubRelease{
|
||||
TagName: "v0.6.5",
|
||||
Name: "v0.6.5",
|
||||
HTMLURL: "https://github.com/Syngnat/GoNavi/releases/tag/v0.6.5",
|
||||
TagName: "v0.6.5",
|
||||
Name: "v0.6.5",
|
||||
HTMLURL: "https://github.com/Syngnat/GoNavi/releases/tag/v0.6.5",
|
||||
PublishedAt: "2026-07-08T11:15:00Z",
|
||||
Assets: []githubAsset{
|
||||
{
|
||||
Name: assetName,
|
||||
@@ -84,9 +85,10 @@ func TestFetchLatestUpdateInfoUsesAssetDigestWhenUpdateIsAvailable(t *testing.T)
|
||||
|
||||
restoreRelease := swapUpdateFetchLatestRelease(func() (*githubRelease, error) {
|
||||
return &githubRelease{
|
||||
TagName: "v0.6.5",
|
||||
Name: "v0.6.5",
|
||||
HTMLURL: "https://github.com/Syngnat/GoNavi/releases/tag/v0.6.5",
|
||||
TagName: "v0.6.5",
|
||||
Name: "v0.6.5",
|
||||
HTMLURL: "https://github.com/Syngnat/GoNavi/releases/tag/v0.6.5",
|
||||
PublishedAt: "2026-07-08T11:15:00Z",
|
||||
Assets: []githubAsset{
|
||||
{
|
||||
Name: assetName,
|
||||
@@ -119,6 +121,9 @@ func TestFetchLatestUpdateInfoUsesAssetDigestWhenUpdateIsAvailable(t *testing.T)
|
||||
if info.SHA256 != strings.ToLower(digest) || info.AssetName != assetName {
|
||||
t.Fatalf("unexpected update info: %#v", info)
|
||||
}
|
||||
if info.ReleasePublishedAt != "2026-07-08T11:15:00Z" {
|
||||
t.Fatalf("expected release published time to be preserved, got %#v", info)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFetchLatestUpdateInfoFallsBackToChecksumFileWhenAssetDigestMissing(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user