Files
cloudron-box/src/test/updater-test.js
T
2026-02-19 10:13:22 +01:00

175 lines
7.2 KiB
JavaScript

import { describe, it, before, after } from 'node:test';
import apps from '../apps.js';
import BoxError from '../boxerror.js';
import common from './common.js';
import constants from '../constants.js';
import assert from 'node:assert/strict';
import nock from 'nock';
import paths from '../paths.js';
import safe from 'safetydance';
import semver from 'semver';
import updater from '../updater.js';
const UPDATE_VERSION = semver.inc(constants.VERSION, 'major');
describe('updater', function () {
const { setup, cleanup, app, appstoreToken, mockApiServerOrigin } = common;
describe('settings', function () {
before(setup);
after(cleanup);
it('can get default autoupdate_pattern', async function () {
const pattern = await updater.getAutoupdatePattern();
assert.equal(pattern, '00 00 1,3,5,23 * * *');
});
it('cannot set invalid autoupdate_pattern', async function () {
const [error] = await safe(updater.setAutoupdatePattern('02 * 1 *'));
assert.equal(error.reason, BoxError.BAD_FIELD);
});
it('can set default autoupdate_pattern', async function () {
await updater.setAutoupdatePattern('02 * 1-5 * * *');
});
});
describe('checker', function () {
before(setup);
before(() => { if (!nock.isActive()) nock.activate(); });
after(cleanup);
describe('box updates', function () {
before(async function () {
safe.fs.unlinkSync(paths.BOX_UPDATE_FILE);
await updater.setAutoupdatePattern(constants.CRON_PATTERN_NEVER);
});
it('no updates', async function () {
nock.cleanAll();
const scope = nock(mockApiServerOrigin)
.get('/api/v1/boxupdate')
.query({ boxVersion: constants.VERSION, accessToken: appstoreToken, stableOnly: false })
.reply(204, { } );
await updater.checkBoxUpdate({ stableOnly: false });
const boxUpdateInfo = await updater.getBoxUpdate();
assert.equal(boxUpdateInfo, null);
assert.ok(scope.isDone());
});
it('new version', async function () {
nock.cleanAll();
const scope = nock(mockApiServerOrigin)
.get('/api/v1/boxupdate')
.query({ boxVersion: constants.VERSION, accessToken: appstoreToken, stableOnly: false })
.reply(200, { version: UPDATE_VERSION, changelog: [''], sourceTarballUrl: 'box.tar.gz', sourceTarballSigUrl: 'box.tar.gz.sig', boxVersionsUrl: 'box.versions', boxVersionsSigUrl: 'box.versions.sig', unstable: false } );
await updater.checkBoxUpdate({ stableOnly: false });
const boxUpdateInfo = await updater.getBoxUpdate();
assert.ok(boxUpdateInfo);
assert.equal(boxUpdateInfo.version, UPDATE_VERSION);
assert.equal(boxUpdateInfo.sourceTarballUrl, 'box.tar.gz');
assert.ok(scope.isDone());
});
it('bad response offers whatever was last valid', async function () {
nock.cleanAll();
const scope = nock(mockApiServerOrigin)
.get('/api/v1/boxupdate')
.query({ boxVersion: constants.VERSION, accessToken: appstoreToken, stableOnly: false })
.reply(404, { version: '2.0.0-pre.0', changelog: [''], sourceTarballUrl: 'box-pre.tar.gz' } );
await safe(updater.checkBoxUpdate({ stableOnly: false })); // ignore error
const boxUpdateInfo = await updater.getBoxUpdate();
assert.equal(boxUpdateInfo.version, UPDATE_VERSION);
assert.equal(boxUpdateInfo.sourceTarballUrl, 'box.tar.gz');
assert.ok(scope.isDone());
});
});
describe('app updates', function () {
before(async function () {
await updater.setAutoupdatePattern(constants.CRON_PATTERN_NEVER);
});
it('no updates', async function () {
nock.cleanAll();
const scope = nock(mockApiServerOrigin)
.get('/api/v1/appupdate')
.query({ boxVersion: constants.VERSION, accessToken: appstoreToken, appId: app.appStoreId, appVersion: app.manifest.version, stableOnly: false })
.reply(204, { } );
const appUpdateInfo = await updater.checkAppUpdate(app, { stableOnly: false });
assert.deepEqual(appUpdateInfo, null);
assert.ok(scope.isDone());
const tmp = await apps.get(app.id);
assert.equal(tmp.updateInfo, null);
});
it('bad response', async function () {
nock.cleanAll();
const scope = nock(mockApiServerOrigin)
.get('/api/v1/appupdate')
.query({ boxVersion: constants.VERSION, accessToken: appstoreToken, appId: app.appStoreId, appVersion: app.manifest.version, stableOnly: false })
.reply(500, { update: { manifest: { version: '1.0.0', changelog: '* some changes' } } } );
const [error] = await safe(updater.checkAppUpdate(app, { stableOnly: false }));
assert.ok(error);
assert.ok(scope.isDone());
});
it('offers new version', async function () {
nock.cleanAll();
const scope = nock(mockApiServerOrigin)
.get('/api/v1/appupdate')
.query({ boxVersion: constants.VERSION, accessToken: appstoreToken, appId: app.appStoreId, appVersion: app.manifest.version, stableOnly: false })
.reply(200, { manifest: { version: '2.0.0', changelog: '* some changes' } } );
const expectedUpdateInfo = {
manifest: { version: '2.0.0', changelog: '* some changes' },
unstable: false,
isAutoUpdatable: false,
manualUpdateReason: 'Invalid or Expired subscription'
};
const appUpdateInfo = await updater.checkAppUpdate(app, { stableOnly: false });
assert.deepEqual(appUpdateInfo.manifest, expectedUpdateInfo.manifest);
assert.ok(scope.isDone());
const tmp = await apps.get(app.id);
assert.deepEqual(tmp.updateInfo, expectedUpdateInfo);
});
it('does not offer old version', async function () {
nock.cleanAll();
const expectedUpdateInfo = {
manifest: { version: '2.0.0', changelog: '* some changes' },
unstable: false,
isAutoUpdatable: false,
manualUpdateReason: 'Invalid or Expired subscription'
};
const [error] = await safe(updater.checkAppUpdate(app, { stableOnly: false }));
assert.ok(error);
const tmp = await apps.get(app.id);
assert.deepEqual(tmp.updateInfo, expectedUpdateInfo);
});
});
});
});