Add tests for release export & import.

Change-type: patch
Signed-off-by: Carlo Miguel F. Cruz <carloc@balena.io>
This commit is contained in:
Carlo Miguel F. Cruz 2024-09-13 01:52:12 +08:00
parent 6c756d5e80
commit dea07bc720
No known key found for this signature in database
GPG Key ID: 997DBC01FCE3FD53
3 changed files with 222 additions and 0 deletions

View File

@ -0,0 +1,109 @@
import * as stream from 'node:stream';
import { cleanOutput, runCommand } from '../../helpers';
import { BalenaAPIMock } from '../../nock/balena-api-mock';
import { expect } from 'chai';
import * as mock from 'mock-require';
import * as sinon from 'sinon';
import { promises as fs } from 'fs';
// "itSS" means "it() Skip Standalone"
const itSS = process.env.BALENA_CLI_TEST_TYPE === 'standalone' ? it.skip : it;
describe('balena release export', function () {
const appCommit = 'badc0ffe';
const appSlug = 'testOrg/testApp';
const appVersion = '1.2.3+rev1';
const outputPath = '/tmp/release.tar';
let api: BalenaAPIMock;
let releaseFileBuffer: Buffer;
const releaseBundleCreateStub = sinon.stub();
this.beforeEach(async function () {
api = new BalenaAPIMock();
releaseFileBuffer = await fs.readFile('./tests/test-data/release.tar');
mock('@balena/release-bundle', {
create: releaseBundleCreateStub,
});
});
this.afterEach(() => {
// Check all expected api calls have been made and clean up.
api.done();
mock.stop('@balena/release-bundle');
});
itSS('should export a release to a file', async () => {
api.expectGetWhoAmI();
api.expectGetRelease();
releaseBundleCreateStub.resolves(stream.Readable.from(releaseFileBuffer));
const { out, err } = await runCommand(
`release export ${appCommit} -o ${outputPath}`,
);
const lines = cleanOutput(out);
expect(lines[0]).to.contain(
`Release ${appCommit} has been exported to ${outputPath}.`,
);
expect(err).to.be.empty;
});
itSS('should fail if the create throws an error', async () => {
api.expectGetWhoAmI();
api.expectGetRelease();
const expectedError = `BalenaReleaseNotFound: Release not found: ${appCommit}`;
releaseBundleCreateStub.rejects(new Error(expectedError));
const { err } = await runCommand(
`release export ${appCommit} -o ${outputPath}`,
);
expect(cleanOutput(err, true)).to.include(
`Release ${appCommit} could not be exported: ${expectedError}`,
);
});
itSS('should parse with application slug and version', async () => {
api.expectGetWhoAmI();
api.expectGetRelease();
api.expectGetApplication();
releaseBundleCreateStub.resolves(stream.Readable.from(releaseFileBuffer));
const { out, err } = await runCommand(
`release export ${appSlug} -o ${outputPath} --version ${appVersion}`,
);
const lines = cleanOutput(out);
expect(lines[0]).to.contain(
`Release ${appSlug} version ${appVersion} has been exported to ${outputPath}.`,
);
expect(err).to.be.empty;
});
it('should fail if the app slug is provided without the release version', async () => {
api.expectGetWhoAmI();
api.expectGetRelease({ notFound: true });
const expectedError = `Release not found: ${appSlug}`;
const { err } = await runCommand(
`release export ${appSlug} -o ${outputPath}`,
);
expect(cleanOutput(err, true)).to.include(
`Release ${appSlug} could not be exported: ${expectedError}`,
);
});
it('should fail if the semver is invalid', async () => {
api.expectGetWhoAmI();
const expectedError = 'version must be valid SemVer';
const { err } = await runCommand(
`release export ${appSlug} --version ${appCommit} -o ${outputPath}`,
);
expect(cleanOutput(err, true)).to.include(
`Release ${appSlug} version ${appCommit} could not be exported: ${expectedError}`,
);
});
});

View File

@ -0,0 +1,113 @@
import { cleanOutput, runCommand } from '../../helpers';
import { BalenaAPIMock } from '../../nock/balena-api-mock';
import { expect } from 'chai';
import * as mock from 'mock-require';
import * as sinon from 'sinon';
// "itSS" means "it() Skip Standalone"
const itSS = process.env.BALENA_CLI_TEST_TYPE === 'standalone' ? it.skip : it;
describe('balena release import', function () {
const appCommit = '4c8becf0780ca69d33b638ea8fa163d7';
const appSlug = 'myOrg/myFleet';
// const appVersion = '1.2.3+rev1';
const releasePath = './tests/test-data/release.tar';
let api: BalenaAPIMock;
const releaseBundleApplyStub = sinon.stub();
this.beforeEach(async function () {
api = new BalenaAPIMock();
mock('@balena/release-bundle', {
apply: releaseBundleApplyStub,
});
});
this.afterEach(() => {
// Check all expected api calls have been made and clean up.
api.done();
mock.stop('@balena/release-bundle');
});
itSS('should import a release to an app', async () => {
api.expectGetWhoAmI();
api.expectGetApplication();
releaseBundleApplyStub.resolves(123);
const { out, err } = await runCommand(
`release import ${releasePath} ${appSlug}`,
);
const lines = cleanOutput(out);
expect(lines[0]).to.contain(
`Release bundle ${releasePath} has been imported to ${appSlug}.`,
);
expect(err).to.be.empty;
});
itSS(
'should import a release to an app with a version override',
async () => {
api.expectGetWhoAmI();
api.expectGetApplication();
releaseBundleApplyStub.resolves(123);
const { out, err } = await runCommand(
`release import ${releasePath} ${appSlug} --override-version 1.2.3`,
);
const lines = cleanOutput(out);
expect(lines[0]).to.contain(
`Release bundle ${releasePath} has been imported to ${appSlug}.`,
);
expect(err).to.be.empty;
},
);
it('should fail if release file does not exist', async () => {
api.expectGetWhoAmI();
const nonExistentFile = './tests/test-data/non-existent-file.tar';
const { out, err } = await runCommand(
`release import ${nonExistentFile} ${appSlug}`,
);
expect(cleanOutput(err, true)).to.contain(
`Could not import release bundle ${nonExistentFile} to ${appSlug}: ${nonExistentFile} does not exist or is not accessible`,
);
expect(out).to.be.empty;
});
itSS('should fail if overriding version is not a valid semver', async () => {
api.expectGetWhoAmI();
api.expectGetApplication();
const expectedError = `Manifest is malformed: Expected version to be a valid semantic version but found '${appCommit}'`;
releaseBundleApplyStub.rejects(new Error(expectedError));
const { out, err } = await runCommand(
`release import ${releasePath} ${appSlug} --override-version ${appCommit}`,
);
expect(cleanOutput(err, true)).to.contain(
`Could not import release bundle ${releasePath} to ${appSlug}: ${expectedError}`,
);
expect(out).to.be.empty;
});
itSS(
'should fail if a successful release with the same commit already exists',
async () => {
api.expectGetWhoAmI();
api.expectGetApplication();
const expectedError = `A successful release with commit ${appCommit} (1.2.3) already exists; nothing to do`;
releaseBundleApplyStub.rejects(new Error(expectedError));
const { out, err } = await runCommand(
`release import ${releasePath} ${appSlug}`,
);
expect(cleanOutput(err, true)).to.include(
`Could not import release bundle ${releasePath} to ${appSlug}: ${expectedError}`,
);
expect(out).to.be.empty;
},
);
});

BIN
tests/test-data/release.tar Normal file

Binary file not shown.