From 5a1065c646dc9fb79f930e64e5bead31dee96f1c Mon Sep 17 00:00:00 2001 From: Joooye_34 Date: Fri, 29 Dec 2023 04:39:28 +0000 Subject: [PATCH] test(electron): add unit tests for updater (#5439) --- .../electron/test/main/fixtures/feeds.txt | 50 +++++++++ .../main/fixtures/releases/0.11.1-beta.1.txt | 20 ++++ .../fixtures/releases/0.11.1-canary.1.txt | 20 ++++ .../test/main/fixtures/releases/0.11.1.txt | 20 ++++ .../electron/test/main/mocks/app-adapter.ts | 34 ++++++ .../electron/test/main/mocks/http-executor.ts | 26 +++++ .../electron/test/main/mocks/index.ts | 3 + .../electron/test/main/mocks/updater.ts | 37 +++++++ .../electron/test/main/updater.spec.ts | 104 ++++++++++++++++++ 9 files changed, 314 insertions(+) create mode 100644 packages/frontend/electron/test/main/fixtures/feeds.txt create mode 100644 packages/frontend/electron/test/main/fixtures/releases/0.11.1-beta.1.txt create mode 100644 packages/frontend/electron/test/main/fixtures/releases/0.11.1-canary.1.txt create mode 100644 packages/frontend/electron/test/main/fixtures/releases/0.11.1.txt create mode 100644 packages/frontend/electron/test/main/mocks/app-adapter.ts create mode 100644 packages/frontend/electron/test/main/mocks/http-executor.ts create mode 100644 packages/frontend/electron/test/main/mocks/index.ts create mode 100644 packages/frontend/electron/test/main/mocks/updater.ts create mode 100644 packages/frontend/electron/test/main/updater.spec.ts diff --git a/packages/frontend/electron/test/main/fixtures/feeds.txt b/packages/frontend/electron/test/main/fixtures/feeds.txt new file mode 100644 index 0000000000..315f9574f1 --- /dev/null +++ b/packages/frontend/electron/test/main/fixtures/feeds.txt @@ -0,0 +1,50 @@ + + + tag:github.com,2008:https://github.com/toeverything/AFFiNE/releases + + + Release notes from AFFiNE + 2023-12-28T16:36:36+08:00 + + tag:github.com,2008:Repository/519859998/0.11.0-nightly-202312280901-e11e827 + 2023-12-28T17:23:15+08:00 + + 0.11.0-nightly-202312280901-e11e827 + No content. + + github-actions[bot] + + + + + tag:github.com,2008:Repository/519859998/v0.11.1 + 2023-12-27T19:40:15+08:00 + + 0.11.1 + + github-actions[bot] + + + + + tag:github.com,2008:Repository/519859998/v0.11.1-beta.1 + 2023-12-27T18:30:52+08:00 + + 0.11.1-beta.1 + + github-actions[bot] + + + + + tag:github.com,2008:Repository/519859998/v0.11.1-canary.1 + 2023-12-27T10:47:52+08:00 + + 0.11.1-canary.1 + + + github-actions[bot] + + + + diff --git a/packages/frontend/electron/test/main/fixtures/releases/0.11.1-beta.1.txt b/packages/frontend/electron/test/main/fixtures/releases/0.11.1-beta.1.txt new file mode 100644 index 0000000000..fd9a7434cf --- /dev/null +++ b/packages/frontend/electron/test/main/fixtures/releases/0.11.1-beta.1.txt @@ -0,0 +1,20 @@ +version: 0.11.1-beta.1 +files: + - url: affine-beta-windows-x64.exe + sha512: uQdF7bEZteCMp/bT7vwCjlEcAf6osW9zZ+Q5grEkmbHPpcqCCzLudguXqHIwohO4GGq9pS8H4kJzG0LZc+SmXg== + size: 179515752 + - url: affine-beta-macos-arm64.dmg + sha512: gRsi4XO4+kREQuLX2CnS2V9vvUmBMmoGR6MvoB6TEFm1WiC8k8v69DRKYQ0Vjlom/j9HZlBEYUTqcW7IsMgrpw== + size: 169726061 + - url: affine-beta-macos-arm64.zip + sha512: +aXkjJfQnp2dUz3Y0i5cL6V5Hm1OkYVlwM/KAcZfLlvLoU3zQ0zSZvJ6+H2IlIhOebSq56Ip76H5NP8fe7UnOw== + size: 169007175 + - url: affine-beta-macos-x64.dmg + sha512: i5V95dLx3iWFpNj89wFU40THT3Oeow8g706Z6/mG1zYOIR3kXUkIpp6+wJmlfe9g4iwNmRd0rgI4HAG5LaQagg== + size: 175712730 + - url: affine-beta-macos-x64.zip + sha512: DnRUHcj+4FluII5kTbUuEAQI2CIRufd1Z0P98pwa/uX5hk2iOj1QzMD8WM+MTbFNC6rZvMtMlos8GyVLsZmK0w== + size: 175235583 +path: affine-beta-windows-x64.exe +sha512: uQdF7bEZteCMp/bT7vwCjlEcAf6osW9zZ+Q5grEkmbHPpcqCCzLudguXqHIwohO4GGq9pS8H4kJzG0LZc+SmXg== +releaseDate: 2023-12-27T08:59:31.826Z diff --git a/packages/frontend/electron/test/main/fixtures/releases/0.11.1-canary.1.txt b/packages/frontend/electron/test/main/fixtures/releases/0.11.1-canary.1.txt new file mode 100644 index 0000000000..36dc8f50c8 --- /dev/null +++ b/packages/frontend/electron/test/main/fixtures/releases/0.11.1-canary.1.txt @@ -0,0 +1,20 @@ +version: 0.11.1-canary.1 +files: + - url: affine-canary-windows-x64.exe + sha512: qbK4N6+axVO2dA/iPzfhANWxCZXY1S3ci9qYIT1v/h0oCjc6vqpXU+2KRGL5mplL6wmVgJAOpqrfnq9gHMsfDg== + size: 179526504 + - url: affine-canary-macos-arm64.dmg + sha512: ++LAGuxTmFAVd65k8UpKKfU19iisvXHKDDfPkGlTVC000QP3foeS21BmTgYnM1ZuhEC6KGzSGrqvUDVDNYnRmA== + size: 169903530 + - url: affine-canary-macos-arm64.zip + sha512: IAWbCpVqPPVVzDowGKGnKZzHN2jPgAW40v+bUZR2tdgDrqIAVy4YdamYz8WmEwpg1TXmi0ueSsWgGFPgBIr0iA== + size: 169085665 + - url: affine-canary-macos-x64.dmg + sha512: 4y4/KkmkmFmZ94ntRAN0lSX7aZzgEd4Wg7f85Tff296P3x85sbPF4FFIp++Zx/cgBZBUQwMWe9xeGlefompQ/g== + size: 175920978 + - url: affine-canary-macos-x64.zip + sha512: S1MuMHooMOQ9eJ+coRYmyz6k5lnWIMqHotSrywxGGo7sFXBY+O5F4PeKgNREJtwXjAIxv0GxZVvbe5jc+onw9w== + size: 175315484 +path: affine-canary-windows-x64.exe +sha512: qbK4N6+axVO2dA/iPzfhANWxCZXY1S3ci9qYIT1v/h0oCjc6vqpXU+2KRGL5mplL6wmVgJAOpqrfnq9gHMsfDg== +releaseDate: 2023-12-26T13:24:28.221Z diff --git a/packages/frontend/electron/test/main/fixtures/releases/0.11.1.txt b/packages/frontend/electron/test/main/fixtures/releases/0.11.1.txt new file mode 100644 index 0000000000..843b632287 --- /dev/null +++ b/packages/frontend/electron/test/main/fixtures/releases/0.11.1.txt @@ -0,0 +1,20 @@ +version: 0.11.1 +files: + - url: affine-stable-windows-x64.exe + sha512: qHRO31Fb8F+Q/hiGiJJ2WH+PpSC5iUIPtWujUoI+XNMz7UfhCGxoVW9U38CTE9LecILS119SZN0rrHkmu+nQiw== + size: 179504488 + - url: affine-stable-macos-arm64.dmg + sha512: uDS7bZusoU5p2t4bi1k/IdvChj3BRIWbOLanbhAfIjwBmf9FM3553wgeUzQLRMRuD5wavsw/aA1BaqFJIbwkyQ== + size: 169793193 + - url: affine-stable-macos-arm64.zip + sha512: n4CrOgNPd70WqPfe0ZEKzmyOdqOlVnFvQqylIlt92eqKrUb8jcxVThQY+GU2Jy3jVjvKqUvubodDbIkQhXQ1xQ== + size: 169014676 + - url: affine-stable-macos-x64.dmg + sha512: xFy1kt1025h1wqBjHt+IoPweC40UqAZvZLI2XD3LIlPG60jZ03+QM75UwaXYuVYEqe3kO9a3WeFcrfGdoj4Hzw== + size: 175720872 + - url: affine-stable-macos-x64.zip + sha512: FfgX22ytleb8fv35odzhDyFsmiUVPdI4XQjTB4uDmkhQ719i+W4yctUnP5TSCpymYC0HgVRFSVg4Jkuuli+8ug== + size: 175244411 +path: affine-stable-windows-x64.exe +sha512: qHRO31Fb8F+Q/hiGiJJ2WH+PpSC5iUIPtWujUoI+XNMz7UfhCGxoVW9U38CTE9LecILS119SZN0rrHkmu+nQiw== +releaseDate: 2023-12-27T11:04:53.014Z diff --git a/packages/frontend/electron/test/main/mocks/app-adapter.ts b/packages/frontend/electron/test/main/mocks/app-adapter.ts new file mode 100644 index 0000000000..cf18d6b314 --- /dev/null +++ b/packages/frontend/electron/test/main/mocks/app-adapter.ts @@ -0,0 +1,34 @@ +import type { AppAdapter } from 'electron-updater/out/AppAdapter'; + +/** + * For testing and same as: + * https://github.com/electron-userland/electron-builder/blob/master/packages/electron-updater/src/ElectronAppAdapter.ts + */ +export class MockedAppAdapter implements AppAdapter { + version: string; + name = 'AFFiNE-testing'; + isPackaged = true; + appUpdateConfigPath = ''; + userDataPath = ''; + baseCachePath = ''; + + constructor(version: string) { + this.version = version; + } + + whenReady() { + return Promise.resolve(); + } + + relaunch() { + return; + } + + quit() { + return; + } + + onQuit(_handler: (exitCode: number) => void) { + return; + } +} diff --git a/packages/frontend/electron/test/main/mocks/http-executor.ts b/packages/frontend/electron/test/main/mocks/http-executor.ts new file mode 100644 index 0000000000..b803eb7c6d --- /dev/null +++ b/packages/frontend/electron/test/main/mocks/http-executor.ts @@ -0,0 +1,26 @@ +import http from 'node:https'; + +import { HttpExecutor } from 'builder-util-runtime'; +import type { ClientRequest } from 'electron'; + +/** + * For testing and same as: + * https://github.com/electron-userland/electron-builder/blob/master/packages/electron-updater/src/electronHttpExecutor.ts + */ +export class MockedHttpExecutor extends HttpExecutor { + createRequest( + options: any, + callback: (response: any) => void + ): ClientRequest { + if (options.headers && options.headers.Host) { + // set host value from headers.Host + options.host = options.headers.Host; + // remove header property 'Host', if not removed causes net::ERR_INVALID_ARGUMENT exception + delete options.headers.Host; + } + + const request = http.request(options); + request.on('response', callback); + return request as unknown as ClientRequest; + } +} diff --git a/packages/frontend/electron/test/main/mocks/index.ts b/packages/frontend/electron/test/main/mocks/index.ts new file mode 100644 index 0000000000..2ba1e3996c --- /dev/null +++ b/packages/frontend/electron/test/main/mocks/index.ts @@ -0,0 +1,3 @@ +export * from './app-adapter'; +export * from './http-executor'; +export * from './updater'; diff --git a/packages/frontend/electron/test/main/mocks/updater.ts b/packages/frontend/electron/test/main/mocks/updater.ts new file mode 100644 index 0000000000..f3fd31bd61 --- /dev/null +++ b/packages/frontend/electron/test/main/mocks/updater.ts @@ -0,0 +1,37 @@ +import 'electron-updater'; // Prevent BaseUpdater is undefined. + +import { type AllPublishOptions, UUID } from 'builder-util-runtime'; +import { randomBytes } from 'crypto'; +import type { AppAdapter } from 'electron-updater/out/AppAdapter'; +import type { DownloadUpdateOptions } from 'electron-updater/out/AppUpdater'; +import type { InstallOptions } from 'electron-updater/out/BaseUpdater'; +import { BaseUpdater } from 'electron-updater/out/BaseUpdater'; + +import { MockedHttpExecutor } from './http-executor'; + +/** + * For testing, like: + * https://github.com/electron-userland/electron-builder/blob/master/packages/electron-updater/src/MacUpdater.ts + */ +export class MockedUpdater extends BaseUpdater { + httpExecutor: MockedHttpExecutor; + + constructor(options?: AllPublishOptions | null, app?: AppAdapter) { + super(options, app); + + this.httpExecutor = new MockedHttpExecutor(); + Object.assign(this, { + getOrCreateStagingUserId: () => { + const id = UUID.v5(randomBytes(4096), UUID.OID); + return id; + }, + }); + } + + doInstall(_options: InstallOptions) { + return true; + } + doDownloadUpdate(_options: DownloadUpdateOptions): Promise { + return Promise.resolve([]); + } +} diff --git a/packages/frontend/electron/test/main/updater.spec.ts b/packages/frontend/electron/test/main/updater.spec.ts new file mode 100644 index 0000000000..51c2864479 --- /dev/null +++ b/packages/frontend/electron/test/main/updater.spec.ts @@ -0,0 +1,104 @@ +import nodePath from 'node:path'; + +import fs from 'fs-extra'; +import { flatten } from 'lodash-es'; +import { http, HttpResponse } from 'msw'; +import { setupServer } from 'msw/node'; +import { compare } from 'semver'; +import { afterAll, afterEach, beforeAll, describe, expect, it } from 'vitest'; + +import { CustomGitHubProvider } from '../../src/main/updater/custom-github-provider'; +import { MockedAppAdapter, MockedUpdater } from './mocks'; + +const platformTail = (() => { + // https://github.com/electron-userland/electron-builder/blob/master/packages/electron-updater/src/providers/Provider.ts#L30 + const platform = process.platform; + if (platform === 'linux') { + const arch = process.env['TEST_UPDATER_ARCH'] || process.arch; + const archSuffix = arch === 'x64' ? '' : `-${arch}`; + return '-linux' + archSuffix; + } else { + return platform === 'darwin' ? '-mac' : ''; + } +})(); + +describe('testing for client update', () => { + const expectReleaseList = [ + { buildType: 'stable', version: '0.11.1' }, + { buildType: 'beta', version: '0.11.1-beta.1' }, + { buildType: 'canary', version: '0.11.1-canary.1' }, + ]; + + const restHandlers = [ + http.get( + 'https://github.com/toeverything/AFFiNE/releases.atom', + async () => { + const buffer = await fs.readFile( + nodePath.join(__dirname, 'fixtures', 'feeds.txt') + ); + const content = buffer.toString(); + return HttpResponse.xml(content); + } + ), + ...flatten( + expectReleaseList.map(({ version, buildType }) => { + function response404() { + return HttpResponse.text('Not Found', { status: 404 }); + } + + return [ + http.get( + `https://github.com/toeverything/AFFiNE/releases/download/v${version}/latest${platformTail}.yml`, + async function responseContent() { + const buffer = await fs.readFile( + nodePath.join( + __dirname, + 'fixtures', + 'releases', + `${version}.txt` + ) + ); + const content = buffer.toString(); + return HttpResponse.text(content); + } + ), + http.get( + `https://github.com/toeverything/AFFiNE/releases/download/v${version}/${buildType}${platformTail}.yml`, + response404 + ), + ]; + }) + ), + ]; + + const server = setupServer(...restHandlers); + + beforeAll(() => server.listen({ onUnhandledRequest: 'error' })); + afterAll(() => server.close()); + afterEach(() => server.resetHandlers()); + + for (const { buildType } of expectReleaseList) { + it(`check update for ${buildType} channel successfully`, async () => { + const app = new MockedAppAdapter('0.10.0'); + const updater = new MockedUpdater(null, app); + updater.allowPrerelease = buildType !== 'stable'; + + const feedUrl: Parameters[0] = { + channel: buildType, + // hack for custom provider + provider: 'custom' as 'github', + repo: 'AFFiNE', + owner: 'toeverything', + releaseType: buildType === 'stable' ? 'release' : 'prerelease', + // @ts-expect-error hack for custom provider + updateProvider: CustomGitHubProvider, + }; + + updater.setFeedURL(feedUrl); + + const info = await updater.checkForUpdates(); + expect(info).not.toBe(null); + expect(compare(info!.updateInfo.version, '0.10.0')).toBe(1); + }); + } +});