mirror of
https://github.com/balena-io/balena-cli.git
synced 2024-12-21 06:33:28 +00:00
Add tests for release export & import.
Change-type: patch Signed-off-by: Carlo Miguel F. Cruz <carloc@balena.io>
This commit is contained in:
parent
6c756d5e80
commit
dea07bc720
109
tests/commands/release/export.spec.ts
Normal file
109
tests/commands/release/export.spec.ts
Normal 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}`,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
113
tests/commands/release/import.spec.ts
Normal file
113
tests/commands/release/import.spec.ts
Normal 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
BIN
tests/test-data/release.tar
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user