230 lines
11 KiB
JavaScript
230 lines
11 KiB
JavaScript
import { describe, it, before, after, afterEach } from 'mocha';
|
|
import assert from 'node:assert/strict';
|
|
import BoxError from '../boxerror.js';
|
|
import common from './common.js';
|
|
import community from '../community.js';
|
|
import nock from 'nock';
|
|
import safe from 'safetydance';
|
|
|
|
const validManifest = Object.assign({}, common.manifest, {
|
|
minBoxVersion: '9.1.0',
|
|
iconUrl: 'https://example.com/icon.png',
|
|
packagerName: 'Cloudron',
|
|
packagerUrl: 'https://cloudron.io',
|
|
tags: [ 'test' ],
|
|
changelog: '12345',
|
|
mediaLinks: [ 'https://example.com/shot.png' ]
|
|
});
|
|
|
|
const versionsFixture = {
|
|
stable: true,
|
|
versions: {
|
|
'0.1.0': {
|
|
manifest: validManifest,
|
|
publishState: 'published',
|
|
creationDate: '2026-01-01T00:00:00.000Z',
|
|
ts: Date.now()
|
|
}
|
|
}
|
|
};
|
|
|
|
describe('Community', function () {
|
|
before(function () {
|
|
if (!nock.isActive()) nock.activate();
|
|
});
|
|
|
|
after(function () {
|
|
nock.restore();
|
|
});
|
|
|
|
afterEach(function () {
|
|
nock.cleanAll();
|
|
});
|
|
|
|
describe('_getUrlCandidates', function () {
|
|
it('returns github blob URL and raw URL', function () {
|
|
assert.deepEqual(
|
|
community._getUrlCandidates(new URL('https://github.com/cloudron/test-app/blob/main/CloudronVersions.json')),
|
|
[
|
|
'https://github.com/cloudron/test-app/blob/main/CloudronVersions.json',
|
|
'https://raw.githubusercontent.com/cloudron/test-app/main/CloudronVersions.json'
|
|
]
|
|
);
|
|
assert.deepEqual(
|
|
community._getUrlCandidates(new URL('https://github.com/cloudron/test-app/blob/main/packaging/CloudronVersions.json')),
|
|
[
|
|
'https://github.com/cloudron/test-app/blob/main/packaging/CloudronVersions.json',
|
|
'https://raw.githubusercontent.com/cloudron/test-app/main/packaging/CloudronVersions.json'
|
|
]
|
|
);
|
|
});
|
|
|
|
it('returns gitlab blob URL and raw URL', function () {
|
|
assert.deepEqual(
|
|
community._getUrlCandidates(new URL('https://gitlab.com/cloudron/test-app/-/blob/main/CloudronVersions.json')),
|
|
[
|
|
'https://gitlab.com/cloudron/test-app/-/blob/main/CloudronVersions.json',
|
|
'https://gitlab.com/cloudron/test-app/-/raw/main/CloudronVersions.json'
|
|
]
|
|
);
|
|
assert.deepEqual(
|
|
community._getUrlCandidates(new URL('https://my.gitlab.company/group/subgroup/test-app/-/blob/main/path/CloudronVersions.json')),
|
|
[
|
|
'https://my.gitlab.company/group/subgroup/test-app/-/blob/main/path/CloudronVersions.json',
|
|
'https://my.gitlab.company/group/subgroup/test-app/-/raw/main/path/CloudronVersions.json'
|
|
]
|
|
);
|
|
});
|
|
|
|
it('returns gitea/forgejo/gogs src URL and raw URL', function () {
|
|
assert.deepEqual(
|
|
community._getUrlCandidates(new URL('https://gitea.example.com/user/repo/src/branch/main/CloudronVersions.json')),
|
|
[
|
|
'https://gitea.example.com/user/repo/src/branch/main/CloudronVersions.json',
|
|
'https://gitea.example.com/user/repo/raw/branch/main/CloudronVersions.json'
|
|
]
|
|
);
|
|
assert.deepEqual(
|
|
community._getUrlCandidates(new URL('https://codeberg.org/forgejo/forgejo/src/branch/forgejo/packaging/CloudronVersions.json')),
|
|
[
|
|
'https://codeberg.org/forgejo/forgejo/src/branch/forgejo/packaging/CloudronVersions.json',
|
|
'https://codeberg.org/forgejo/forgejo/raw/branch/forgejo/packaging/CloudronVersions.json'
|
|
]
|
|
);
|
|
assert.deepEqual(
|
|
community._getUrlCandidates(new URL('https://gogs.example.com/user/repo/src/tag/v1.0.0/CloudronVersions.json')),
|
|
[
|
|
'https://gogs.example.com/user/repo/src/tag/v1.0.0/CloudronVersions.json',
|
|
'https://gogs.example.com/user/repo/raw/tag/v1.0.0/CloudronVersions.json'
|
|
]
|
|
);
|
|
});
|
|
|
|
it('returns single candidate for already-raw github URL', function () {
|
|
assert.deepEqual(
|
|
community._getUrlCandidates(new URL('https://raw.githubusercontent.com/cloudron/test-app/main/CloudronVersions.json')),
|
|
['https://raw.githubusercontent.com/cloudron/test-app/main/CloudronVersions.json']
|
|
);
|
|
});
|
|
|
|
it('appends CloudronVersions.json when missing', function () {
|
|
assert.deepEqual(
|
|
community._getUrlCandidates(new URL('https://example.com/cloudron/webmail/')),
|
|
['https://example.com/cloudron/webmail/CloudronVersions.json']
|
|
);
|
|
assert.deepEqual(
|
|
community._getUrlCandidates(new URL('https://github.com/cloudron/test-app/blob/main/packaging/')),
|
|
[
|
|
'https://github.com/cloudron/test-app/blob/main/packaging/CloudronVersions.json',
|
|
'https://raw.githubusercontent.com/cloudron/test-app/main/packaging/CloudronVersions.json'
|
|
]
|
|
);
|
|
assert.deepEqual(
|
|
community._getUrlCandidates(new URL('https://github.com/cloudron/test-app')),
|
|
['https://github.com/cloudron/test-app/CloudronVersions.json']
|
|
);
|
|
});
|
|
|
|
it('strips query params', function () {
|
|
assert.deepEqual(
|
|
community._getUrlCandidates(new URL('https://gitlab.com/group/project/-/blob/main/CloudronVersions.json?ref_type=heads')),
|
|
[
|
|
'https://gitlab.com/group/project/-/blob/main/CloudronVersions.json',
|
|
'https://gitlab.com/group/project/-/raw/main/CloudronVersions.json'
|
|
]
|
|
);
|
|
});
|
|
|
|
it('returns single candidate for plain surfer URL', function () {
|
|
assert.deepEqual(
|
|
community._getUrlCandidates(new URL('https://minimal-space.de/cloudron/webmail/CloudronVersions.json')),
|
|
['https://minimal-space.de/cloudron/webmail/CloudronVersions.json']
|
|
);
|
|
});
|
|
|
|
it('generates forge candidates for bare repo URL with git in subdomain', function () {
|
|
assert.deepEqual(
|
|
community._getUrlCandidates(new URL('https://git.cloudron.io/platform/test-app')),
|
|
[
|
|
'https://git.cloudron.io/platform/test-app/CloudronVersions.json',
|
|
'https://git.cloudron.io/platform/test-app/-/raw/master/CloudronVersions.json',
|
|
'https://git.cloudron.io/platform/test-app/-/raw/main/CloudronVersions.json',
|
|
'https://git.cloudron.io/platform/test-app/raw/branch/master/CloudronVersions.json',
|
|
'https://git.cloudron.io/platform/test-app/raw/branch/main/CloudronVersions.json'
|
|
]
|
|
);
|
|
});
|
|
|
|
it('generates forge candidates for bare gitlab.com repo URL', function () {
|
|
assert.deepEqual(
|
|
community._getUrlCandidates(new URL('https://gitlab.com/group/project')),
|
|
[
|
|
'https://gitlab.com/group/project/CloudronVersions.json',
|
|
'https://gitlab.com/group/project/-/raw/master/CloudronVersions.json',
|
|
'https://gitlab.com/group/project/-/raw/main/CloudronVersions.json',
|
|
'https://gitlab.com/group/project/raw/branch/master/CloudronVersions.json',
|
|
'https://gitlab.com/group/project/raw/branch/main/CloudronVersions.json'
|
|
]
|
|
);
|
|
});
|
|
|
|
it('does not generate forge candidates for non-git hostname', function () {
|
|
assert.deepEqual(
|
|
community._getUrlCandidates(new URL('https://example.com/some/path')),
|
|
['https://example.com/some/path/CloudronVersions.json']
|
|
);
|
|
});
|
|
});
|
|
|
|
it('resolveVersionsUrl returns direct URL and version data', async function () {
|
|
nock('https://example.com')
|
|
.get('/CloudronVersions.json')
|
|
.reply(200, versionsFixture);
|
|
|
|
const result = await community.resolveVersionsUrl('https://example.com/CloudronVersions.json', '0.1.0');
|
|
assert.equal(result.resolvedUrl, 'https://example.com/CloudronVersions.json');
|
|
assert.equal(result.versionsUrl, 'https://example.com/CloudronVersions.json@0.1.0');
|
|
assert.deepEqual(result.manifest, validManifest);
|
|
});
|
|
|
|
it('resolveVersionsUrl handles browser blob link to CloudronVersions.json', async function () {
|
|
nock('https://github.com')
|
|
.get('/cloudron/test-app/blob/main/CloudronVersions.json')
|
|
.reply(200, '<html>not json</html>');
|
|
|
|
nock('https://raw.githubusercontent.com')
|
|
.get('/cloudron/test-app/main/CloudronVersions.json')
|
|
.reply(200, versionsFixture);
|
|
|
|
const result = await community.resolveVersionsUrl('https://github.com/cloudron/test-app/blob/main/CloudronVersions.json', 'latest');
|
|
|
|
assert.equal(result.resolvedUrl, 'https://raw.githubusercontent.com/cloudron/test-app/main/CloudronVersions.json');
|
|
assert.equal(result.versionsUrl, 'https://raw.githubusercontent.com/cloudron/test-app/main/CloudronVersions.json@latest');
|
|
});
|
|
|
|
it('resolveVersionsUrl preserves hinted path from blob URL', async function () {
|
|
nock('https://raw.githubusercontent.com')
|
|
.get('/cloudron/test-app/main/packaging/CloudronVersions.json')
|
|
.reply(200, versionsFixture);
|
|
|
|
const result = await community.resolveVersionsUrl('https://github.com/cloudron/test-app/blob/main/packaging/CloudronVersions.json', 'latest');
|
|
assert.equal(result.resolvedUrl, 'https://raw.githubusercontent.com/cloudron/test-app/main/packaging/CloudronVersions.json');
|
|
});
|
|
|
|
it('resolveVersionsUrl accepts already raw github URL', async function () {
|
|
nock('https://raw.githubusercontent.com')
|
|
.get('/cloudron/test-app/main/CloudronVersions.json')
|
|
.reply(200, versionsFixture);
|
|
|
|
const result = await community.resolveVersionsUrl('https://raw.githubusercontent.com/cloudron/test-app/main/CloudronVersions.json', 'latest');
|
|
|
|
assert.equal(result.resolvedUrl, 'https://raw.githubusercontent.com/cloudron/test-app/main/CloudronVersions.json');
|
|
});
|
|
|
|
it('resolveVersionsUrl returns not found when no candidate works', async function () {
|
|
const [error] = await safe(community.resolveVersionsUrl('https://github.com/cloudron/missing', 'latest'));
|
|
assert.equal(error.reason, BoxError.NOT_FOUND);
|
|
});
|
|
|
|
});
|