diff --git a/src/app.ts b/src/app.ts index e2c4f17d..13b3e5b5 100644 --- a/src/app.ts +++ b/src/app.ts @@ -101,11 +101,9 @@ async function init() { /** Execute the oclif parser and the CLI command. */ async function oclifRun(command: string[], options: AppOptions) { - let deprecationPromise: Promise; + let deprecationPromise: Promise | undefined; // check and enforce the CLI's deprecation policy - if (unsupportedFlag || process.env.BALENARC_UNSUPPORTED) { - deprecationPromise = Promise.resolve(); - } else { + if (!(unsupportedFlag || process.env.BALENARC_UNSUPPORTED)) { const { DeprecationChecker } = await import('./deprecation'); const deprecationChecker = new DeprecationChecker(packageJSON.version); // warnAndAbortIfDeprecated uses previously cached data only diff --git a/src/utils/normalization.ts b/src/utils/normalization.ts index 1cc09fda..a490f0b5 100644 --- a/src/utils/normalization.ts +++ b/src/utils/normalization.ts @@ -75,13 +75,13 @@ export async function disambiguateReleaseParam( return (await balena.models.release.get(release, { $select: 'id' })).id; } +/* eslint-disable @typescript-eslint/require-await -- oclif parse functions require a Promise return */ /** * Convert to lowercase if looks like slug */ -export function lowercaseIfSlug(s: string) { - return s.includes('/') - ? Promise.resolve(s.toLowerCase()) - : Promise.resolve(s); +export async function lowercaseIfSlug(s: string) { + /* eslint-enable @typescript-eslint/require-await */ + return s.includes('/') ? s.toLowerCase() : s; } export function normalizeOsVersion(version: string) { diff --git a/src/utils/remote-build.ts b/src/utils/remote-build.ts index 1985b35d..fd4c3ced 100644 --- a/src/utils/remote-build.ts +++ b/src/utils/remote-build.ts @@ -110,7 +110,7 @@ export async function startRemoteBuild( const [buildRequest, stream] = await getRemoteBuildStream(build); // Setup CTRL-C handler so the user can interrupt the build - let cancellationPromise = Promise.resolve(); + let cancellationPromise: Promise | undefined; const sigintHandler = () => { process.exitCode = 130; console.error('\nReceived SIGINT, cleaning up. Please wait.'); diff --git a/src/utils/validation.ts b/src/utils/validation.ts index f3929352..af58de68 100644 --- a/src/utils/validation.ts +++ b/src/utils/validation.ts @@ -87,7 +87,8 @@ export function looksLikeInteger(input: string) { return /^(?:0|[1-9][0-9]*)$/.test(input); } -export function parseAsInteger(input: string, paramName?: string) { +// eslint-disable-next-line @typescript-eslint/require-await -- oclif parse functions require a Promise return +export async function parseAsInteger(input: string, paramName?: string) { if (!looksLikeInteger(input)) { const message = paramName == null @@ -97,7 +98,7 @@ export function parseAsInteger(input: string, paramName?: string) { throw new ExpectedError(message); } - return Promise.resolve(Number(input)); + return Number(input); } export async function tryAsInteger(input: string): Promise { @@ -108,13 +109,14 @@ export async function tryAsInteger(input: string): Promise { } } -export function parseAsLocalHostnameOrIp(input: string) { +// eslint-disable-next-line @typescript-eslint/require-await -- oclif parse functions require a Promise return +export async function parseAsLocalHostnameOrIp(input: string) { if (input && !validateLocalHostnameOrIp(input)) { throw new ExpectedError( 'The parameter must be a local hostname or IP address.', ); } - return Promise.resolve(input); + return input; } export function looksLikeFleetSlug(input: string) { diff --git a/tests/auth/server.spec.ts b/tests/auth/server.spec.ts index 66960eea..02bd2c59 100644 --- a/tests/auth/server.spec.ts +++ b/tests/auth/server.spec.ts @@ -134,7 +134,7 @@ describe('Login server:', function () { describe('given the token authenticates with the server', function () { beforeEach(function () { this.loginIfTokenValidStub = sinon.stub(utils, 'loginIfTokenValid'); - this.loginIfTokenValidStub.returns(Promise.resolve(true)); + this.loginIfTokenValidStub.resolves(true); }); afterEach(function () { @@ -153,7 +153,7 @@ describe('Login server:', function () { describe('given the token does not authenticate with the server', function () { beforeEach(function () { this.loginIfTokenValidStub = sinon.stub(utils, 'loginIfTokenValid'); - return this.loginIfTokenValidStub.returns(Promise.resolve(false)); + return this.loginIfTokenValidStub.resolves(false); }); afterEach(function () { diff --git a/tests/docker-build.ts b/tests/docker-build.ts index f5a18680..469f41eb 100644 --- a/tests/docker-build.ts +++ b/tests/docker-build.ts @@ -188,7 +188,6 @@ export async function testDockerBuildStream(o: { expect(deepJsonParse(queryParams)).to.have.deep.members( deepJsonParse(expectedQueryParams), ); - return Promise.resolve(); }, checkBuildRequestBody: (buildRequestBody: string) => inspectTarStream(buildRequestBody, expectedFiles, projectPath), @@ -246,7 +245,6 @@ export async function testPushBuildStream(o: { expect(deepJsonParse(queryParams)).to.have.deep.members( deepJsonParse(expectedQueryParams), ); - return Promise.resolve(); }, checkBuildRequestBody: (buildRequestBody) => inspectTarStream(buildRequestBody, o.expectedFiles, o.projectPath), diff --git a/tests/nock/builder-mock.ts b/tests/nock/builder-mock.ts index ef1cc55d..71450f36 100644 --- a/tests/nock/builder-mock.ts +++ b/tests/nock/builder-mock.ts @@ -37,7 +37,7 @@ export class BuilderMock extends NockMock { persist?: boolean; responseBody: any; responseCode: number; - checkURI: (uri: string) => Promise; + checkURI: (uri: string) => Promise | void; checkBuildRequestBody: (requestBody: string | Buffer) => Promise; }) { this.optPost(/^\/v3\/build($|[(?])/, opts).reply( diff --git a/tests/nock/docker-mock.ts b/tests/nock/docker-mock.ts index b21dab20..955b44b6 100644 --- a/tests/nock/docker-mock.ts +++ b/tests/nock/docker-mock.ts @@ -75,7 +75,7 @@ export class DockerMock extends NockMock { responseBody: any; responseCode: number; tag: string; - checkURI: (uri: string) => Promise; + checkURI: (uri: string) => Promise | void; checkBuildRequestBody: (requestBody: string) => Promise; }) { this.optPost( diff --git a/tests/utils/eol-conversion.spec.ts b/tests/utils/eol-conversion.spec.ts index b26c3780..678fdb2d 100644 --- a/tests/utils/eol-conversion.spec.ts +++ b/tests/utils/eol-conversion.spec.ts @@ -75,12 +75,12 @@ describe('detectEncoding() function', function () { for (const fname of sampleBinary) { const buf = await fs.readFile(path.join('node_modules', fname)); - const encoding = await detectEncoding(buf); + const encoding = detectEncoding(buf); expect(encoding).to.equal('binary'); } for (const fname of sampleText) { const buf = await fs.readFile(fname); - const encoding = await detectEncoding(buf); + const encoding = detectEncoding(buf); expect(encoding).to.equal('utf-8'); } }); diff --git a/tests/utils/image-manager/image-manager.spec.ts b/tests/utils/image-manager/image-manager.spec.ts index cbc09a36..7d56640f 100644 --- a/tests/utils/image-manager/image-manager.spec.ts +++ b/tests/utils/image-manager/image-manager.spec.ts @@ -32,9 +32,7 @@ describe('image-manager', function () { fs.writeSync(this.image.fd, 'Cache image', 0, 'utf8'); this.cacheGetImagePathStub = stub(imageManager, 'getImagePath'); - return this.cacheGetImagePathStub.returns( - Promise.resolve(this.image.name), - ); + return this.cacheGetImagePathStub.resolves(this.image.name); }); afterEach(function () { @@ -45,7 +43,7 @@ describe('image-manager', function () { describe('given the image is fresh', function () { beforeEach(function () { this.cacheIsImageFresh = stub(imageManager, 'isImageFresh'); - return this.cacheIsImageFresh.returns(Promise.resolve(true)); + return this.cacheIsImageFresh.resolves(true); }); afterEach(function () { @@ -71,7 +69,7 @@ describe('image-manager', function () { describe('given the image is not fresh', function () { beforeEach(function () { this.cacheIsImageFresh = stub(imageManager, 'isImageFresh'); - return this.cacheIsImageFresh.returns(Promise.resolve(false)); + return this.cacheIsImageFresh.resolves(false); }); afterEach(function () { @@ -82,9 +80,7 @@ describe('image-manager', function () { describe.skip('given a valid download endpoint', function () { beforeEach(function () { this.osDownloadStub = stub(balena.models.os, 'download'); - this.osDownloadStub.returns( - Promise.resolve(stringToStream('Download image')), - ); + this.osDownloadStub.resolves(stringToStream('Download image')); }); afterEach(function () { @@ -131,7 +127,7 @@ describe('image-manager', function () { beforeEach(function () { this.osDownloadStream = new stream.PassThrough(); this.osDownloadStub = stub(balena.models.os, 'download'); - this.osDownloadStub.returns(Promise.resolve(this.osDownloadStream)); + this.osDownloadStub.resolves(this.osDownloadStream); }); afterEach(function () { @@ -182,7 +178,7 @@ describe('image-manager', function () { mime?: string; }; mockResultStream.mime = 'application/zip'; - this.osDownloadStub.returns(Promise.resolve(mockResultStream)); + this.osDownloadStub.resolves(mockResultStream); }); afterEach(function () { @@ -207,12 +203,10 @@ describe('image-manager', function () { this.balenaSettingsGetStub .withArgs('cacheDirectory') - .returns( - Promise.resolve( - os.platform() === 'win32' - ? 'C:\\Users\\johndoe\\_balena\\cache' - : '/Users/johndoe/.balena/cache', - ), + .resolves( + os.platform() === 'win32' + ? 'C:\\Users\\johndoe\\_balena\\cache' + : '/Users/johndoe/.balena/cache', ); }); @@ -226,21 +220,21 @@ describe('image-manager', function () { balena.models.config, 'getDeviceTypeManifestBySlug', ); - this.getDeviceTypeManifestBySlugStub.withArgs('raspberry-pi').returns( - Promise.resolve({ + this.getDeviceTypeManifestBySlugStub + .withArgs('raspberry-pi') + .resolves({ yocto: { fstype: 'resin-sdcard', }, - }), - ); + }); - this.getDeviceTypeManifestBySlugStub.withArgs('intel-edison').returns( - Promise.resolve({ + this.getDeviceTypeManifestBySlugStub + .withArgs('intel-edison') + .resolves({ yocto: { fstype: 'zip', }, - }), - ); + }); }); afterEach(function () { @@ -293,13 +287,11 @@ describe('image-manager', function () { balena.models.config, 'getDeviceTypeManifestBySlug', ); - this.getDeviceTypeManifestBySlugStub.returns( - Promise.resolve({ - yocto: { - fstype: 'balena-sdcard', - }, - }), - ); + this.getDeviceTypeManifestBySlugStub.resolves({ + yocto: { + fstype: 'balena-sdcard', + }, + }); }); afterEach(function () { @@ -312,8 +304,8 @@ describe('image-manager', function () { imageManager, 'getFileCreatedDate', ); - this.utilsGetFileCreatedDate.returns( - Promise.reject(new Error("ENOENT, stat 'raspberry-pi'")), + this.utilsGetFileCreatedDate.rejects( + new Error("ENOENT, stat 'raspberry-pi'"), ); }); @@ -333,8 +325,8 @@ describe('image-manager', function () { imageManager, 'getFileCreatedDate', ); - this.utilsGetFileCreatedDate.returns( - Promise.resolve(new Date('2014-01-01T00:00:00.000Z')), + this.utilsGetFileCreatedDate.resolves( + new Date('2014-01-01T00:00:00.000Z'), ); }); @@ -345,8 +337,8 @@ describe('image-manager', function () { describe('given the file was created before the os last modified time', function () { beforeEach(function () { this.osGetLastModified = stub(balena.models.os, 'getLastModified'); - this.osGetLastModified.returns( - Promise.resolve(new Date('2014-02-01T00:00:00.000Z')), + this.osGetLastModified.resolves( + new Date('2014-02-01T00:00:00.000Z'), ); }); @@ -363,8 +355,8 @@ describe('image-manager', function () { describe('given the file was created after the os last modified time', function () { beforeEach(function () { this.osGetLastModified = stub(balena.models.os, 'getLastModified'); - this.osGetLastModified.returns( - Promise.resolve(new Date('2013-01-01T00:00:00.000Z')), + this.osGetLastModified.resolves( + new Date('2013-01-01T00:00:00.000Z'), ); }); @@ -381,8 +373,8 @@ describe('image-manager', function () { describe('given the file was created just at the os last modified time', function () { beforeEach(function () { this.osGetLastModified = stub(balena.models.os, 'getLastModified'); - this.osGetLastModified.returns( - Promise.resolve(new Date('2014-00-01T00:00:00.000Z')), + this.osGetLastModified.resolves( + new Date('2014-00-01T00:00:00.000Z'), ); }); @@ -406,7 +398,7 @@ describe('image-manager', function () { fs.writeSync(this.image.fd, 'Lorem ipsum dolor sit amet', 0, 'utf8'); this.cacheGetImagePathStub = stub(imageManager, 'getImagePath'); - this.cacheGetImagePathStub.returns(Promise.resolve(this.image.name)); + this.cacheGetImagePathStub.resolves(this.image.name); }); afterEach(function (done) { @@ -443,7 +435,7 @@ describe('image-manager', function () { beforeEach(function () { this.image = tmp.fileSync(); this.cacheGetImagePathStub = stub(imageManager, 'getImagePath'); - this.cacheGetImagePathStub.returns(Promise.resolve(this.image.name)); + this.cacheGetImagePathStub.resolves(this.image.name); }); afterEach(function (done) { @@ -486,9 +478,7 @@ describe('image-manager', function () { beforeEach(function () { this.date = new Date(2014, 1, 1); this.fsStatStub = stub(fs.promises, 'stat'); - this.fsStatStub - .withArgs('foo') - .returns(Promise.resolve({ ctime: this.date })); + this.fsStatStub.withArgs('foo').resolves({ ctime: this.date }); }); afterEach(function () { @@ -506,7 +496,7 @@ describe('image-manager', function () { this.fsStatStub = stub(fs.promises, 'stat'); this.fsStatStub .withArgs('foo') - .returns(Promise.reject(new Error("ENOENT, stat 'foo'"))); + .rejects(new Error("ENOENT, stat 'foo'")); }); afterEach(function () { diff --git a/tests/utils/normalization.spec.ts b/tests/utils/normalization.spec.ts index e4979ef3..6cbf146a 100644 --- a/tests/utils/normalization.spec.ts +++ b/tests/utils/normalization.spec.ts @@ -117,7 +117,7 @@ describe('disambiguateReleaseParam() function', () => { it('should return id from SDK on first call, if match is found', async () => { const input = '1234'; const output = 1234; - const getRelease = sinon.stub().returns(Promise.resolve({ id: output })); + const getRelease = sinon.stub().resolves({ id: output }); const sdk: any = { models: { release: { @@ -139,9 +139,9 @@ describe('disambiguateReleaseParam() function', () => { const getRelease = sinon .stub() .onCall(0) - .returns(Promise.reject(new BalenaReleaseNotFound(input))) + .rejects(new BalenaReleaseNotFound(input)) .onCall(1) - .returns(Promise.resolve({ id: output })); + .resolves({ id: output }); const sdk: any = { models: { @@ -161,9 +161,7 @@ describe('disambiguateReleaseParam() function', () => { it('should throw error if no match found', async () => { const input = '1234'; - const getRelease = sinon - .stub() - .returns(Promise.reject(new BalenaReleaseNotFound(input))); + const getRelease = sinon.stub().rejects(new BalenaReleaseNotFound(input)); const sdk: any = { models: { @@ -185,9 +183,7 @@ describe('disambiguateReleaseParam() function', () => { it('should throw error if unknown error returned from SDK', async () => { const input = '1234'; - const getRelease = sinon - .stub() - .returns(Promise.reject(new Error('some error'))); + const getRelease = sinon.stub().rejects(new Error('some error')); const sdk: any = { models: { diff --git a/tests/utils/validation.spec.ts b/tests/utils/validation.spec.ts index 7f502f2d..0d77ff59 100644 --- a/tests/utils/validation.spec.ts +++ b/tests/utils/validation.spec.ts @@ -15,10 +15,14 @@ * limitations under the License. */ -import { expect } from 'chai'; +import * as chaiAsPromised from 'chai-as-promised'; +import * as chai from 'chai'; import { ExpectedError } from '../../build/errors'; import * as v from '../../build/utils/validation'; +chai.use(chaiAsPromised); +const { expect } = chai; + describe('validateEmail() function', () => { it('should reject invalid email addresses with a message', () => { const errorMessage = 'Email is not valid'; @@ -186,26 +190,26 @@ describe('validateUuid() function', () => { describe('parseAsInteger() function', () => { it('should reject non-numeric characters', () => { - expect(() => v.parseAsInteger('abc')).to.throw(ExpectedError); - expect(() => v.parseAsInteger('1a')).to.throw(ExpectedError); - expect(() => v.parseAsInteger('a1')).to.throw(ExpectedError); - expect(() => v.parseAsInteger('a')).to.throw(ExpectedError); - expect(() => v.parseAsInteger('1.0')).to.throw(ExpectedError); + expect(v.parseAsInteger('abc')).to.be.rejectedWith(ExpectedError); + expect(v.parseAsInteger('1a')).to.be.rejectedWith(ExpectedError); + expect(v.parseAsInteger('a1')).to.be.rejectedWith(ExpectedError); + expect(v.parseAsInteger('a')).to.be.rejectedWith(ExpectedError); + expect(v.parseAsInteger('1.0')).to.be.rejectedWith(ExpectedError); }); it('should reject leading zeros', () => { - expect(() => v.parseAsInteger('01')).to.throw(ExpectedError); - expect(() => v.parseAsInteger('001')).to.throw(ExpectedError); + expect(v.parseAsInteger('01')).to.be.rejectedWith(ExpectedError); + expect(v.parseAsInteger('001')).to.be.rejectedWith(ExpectedError); }); it('should throw with specific message when param name passed', () => { - expect(() => v.parseAsInteger('abc')).to.throw( + expect(v.parseAsInteger('abc')).to.be.rejectedWith( 'The parameter must be an integer.', ); }); it('should throw with general message when no param name passed', () => { - expect(() => v.parseAsInteger('abc', 'foo')).to.throw( + expect(v.parseAsInteger('abc', 'foo')).to.be.rejectedWith( "The parameter 'foo' must be an integer.", ); });