From 044ba258595c5ef491d0e016a52223dff04d2a2d Mon Sep 17 00:00:00 2001 From: "R. Tyler Croy" Date: Fri, 5 Oct 2018 19:21:31 -0700 Subject: [PATCH] Convert everything over to TypeScript This was mostly minor minor tweaking of imports and fiddling with a few types --- distribution/client/Makefile | 4 +- distribution/client/package-lock.json | 6 ++ distribution/client/package.json | 23 +++++-- .../client/src/{client.js => client.ts} | 49 +++++++------ .../src/lib/{checksum.js => checksum.ts} | 10 ++- .../src/lib/{downloader.js => downloader.ts} | 26 +++---- ...{error-telemetry.js => error-telemetry.ts} | 25 +++++-- .../{healthchecker.js => healthchecker.ts} | 19 ++++-- .../src/lib/{periodic.js => periodic.ts} | 18 ++--- .../src/lib/{rand-patch.js => rand-patch.ts} | 4 +- .../lib/{registration.js => registration.ts} | 68 ++++++++++++------- .../client/src/lib/request-options.ts | 6 ++ .../lib/{snapshotter.js => snapshotter.ts} | 12 ++-- .../client/src/lib/{status.js => status.ts} | 38 ++++++----- .../client/src/lib/{storage.js => storage.ts} | 19 +++--- .../lib/{supervisord.js => supervisord.ts} | 25 +++---- distribution/client/src/lib/{ui.js => ui.ts} | 10 ++- .../client/src/lib/{update.js => update.ts} | 56 ++++++++------- .../{checksum.test.js => checksum.test.ts} | 5 +- .../test/{client.test.js => client.test.ts} | 11 ++- ...{downloader.test.js => downloader.test.ts} | 8 ++- ...emetry.test.js => error-telemetry.test.ts} | 6 +- ...hchecker.test.js => healthchecker.test.ts} | 15 ++-- distribution/client/test/periodic.test.js | 33 --------- distribution/client/test/periodic.test.ts | 29 ++++++++ ...istration.test.js => registration.test.ts} | 34 +++++----- ...napshotter.test.js => snapshotter.test.ts} | 8 +-- .../test/{status.test.js => status.test.ts} | 7 +- .../test/{storage.test.js => storage.test.ts} | 5 +- .../client/test/{ui.test.js => ui.test.ts} | 3 +- .../test/{update.test.js => update.test.ts} | 20 +++--- .../{test/helpers.js => testlib/helpers.ts} | 4 +- distribution/client/tsconfig.json | 2 +- node.mk | 4 +- 34 files changed, 356 insertions(+), 256 deletions(-) rename distribution/client/src/{client.js => client.ts} (84%) rename distribution/client/src/lib/{checksum.js => checksum.ts} (80%) rename distribution/client/src/lib/{downloader.js => downloader.ts} (89%) rename distribution/client/src/lib/{error-telemetry.js => error-telemetry.ts} (85%) rename distribution/client/src/lib/{healthchecker.js => healthchecker.ts} (89%) rename distribution/client/src/lib/{periodic.js => periodic.ts} (79%) rename distribution/client/src/lib/{rand-patch.js => rand-patch.ts} (81%) rename distribution/client/src/lib/{registration.js => registration.ts} (82%) create mode 100644 distribution/client/src/lib/request-options.ts rename distribution/client/src/lib/{snapshotter.js => snapshotter.ts} (95%) rename distribution/client/src/lib/{status.js => status.ts} (86%) rename distribution/client/src/lib/{storage.js => storage.ts} (86%) rename distribution/client/src/lib/{supervisord.js => supervisord.ts} (84%) rename distribution/client/src/lib/{ui.js => ui.ts} (91%) rename distribution/client/src/lib/{update.js => update.ts} (88%) rename distribution/client/test/{checksum.test.js => checksum.test.ts} (88%) rename distribution/client/test/{client.test.js => client.test.ts} (88%) rename distribution/client/test/{downloader.test.js => downloader.test.ts} (93%) rename distribution/client/test/{error-telemetry.test.js => error-telemetry.test.ts} (88%) rename distribution/client/test/{healthchecker.test.js => healthchecker.test.ts} (95%) delete mode 100644 distribution/client/test/periodic.test.js create mode 100644 distribution/client/test/periodic.test.ts rename distribution/client/test/{registration.test.js => registration.test.ts} (84%) rename distribution/client/test/{snapshotter.test.js => snapshotter.test.ts} (91%) rename distribution/client/test/{status.test.js => status.test.ts} (93%) rename distribution/client/test/{storage.test.js => storage.test.ts} (95%) rename distribution/client/test/{ui.test.js => ui.test.ts} (74%) rename distribution/client/test/{update.test.js => update.test.ts} (92%) rename distribution/client/{test/helpers.js => testlib/helpers.ts} (89%) diff --git a/distribution/client/Makefile b/distribution/client/Makefile index b3b0ba2..8b60b05 100644 --- a/distribution/client/Makefile +++ b/distribution/client/Makefile @@ -8,6 +8,8 @@ lint:: compile check:: compile +unit:: compile + compile: tsc @@ -27,6 +29,6 @@ run: depends build EVERGREEN_DISABLE_SNAPSHOT=true \ EVERGREEN_ENDPOINT=http://127.0.0.1:3030 \ FLAVOR=docker-cloud \ - npm run client + npm run start .PHONY: run build docs compile diff --git a/distribution/client/package-lock.json b/distribution/client/package-lock.json index ae283fb..23e60e0 100644 --- a/distribution/client/package-lock.json +++ b/distribution/client/package-lock.json @@ -173,6 +173,12 @@ "integrity": "sha512-ojnbBiKkZFYRfQpmtnnWTMw+rzGp/JiystjluW9jgN3VzRwilXddJ6aGQ9V/7iuDG06SBgn7ozW9k3zcAnYjYQ==", "dev": true }, + "@types/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/@types/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha1-EHPEvIJHVK49EM+riKsCN7qWTk0=", + "dev": true + }, "@webassemblyjs/ast": { "version": "1.5.13", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.5.13.tgz", diff --git a/distribution/client/package.json b/distribution/client/package.json index 8d08a34..6bcb46d 100644 --- a/distribution/client/package.json +++ b/distribution/client/package.json @@ -4,10 +4,11 @@ "description": "", "main": "src/client.js", "scripts": { - "client": "node src/client.js", - "test": "npm run eslint && npm run jest", - "eslint": "eslint src/. test/. --config .eslintrc.json", - "jest": "jest", + "prestart": "tsc", + "start": "node build/client.js", + "pretest": "eslint src/. test/. --config .eslintrc.json", + "eslint": "npm run pretest", + "test": "jest", "postinstall": "patch-package" }, "author": "R Tyler Croy", @@ -15,6 +16,8 @@ "devDependencies": { "@types/feathersjs__feathers": "^3.0.5", "@types/jest": "^23.3.3", + "@types/node": "^10.11.4", + "@types/tmp": "0.0.33", "asciidoctor.js": "^1.5.7-rc.1", "css-loader": "^1.0.0", "eslint": "^4.19.1", @@ -60,11 +63,23 @@ "/ui/index.js", "/src/lib/ui.js" ], + "transform": { + "^.+\\.tsx?$": "ts-jest" + }, + "testRegex": "(/test/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$", "coverageReporters": [ "json", "lcov", "text-summary" ], + "moduleFileExtensions": [ + "ts", + "tsx", + "js", + "jsx", + "json", + "node" + ], "coverageThreshold": { "global": { "statements": 54, diff --git a/distribution/client/src/client.js b/distribution/client/src/client.ts similarity index 84% rename from distribution/client/src/client.js rename to distribution/client/src/client.ts index 3a4a864..de0d301 100644 --- a/distribution/client/src/client.js +++ b/distribution/client/src/client.ts @@ -2,28 +2,37 @@ * This is the main entrypoint for the evergreen-client */ -const process = require('process'); +import feathers from '@feathersjs/feathers'; +import * as logger from 'winston'; +import socketio from '@feathersjs/socketio-client'; +import auth from '@feathersjs/authentication-client'; +import io from 'socket.io-client'; -const feathers = require('@feathersjs/feathers'); -const logger = require('winston'); -const socketio = require('@feathersjs/socketio-client'); -const auth = require('@feathersjs/authentication-client'); -const io = require('socket.io-client'); - -const createCron = require('./lib/periodic'); -const ErrorTelemetry = require('./lib/error-telemetry'); -const HealthChecker = require('./lib/healthchecker'); -const Registration = require('./lib/registration'); -const Status = require('./lib/status'); -const Storage = require('./lib/storage'); -const UI = require('./lib/ui'); -const Update = require('./lib/update'); +import ErrorTelemetry from './lib/error-telemetry'; +import HealthChecker from './lib/healthchecker'; +import Registration from './lib/registration'; +import Status from './lib/status'; +import Storage from './lib/storage'; +import UI from './lib/ui' +import Update from './lib/update'; +import Periodic from './lib/periodic'; /* * The Client class is a simple wrapper meant to start the basics of the client * and then run a simple runloop to block the client from ever exiting */ -class Client { +export default class Client { + protected readonly app : any; + protected readonly reg : Registration; + protected readonly healthChecker : HealthChecker; + protected readonly update : Update; + protected readonly status : Status; + protected readonly errorTelemetry : ErrorTelemetry; + + protected socket : any; + + public updating : boolean; + constructor() { if (!process.env.FLAVOR) { logger.error('Fatal error encountered while trying to start, no flavor set, exiting the client'); @@ -79,7 +88,7 @@ class Client { * Only setting on the cron once we have registered and logged in, * otherwise it's not really useful to have anything running periodically */ - const cron = createCron(app); + const cron = new Periodic(); this.runUpdates(); @@ -151,7 +160,7 @@ class Client { this.runUpdates(); }); - this.reg.register().then((res, newRegistration) => { + this.reg.register().then(({res, newRegistration}) => { UI.publish('Registered this Evergreen instance', { log: 'debug', error: res} ); this.status.authenticate(this.reg.uuid, this.reg.token); this.update.authenticate(this.reg.uuid, this.reg.token); @@ -168,8 +177,6 @@ class Client { } } -module.exports = Client; - if (require.main === module) { Storage.setBootingFlag(); UI.serve(); @@ -180,6 +187,6 @@ if (require.main === module) { logger.level = process.env.LOG_LEVEL || 'warn'; /* Main entrypoint for module */ UI.publish('Starting the evergreen-client..', { log: 'info' }); - let client = new Client(); + const client = new Client(); client.bootstrap(); } diff --git a/distribution/client/src/lib/checksum.js b/distribution/client/src/lib/checksum.ts similarity index 80% rename from distribution/client/src/lib/checksum.js rename to distribution/client/src/lib/checksum.ts index 2feef35..f94254a 100644 --- a/distribution/client/src/lib/checksum.js +++ b/distribution/client/src/lib/checksum.ts @@ -1,10 +1,10 @@ 'use strict'; -const crypto = require('crypto'); -const fs = require('fs'); -const logger = require('winston'); +import crypto from 'crypto'; +import fs from 'fs'; +import * as logger from 'winston'; -class Checksum { +export default class Checksum { /* * Generate a SHA-256 checksum signature from the provided relative or * absolute file path @@ -26,5 +26,3 @@ class Checksum { } } } - -module.exports = Checksum; diff --git a/distribution/client/src/lib/downloader.js b/distribution/client/src/lib/downloader.ts similarity index 89% rename from distribution/client/src/lib/downloader.js rename to distribution/client/src/lib/downloader.ts index 1a27a22..1213aac 100644 --- a/distribution/client/src/lib/downloader.js +++ b/distribution/client/src/lib/downloader.ts @@ -3,18 +3,19 @@ * disk and checking them against provided checksums. */ -const fs = require('fs'); -const path = require('path'); -const url = require('url'); +import fs from 'fs'; +import path from 'path'; +import url from 'url'; -const rp = require('promise-request-retry'); -const logger = require('winston'); -const mkdirp = require('mkdirp'); +import rp from 'promise-request-retry'; +import * as logger from 'winston'; +import mkdirp from 'mkdirp'; -const Checksum = require('./checksum'); -const UI = require('./ui'); +import UI from './ui'; +import Checksum from './checksum'; +import { RequestOptions } from './request-options'; -class Downloader { +export default class Downloader { constructor() { } @@ -40,7 +41,10 @@ class Downloader { * @param {string} the filename to output at * @parma {string} Optional sha256 signature to verify of the file */ - static download(item, dir, fileNameToWrite, sha256, downloadOptions = {}) { + static download(item, dir, + fileNameToWrite?: string, + sha256?: string, + downloadOptions: RequestOptions = {}) { const itemUrl = url.parse(item); const itemUrlBaseName = path.basename(itemUrl.pathname); @@ -113,5 +117,3 @@ class Downloader { }); } } - -module.exports = Downloader; diff --git a/distribution/client/src/lib/error-telemetry.js b/distribution/client/src/lib/error-telemetry.ts similarity index 85% rename from distribution/client/src/lib/error-telemetry.js rename to distribution/client/src/lib/error-telemetry.ts index f263d15..76ecfc9 100644 --- a/distribution/client/src/lib/error-telemetry.js +++ b/distribution/client/src/lib/error-telemetry.ts @@ -5,13 +5,24 @@ * handle both error and "metrics" telemetry, but let's start with a smaller * scope at least for now. */ -const { Tail } = require('tail'); -const fs = require('fs'); -const logger = require('winston'); -const path = require('path'); -const Storage = require('./storage'); +import { Tail } from 'tail'; +import fs from 'fs'; +import * as logger from 'winston' +import path from 'path'; + +import Storage from './storage'; + +export interface ErrorTelemetryOptions { + flavor?: string, +}; + +export default class ErrorTelemetry { + protected readonly app : any; + protected readonly options : ErrorTelemetryOptions; + + public uuid : string; + public token : string; -class ErrorTelemetry { constructor(app, options) { this.app = app; this.options = options; @@ -45,7 +56,7 @@ class ErrorTelemetry { * monitoredFile: path to the log file to watch * outputFunction(app,line): the function that will be called on each new line detected */ - setup(monitoredFile) { + setup(monitoredFile?: string) { logger.info('Setting up error logging...'); let loggingFile = monitoredFile || this.fileToWatch(); diff --git a/distribution/client/src/lib/healthchecker.js b/distribution/client/src/lib/healthchecker.ts similarity index 89% rename from distribution/client/src/lib/healthchecker.js rename to distribution/client/src/lib/healthchecker.ts index 60a829c..0b07486 100644 --- a/distribution/client/src/lib/healthchecker.js +++ b/distribution/client/src/lib/healthchecker.ts @@ -1,12 +1,21 @@ -const logger = require('winston'); -const rp = require('promise-request-retry'); + +import * as logger from 'winston' +import rp from 'promise-request-retry'; + +import { RequestOptions } from './request-options'; const INSTANCE_IDENTITY_URL = '/instance-identity/'; const METRICS_URL = '/metrics/evergreen/healthcheck'; -class HealthChecker { +export default class HealthChecker { + protected readonly defaultRequestOptions : any; - constructor(jenkinsRootUrl, requestOptions = {}) { + public readonly jenkinsRootUrl : string; + public readonly retry : number; + public readonly delay : number; + public readonly factor : number; + + constructor(jenkinsRootUrl, requestOptions: RequestOptions = {}) { this.jenkinsRootUrl = jenkinsRootUrl; // let's target ~3 to 5 minutes overall of attempts for updates to arrive + Jenkins to start // TODO: later, introduce some smarter delay depending on the number of things to download? @@ -111,5 +120,3 @@ class HealthChecker { }); } } - -module.exports = HealthChecker; diff --git a/distribution/client/src/lib/periodic.js b/distribution/client/src/lib/periodic.ts similarity index 79% rename from distribution/client/src/lib/periodic.js rename to distribution/client/src/lib/periodic.ts index b8b546d..442d000 100644 --- a/distribution/client/src/lib/periodic.js +++ b/distribution/client/src/lib/periodic.ts @@ -4,16 +4,17 @@ * */ -const logger = require('winston'); -const cron = require('cron'); +import * as logger from 'winston' +import cron from 'cron'; + +export default class Periodic { + protected readonly jobs : any; + protected readonly offset : number; -class Periodic { /* * Requires the feathersjs app instance on initialization */ - constructor (app, options) { - this.app = app; - this.options = options || {}; + constructor() { this.jobs = {}; this.offset = this.computeOffset(); logger.info('Periodic using minute offset of', this.offset); @@ -48,8 +49,3 @@ class Periodic { return Math.floor(Math.random() * 59); } } - -module.exports = function(app, options) { - return new Periodic(app, options); -}; -module.exports.Periodic = Periodic; diff --git a/distribution/client/src/lib/rand-patch.js b/distribution/client/src/lib/rand-patch.ts similarity index 81% rename from distribution/client/src/lib/rand-patch.js rename to distribution/client/src/lib/rand-patch.ts index ea871e2..1b6064e 100644 --- a/distribution/client/src/lib/rand-patch.js +++ b/distribution/client/src/lib/rand-patch.ts @@ -6,8 +6,8 @@ * It seems to not believe that we're in nodejs when we really are */ -const crypto = require('crypto'); -const rand = require('brorand'); +import crypto from 'crypto'; +import rand from 'brorand'; rand.Rand.prototype._rand = function _rand(n) { return crypto.randomBytes(n); diff --git a/distribution/client/src/lib/registration.js b/distribution/client/src/lib/registration.ts similarity index 82% rename from distribution/client/src/lib/registration.js rename to distribution/client/src/lib/registration.ts index f6a0c96..be47f2a 100644 --- a/distribution/client/src/lib/registration.js +++ b/distribution/client/src/lib/registration.ts @@ -3,20 +3,35 @@ * of the evergreen-client with the backend services layer */ -const ecc = require('elliptic'); -const fs = require('fs'); -const logger = require('winston'); -const path = require('path'); -const mkdirp = require('mkdirp'); +import ecc from 'elliptic'; +import * as logger from 'winston'; +import path from 'path'; +import mkdirp from 'mkdirp' +import fs from 'fs'; -const storage = require('./storage'); +import Storage from './storage'; require('./rand-patch'); -class Registration { - constructor (app, options) { +export interface FileOptions { + encoding?: string, + flag?: string, +}; + +export default class Registration { + protected readonly app : any; + protected readonly options : Map; + protected readonly curve : string; + + protected privateKey : string; + protected publicKey : string; + protected fileOptions : FileOptions; + + public uuid : string; + public token : string; + + constructor(app) { this.app = app; - this.options = options || {}; this.uuid = null; this.publicKey = null; this.privateKey = null; @@ -46,15 +61,19 @@ class Registration { * @return Promise */ async register() { - let self = this; + const self = this; return new Promise((resolve, reject) => { - let api = self.app.service('registration'); + const api = self.app.service('registration'); logger.info('Checking registration status..'); if (self.hasKeys() && self.hasUUID()) { logger.info('We have keys and a UUID already'); self.loadKeysSync(); self.loadUUIDSync(); - return self.login().then(res => resolve(res, false)); + return self.login().then(res => resolve( + { + result: res, + created: false, + })); } else { if (!self.generateKeys()) { return reject('Failed to generate keys'); @@ -72,7 +91,10 @@ class Registration { if (!self.saveUUIDSync()) { reject('Failed to save UUID!'); } else { - return self.login().then(res => resolve(res, true)); + return self.login().then(res => resolve({ + result: res, + created: true, + })); } }).catch((res) => { logger.error('Failed to register:', res); @@ -108,8 +130,8 @@ class Registration { * @return Boolean */ generateKeys() { - let ec = new ecc.ec(this.curve); - let privkey = ec.genKeyPair(); + const ec = new ecc.ec(this.curve); + const privkey = ec.genKeyPair(); this.publicKey = privkey.getPublic('hex'); this.privateKey = privkey.getPrivate('hex'); @@ -126,7 +148,7 @@ class Registration { * * Will return null if no public key has yet been generated * - * @return String + * @return string */ getPublicKey() { return this.publicKey; @@ -154,7 +176,7 @@ class Registration { } loadUUIDSync() { - let config = JSON.parse(fs.readFileSync(this.uuidPath(), this.fileOptions)); + const config = JSON.parse(fs.readFileSync(this.uuidPath(), this.fileOptions) as string); this.uuid = config.uuid; return (!!this.uuid); } @@ -215,8 +237,8 @@ class Registration { if (!this.hasKeys()) { return false; } - this.publicKey = fs.readFileSync(this.publicKeyPath(), this.fileOptions); - this.privateKey = fs.readFileSync(this.privateKeyPath(), this.fileOptions); + this.publicKey = fs.readFileSync(this.publicKeyPath(), this.fileOptions) as string; + this.privateKey = fs.readFileSync(this.privateKeyPath(), this.fileOptions) as string; return true; } @@ -240,10 +262,10 @@ class Registration { /* Return the directory where registration keys should be stored * - * @return String + * @return string */ keyPath() { - const keys = path.join(storage.homeDirectory(), 'keys'); + const keys = path.join(Storage.homeDirectory(), 'keys'); /* Only bother making the directory if it doesn't already exist */ try { @@ -263,7 +285,7 @@ class Registration { * * This public key is safe to be shared with external services * - * @return String + * @return string */ publicKeyPath() { return path.join(this.keyPath(), 'evergreen.pub'); @@ -277,5 +299,3 @@ class Registration { return path.join(this.keyPath(), 'uuid.json'); } } - -module.exports = Registration; diff --git a/distribution/client/src/lib/request-options.ts b/distribution/client/src/lib/request-options.ts new file mode 100644 index 0000000..6c688d3 --- /dev/null +++ b/distribution/client/src/lib/request-options.ts @@ -0,0 +1,6 @@ + +export interface RequestOptions { + retry?: number, + delay?: number, + factor?: number, +}; diff --git a/distribution/client/src/lib/snapshotter.js b/distribution/client/src/lib/snapshotter.ts similarity index 95% rename from distribution/client/src/lib/snapshotter.js rename to distribution/client/src/lib/snapshotter.ts index 9694aec..b995d83 100644 --- a/distribution/client/src/lib/snapshotter.js +++ b/distribution/client/src/lib/snapshotter.ts @@ -4,9 +4,9 @@ * https://github.com/jenkinsci/jep/tree/master/jep/302 */ -const { spawnSync } = require('child_process'); -const logger = require('winston'); -const fs = require('fs'); +import { spawnSync } from 'child_process'; +import * as logger from 'winston'; +import fs from 'fs'; const LOG_PREFIX = '[snapshotting]'; // https://github.com/jenkinsci/jep/tree/master/jep/302#user-content-files-to-store @@ -16,10 +16,10 @@ const GITIGNORE_CONTENT = ` /secrets/master.key `; -class Snapshotter { +export default class Snapshotter { + protected workingDirectory : string; - constructor(app, options) { - this.options = options || {}; + constructor() { } /** diff --git a/distribution/client/src/lib/status.js b/distribution/client/src/lib/status.ts similarity index 86% rename from distribution/client/src/lib/status.js rename to distribution/client/src/lib/status.ts index 22cd389..2eebf5a 100644 --- a/distribution/client/src/lib/status.js +++ b/distribution/client/src/lib/status.ts @@ -1,20 +1,30 @@ 'use strict'; -const fs = require('fs'); -const path = require('path'); +import path from 'path'; +import fs from 'fs'; -const logger = require('winston'); -const Storage = require('./storage'); -const Checksum = require('./checksum'); +import * as logger from 'winston'; +import Storage from './storage'; +import Checksum from './checksum'; +export interface StatusOptions { + flavor?: string, +}; + /* * The status module is responsible for collecting and reporting the current * state of this instance to the Evergreen backend `Status` service */ -class Status { - constructor(app, options) { - this.options = options || {}; +export default class Status { + protected readonly app : any; + protected readonly options : StatusOptions; + + public uuid : string; + public token : string; + + constructor(app : any, options : StatusOptions = {}) { + this.options = options; this.token = null; this.uuid = null; this.app = app; @@ -38,8 +48,8 @@ class Status { * Create a status record in the backend for this particular instance */ async create() { - let api = this.app.service('status'); - let record = { + const api = this.app.service('status'); + const record = { uuid: this.uuid, flavor: this.options.flavor, timezone: this.getTimezone(), @@ -68,8 +78,8 @@ class Status { } reportLevel(updateLevel) { - let api = this.app.service('status'); - let record = { + const api = this.app.service('status'); + const record = { uuid: this.uuid, updateId: updateLevel, }; @@ -152,10 +162,6 @@ class Status { throw err; } } - return versions; } - } - -module.exports = Status; diff --git a/distribution/client/src/lib/storage.js b/distribution/client/src/lib/storage.ts similarity index 86% rename from distribution/client/src/lib/storage.js rename to distribution/client/src/lib/storage.ts index 7245a58..f312b80 100644 --- a/distribution/client/src/lib/storage.js +++ b/distribution/client/src/lib/storage.ts @@ -1,15 +1,16 @@ 'use strict'; -const path = require('path'); -const fs = require('fs'); -const logger = require('winston'); -const UI = require('./ui'); +import fs from 'fs'; +import path from 'path'; + +import * as logger from 'winston'; +import UI from './ui'; /* * The Storage module simply contains common functions necessary for the * evergreen-client to store its own data. */ -class Storage { +export default class Storage { /* * Returns the default home directory or the value of EVERGREEN_HOME * @@ -69,12 +70,12 @@ class Storage { } } - static removePlugins(plugins) { + static removePlugins(plugins?: Array) { if (!plugins) { return; } - let pluginPath = this.pluginsDirectory(); - let retArray = []; + const pluginPath = this.pluginsDirectory(); + const retArray = []; plugins.forEach((plugin) => { retArray.push(fs.unlink(`${pluginPath}/${plugin}.hpi`, () => { logger.info(`${pluginPath}/${plugin}.hpi was deleted`); @@ -84,5 +85,3 @@ class Storage { return retArray; } } - -module.exports = Storage; diff --git a/distribution/client/src/lib/supervisord.js b/distribution/client/src/lib/supervisord.ts similarity index 84% rename from distribution/client/src/lib/supervisord.js rename to distribution/client/src/lib/supervisord.ts index 4a334a2..9a49cd0 100644 --- a/distribution/client/src/lib/supervisord.js +++ b/distribution/client/src/lib/supervisord.ts @@ -3,15 +3,18 @@ * XML-RPC API: http://supervisord.org/api.html */ -const xmlrpc = require('xmlrpc'); -const client = xmlrpc.createClient('http://localhost:9001/RPC2'); -const logger = require('winston'); +import xmlrpc from 'xmlrpc'; +import * as logger from 'winston' + +const client = xmlrpc.createClient('http://localhost:9001/RPC2'); + +export default class Supervisord { + protected readonly client : xmlrpc.Client; -class Supervisord { constructor() { } - isRunning() { + static isRunning() { return new Promise((resolve, reject) => { client.methodCall('supervisor.getState', null, (e, v) => { if (e) { @@ -22,7 +25,7 @@ class Supervisord { }); } - printState(name) { + static printState(name) { return new Promise((resolve, reject) => { client.methodCall('supervisor.getProcessInfo', [name], (e, value) => { if (e) { @@ -33,7 +36,7 @@ class Supervisord { }); } - isProcessRunning(name) { + static isProcessRunning(name) { return new Promise((resolve, reject) => { client.methodCall('supervisor.getProcessInfo', [name], (e, value) => { if (e) { @@ -44,7 +47,7 @@ class Supervisord { }); } - startProcess(name) { + static startProcess(name) { logger.info(`[supervisord] Starting ${name} process`); return new Promise((resolve, reject) => { client.methodCall('supervisor.startProcess', [name], (e, value) => { @@ -56,7 +59,7 @@ class Supervisord { }); } - stopProcess(name) { + static stopProcess(name) { logger.info(`[supervisord] Stopping ${name} process`); return new Promise((resolve, reject) => { client.methodCall('supervisor.stopProcess', [name], (e, value) => { @@ -68,7 +71,7 @@ class Supervisord { }); } - async restartProcess(name) { + static async restartProcess(name) { logger.info(`[supervisord] Restarting ${name} process`); if (await this.isProcessRunning(name)) { await this.stopProcess(name); @@ -76,5 +79,3 @@ class Supervisord { return this.startProcess(name); } } - -module.exports = new Supervisord(); diff --git a/distribution/client/src/lib/ui.js b/distribution/client/src/lib/ui.ts similarity index 91% rename from distribution/client/src/lib/ui.js rename to distribution/client/src/lib/ui.ts index 5b85713..95227f8 100644 --- a/distribution/client/src/lib/ui.js +++ b/distribution/client/src/lib/ui.ts @@ -14,6 +14,9 @@ const logger = require('winston'); * Simple shim feathers service just to enable events */ class MessageService { + protected readonly app : any; + protected recent : Array; + constructor(app) { this.app = app; this.recent = []; @@ -37,6 +40,9 @@ class MessageService { } class UI { + protected readonly app : any; + protected server : any; + constructor() { const app = express(feathers()); this.app = app; @@ -60,7 +66,7 @@ class UI { * necessarily be presented to the user. * */ - publish(message, params) { + publish(message, params?: any) { return this.app.service('messages').create({ message: message, timestamp: Date.now(), @@ -75,4 +81,4 @@ class UI { } } -module.exports = new UI(); +export default new UI(); diff --git a/distribution/client/src/lib/update.js b/distribution/client/src/lib/update.ts similarity index 88% rename from distribution/client/src/lib/update.js rename to distribution/client/src/lib/update.ts index 941fc26..b86c722 100644 --- a/distribution/client/src/lib/update.js +++ b/distribution/client/src/lib/update.ts @@ -4,26 +4,38 @@ * https://github.com/jenkinsci/jep/tree/master/jep/307 */ -const fs = require('fs'); -const path = require('path'); -const mkdirp = require('mkdirp'); -const logger = require('winston'); +import fs from 'fs'; +import path from 'path'; +import mkdirp from 'mkdirp'; +import * as logger from 'winston'; -const Downloader = require('./downloader'); -const HealthChecker = require('./healthchecker'); -const Storage = require('./storage'); -const Supervisord = require('./supervisord'); -const UI = require('./ui'); -const Snapshotter = require('./snapshotter'); +import Downloader from './downloader'; +import HealthChecker from './healthchecker'; +import Storage from './storage'; +import Supervisord from './supervisord'; +import UI from './ui'; +import Snapshotter from './snapshotter'; -class Update { - constructor(app, options) { - this.options = options || {}; +export interface FileOptions { + encoding?: string, + flag?: string, +}; + +export default class Update { + protected readonly app : any; + protected readonly snapshotter : Snapshotter; + protected readonly fileOptions : FileOptions; + protected readonly options : any; + protected readonly healthChecker : HealthChecker; + + public uuid : string; + public token : string; + public manifest : any; + public updateInProgress : Date; + + constructor(app, options = {}) { this.app = app; - this.token = null; - this.uuid = null; - this.manifest = null; - this.updateInProgress = null; + this.options = options; this.fileOptions = { encoding: 'utf8' }; this.snapshotter = new Snapshotter(); this.snapshotter.init(Storage.jenkinsHome()); @@ -84,7 +96,7 @@ class Update { UI.publish('Starting to apply updates'); // Setting this to a timestamp to make a timeout in the future this.updateInProgress = new Date(); - let tasks = []; + const tasks = []; if ((updates.core) && (updates.core.url)) { tasks.push(Downloader.download(updates.core.url, @@ -150,7 +162,7 @@ class Update { while it's not been yet marked as tainted in the backend? * how to report that borked case in a clear way */ - restartJenkins(rollingBack) { // Add param to stop recursion? + restartJenkins(rollingBack?: boolean) { // Add param to stop recursion? Supervisord.restartProcess('jenkins'); const messageWhileRestarting = 'Jenkins should now be online, health checking!'; @@ -207,7 +219,7 @@ class Update { getCurrentLevel() { this.loadUpdateSync(); if (this.manifest) { - let level = this.manifest.meta.level; + const level = this.manifest.meta.level; logger.silly('Currently at Update Level %d', level); return level; } @@ -235,7 +247,7 @@ class Update { } } this.manifest = JSON.parse(fs.readFileSync(this.updatePath(), - this.fileOptions)); + this.fileOptions) as string); return this.manifest; } @@ -260,5 +272,3 @@ class Update { return dir; } } - -module.exports = Update; diff --git a/distribution/client/test/checksum.test.js b/distribution/client/test/checksum.test.ts similarity index 88% rename from distribution/client/test/checksum.test.js rename to distribution/client/test/checksum.test.ts index 9ad81f7..3f906d5 100644 --- a/distribution/client/test/checksum.test.js +++ b/distribution/client/test/checksum.test.ts @@ -2,8 +2,9 @@ jest.mock('fs'); -const fs = require('fs'); -const Checksum = require('../src/lib/checksum'); +const fs = require('fs'); + +import Checksum from '../src/lib/checksum'; describe('Checksum', () => { beforeEach(() => { diff --git a/distribution/client/test/client.test.js b/distribution/client/test/client.test.ts similarity index 88% rename from distribution/client/test/client.test.js rename to distribution/client/test/client.test.ts index 623799e..6413445 100644 --- a/distribution/client/test/client.test.js +++ b/distribution/client/test/client.test.ts @@ -1,13 +1,12 @@ -const assert = require('assert'); -const tmp = require('tmp'); -const Client = require('../src/client'); -const Storage = require('../src/lib/storage'); const mkdirp = require('mkdirp'); -describe('The base client module', () => { +import tmp from 'tmp'; +import Client from '../src/client'; +import Storage from '../src/lib/storage'; +describe('The base client module', () => { it('should interpret properly', () => { - assert(Client); + expect(Client).toBeTruthy(); }); describe('flavorCheck', () => { diff --git a/distribution/client/test/downloader.test.js b/distribution/client/test/downloader.test.ts similarity index 93% rename from distribution/client/test/downloader.test.js rename to distribution/client/test/downloader.test.ts index d6f2857..53b4c04 100644 --- a/distribution/client/test/downloader.test.js +++ b/distribution/client/test/downloader.test.ts @@ -2,8 +2,9 @@ jest.mock('fs'); const fs = require('fs'); const mkdirp = require('mkdirp'); -const Downloader = require('../src/lib/downloader'); -const Checksum = require('../src/lib/checksum'); + +import Downloader from '../src/lib/downloader'; +import Checksum from '../src/lib/checksum'; describe('the Downloader class', () => { describe('download()', () => { @@ -63,8 +64,9 @@ describe('the Downloader class', () => { await Downloader.download(toDownload, dir, 'thefile', null, {delay: 20, retry: 4, factor: 10}); expect(false).toBeTruthy(); // fail(), should not reach this line. } catch (e) { + const endTime = new Date(); // 4 attempts, no delay for the first, then 20 ms, 20*10 (exponential factor), 20*10*10 - expect(new Date() - startTime).toBeGreaterThan(0 + 20 + 200 + 2000); + expect((endTime as any) - (startTime as any)).toBeGreaterThan(0 + 20 + 200 + 2000); } }); }); diff --git a/distribution/client/test/error-telemetry.test.js b/distribution/client/test/error-telemetry.test.ts similarity index 88% rename from distribution/client/test/error-telemetry.test.js rename to distribution/client/test/error-telemetry.test.ts index a53cafc..70f6b3a 100644 --- a/distribution/client/test/error-telemetry.test.js +++ b/distribution/client/test/error-telemetry.test.ts @@ -5,7 +5,7 @@ const fs = require('fs'); const path = require('path'); const mkdirp = require('mkdirp'); -const ErrorTelemetry = require('../src/lib/error-telemetry'); +import ErrorTelemetry from '../src/lib/error-telemetry'; describe('Error Telemetry Logging', () => { beforeEach(() => { @@ -15,13 +15,13 @@ describe('Error Telemetry Logging', () => { describe('authenticate()', () => { it('should store values', () => { - const telemetry = new ErrorTelemetry().authenticate('you-you-i-Dee', 'toe-ken-that-guy'); + const telemetry = new ErrorTelemetry(null, null).authenticate('you-you-i-Dee', 'toe-ken-that-guy'); assert.equal(telemetry.uuid, 'you-you-i-Dee'); }); }); describe('setup() call', () => { - const errorTelemetryService = new ErrorTelemetry(); + const errorTelemetryService = new ErrorTelemetry(null, null); let logsDir = '/evergreen/jenkins/war/logs'; let logFile = path.join(logsDir, 'evergreen.log.0'); diff --git a/distribution/client/test/healthchecker.test.js b/distribution/client/test/healthchecker.test.ts similarity index 95% rename from distribution/client/test/healthchecker.test.js rename to distribution/client/test/healthchecker.test.ts index 111b322..951fb4f 100644 --- a/distribution/client/test/healthchecker.test.js +++ b/distribution/client/test/healthchecker.test.ts @@ -1,7 +1,8 @@ -const HealthChecker = require('../src/lib/healthchecker'); const logger = require('winston'); const http = require('http'); +import HealthChecker from '../src/lib/healthchecker'; + describe('The healthchecker module', () => { let server = null; let port = -1; @@ -13,17 +14,19 @@ describe('The healthchecker module', () => { instanceIdentity: true, metrics: { plugins: true, - deadlock: true - } + deadlock: true, + body: null, + }, }; describe('constructor', () => { it('should use default values if none passed in', () => { - const healthChecker = new HealthChecker(); + const healthChecker = new HealthChecker('http://example.com'); expect(healthChecker.retry).toEqual(25); expect(healthChecker.delay).toEqual(3000); expect(healthChecker.factor).toEqual(1.10); }); + it('should use passed in values', () => { const jenkinsRootUrl = `http://localhost:${port}`; const requestOptions = {delay: 100, retry: 1, factor: 1.01}; @@ -35,7 +38,7 @@ describe('The healthchecker module', () => { }); it('should override the delay if env var set', () => { const retryOverride = 21; - process.env.PROCESS_RETRY_OVERRIDE = retryOverride; + process.env.PROCESS_RETRY_OVERRIDE = retryOverride.toString(); const jenkinsRootUrl = `http://localhost:${port}`; const requestOptions = {delay: 100, retry: 1, factor: 1.01}; const healthChecker = new HealthChecker(jenkinsRootUrl, requestOptions); @@ -45,7 +48,7 @@ describe('The healthchecker module', () => { expect(healthChecker.factor).toEqual(requestOptions.factor); }); it('should handle non int value in env var', () => { - process.env.PROCESS_RETRY_OVERRIDE = true; + process.env.PROCESS_RETRY_OVERRIDE = 'true'; const jenkinsRootUrl = `http://localhost:${port}`; const requestOptions = {delay: 100, retry: 1, factor: 1.01}; const healthChecker = new HealthChecker(jenkinsRootUrl, requestOptions); diff --git a/distribution/client/test/periodic.test.js b/distribution/client/test/periodic.test.js deleted file mode 100644 index acbbc3d..0000000 --- a/distribution/client/test/periodic.test.js +++ /dev/null @@ -1,33 +0,0 @@ -const assert = require('assert'); -const periodic = require('../src/lib/periodic'); - -describe('The periodic module', () => { - /* Just a simple fake app for unit test - */ - let app = new Object(); - - describe('runHourly()', () => { - it('allow registration of an hourly callback', () => { - let p = periodic(app); - assert.ok(p.runHourly('jest-fun', () => { })); - }); - }); - - describe('runDaily()', () => { - it('allows registration of a daily callback', () => { - let p = periodic(app); - assert.ok(p.runDaily('jest-fun', () => { })); - }); - }); - - describe('computeOffset()', () => { - let p = periodic(app); - - it('should return a number between 0-59', () => { - let offset = p.computeOffset(); - assert.equal(typeof offset, 'number'); - assert.ok(offset <= 59); - assert.ok(offset >= 0); - }); - }); -}); diff --git a/distribution/client/test/periodic.test.ts b/distribution/client/test/periodic.test.ts new file mode 100644 index 0000000..6995da7 --- /dev/null +++ b/distribution/client/test/periodic.test.ts @@ -0,0 +1,29 @@ +import Periodic from '../src/lib/periodic'; + +describe('The periodic module', () => { + /* Just a simple fake app for unit test + */ + describe('runHourly()', () => { + it('allow registration of an hourly callback', () => { + const p = new Periodic(); + expect(p.runHourly('jest-fun', () => {})).toBeTruthy(); + }); + }); + + describe('runDaily()', () => { + it('allows registration of a daily callback', () => { + const p = new Periodic(); + expect(p.runDaily('jest-fun', () => {})).toBeTruthy(); + }); + }); + + describe('computeOffset()', () => { + const p = new Periodic(); + + it('should return a number between 0-59', () => { + const offset = p.computeOffset(); + expect(offset).toBeGreaterThanOrEqual(0); + expect(offset).toBeLessThanOrEqual(59); + }); + }); +}); diff --git a/distribution/client/test/registration.test.js b/distribution/client/test/registration.test.ts similarity index 84% rename from distribution/client/test/registration.test.js rename to distribution/client/test/registration.test.ts index 2121106..9659e5d 100644 --- a/distribution/client/test/registration.test.js +++ b/distribution/client/test/registration.test.ts @@ -3,9 +3,11 @@ jest.mock('fs'); const assert = require('assert'); const fs = require('fs'); const path = require('path'); -const Registration = require('../src/lib/registration'); + +import Registration from '../src/lib/registration'; describe('The registration module', () => { + const app = new Object(); beforeEach(() => { /* Make sure memfs is flushed every time */ fs.volume.reset(); @@ -13,19 +15,19 @@ describe('The registration module', () => { describe('register()', () => { it('should return a Promise', () => { - const response = (new Registration()).register(); + const response = (new Registration(app)).register(); assert(response instanceof Promise); }); }); describe('getPublicKey()', () => { it('should return null on a new instance', () => { - const r = new Registration(); + const r = new Registration(app); assert.equal(null, r.getPublicKey()); }); it('should return a public key after generateKeys() has been called', () => { - const r = new Registration(); + const r = new Registration(app); assert(r.generateKeys()); assert.equal(typeof r.getPublicKey(), 'string'); }); @@ -33,7 +35,7 @@ describe('The registration module', () => { describe('saveUUIDSync()', () => { beforeEach(() => { - this.reg = new Registration(); + this.reg = new Registration(app); }); it('should not write anything by default', () => { assert.equal(this.reg.saveUUIDSync(), false); @@ -62,7 +64,7 @@ describe('The registration module', () => { describe('loadUUIDSync()', () => { let uuid = 'just another-fake-uuid'; beforeEach(() => { - this.reg = new Registration(); + this.reg = new Registration(app); this.reg.uuid = uuid; this.reg.saveUUIDSync(); }); @@ -76,13 +78,13 @@ describe('The registration module', () => { describe('saveKeysSync()', () => { it('should return false if there are not keys', () => { - const r = new Registration(); + const r = new Registration(app); assert(!r.saveKeysSync()); }); describe('when keys have been generated', () => { beforeEach(() => { - this.reg = new Registration(); + this.reg = new Registration(app); this.reg.generateKeys(); }); it('should return true if the public key has been written', () => { @@ -107,7 +109,7 @@ describe('The registration module', () => { describe('loadKeysSync()', () => { beforeEach(() => { - this.reg = new Registration(); + this.reg = new Registration(app); }); it('should return false by default when there are no keys', () => { @@ -121,7 +123,7 @@ describe('The registration module', () => { describe('when keys are already on disk', () => { beforeEach(() => { - const preflight = new Registration(); + const preflight = new Registration(app); preflight.generateKeys(); preflight.saveKeysSync(); }); @@ -135,31 +137,31 @@ describe('The registration module', () => { describe('hasKeys()', () => { it('should return false by default', () => { - assert.equal((new Registration()).hasKeys(), false); + assert.equal((new Registration(app)).hasKeys(), false); }); }); describe('generateKeys()', () => { it('should return a boolean on success', () => { - assert.ok((new Registration()).generateKeys()); + assert.ok((new Registration(app)).generateKeys()); }); }); describe('publicKeyPath()', () => { it('should return a path', () => { - const p = (new Registration()).publicKeyPath(); + const p = (new Registration(app)).publicKeyPath(); assert(p != path.basename(p), 'This doesn\'t look like a path'); }); }); describe('keyPath()', () => { it('should return a path', () => { - const keys = (new Registration()).keyPath(); + const keys = (new Registration(app)).keyPath(); assert(keys != path.basename(keys), 'This doesn\'t look like a path'); }); it('should create a directory if one does not exist', () => { - const keyPath = (new Registration()).keyPath(); + const keyPath = (new Registration(app)).keyPath(); const stats = fs.statSync(keyPath); assert(stats.isDirectory()); }); @@ -176,7 +178,7 @@ describe('The registration module', () => { describe('uuidPath()', () => { it('should return a path', () => { - const p = (new Registration()).uuidPath(); + const p = (new Registration(app)).uuidPath(); assert(p != path.basename(p), 'This doesn\'t look like a path'); }); }); diff --git a/distribution/client/test/snapshotter.test.js b/distribution/client/test/snapshotter.test.ts similarity index 91% rename from distribution/client/test/snapshotter.test.js rename to distribution/client/test/snapshotter.test.ts index 21c4809..3eddead 100644 --- a/distribution/client/test/snapshotter.test.js +++ b/distribution/client/test/snapshotter.test.ts @@ -1,10 +1,10 @@ -const Snapshotter = require('../src/lib/snapshotter'); -const tmp = require('tmp'); const fs = require('fs'); -describe('The snapshotting module', () => { +import tmp from 'tmp'; +import Snapshotter from '../src/lib/snapshotter'; - let tmpDir = ''; +describe('The snapshotting module', () => { + let tmpDir = null; beforeEach(() => { tmpDir = tmp.dirSync({unsafeCleanup: true}); }); diff --git a/distribution/client/test/status.test.js b/distribution/client/test/status.test.ts similarity index 93% rename from distribution/client/test/status.test.js rename to distribution/client/test/status.test.ts index 2e7fdb7..97d2a7c 100644 --- a/distribution/client/test/status.test.js +++ b/distribution/client/test/status.test.ts @@ -5,7 +5,8 @@ jest.mock('fs'); const fs = require('fs'); const mkdirp = require('mkdirp'); const feathers = require('@feathersjs/feathers'); -const Status = require('../src/lib/status'); + +import Status from '../src/lib/status'; describe('The status module', () => { beforeEach(() => { @@ -57,7 +58,7 @@ describe('The status module', () => { describe('collectVersions()', () => { it('should contain a node version', () => { - const versions = (new Status(app)).collectVersions(); + const versions : any = (new Status(app)).collectVersions(); expect(versions.container.tools.node).toBeTruthy(); }); @@ -80,7 +81,7 @@ describe('The status module', () => { }); it('should contain the signature of the plugin', () => { - const versions = (new Status(app)).collectVersions(); + const versions : any = (new Status(app)).collectVersions(); expect(versions.jenkins.plugins.git).toBeTruthy(); }); }); diff --git a/distribution/client/test/storage.test.js b/distribution/client/test/storage.test.ts similarity index 95% rename from distribution/client/test/storage.test.js rename to distribution/client/test/storage.test.ts index dc464f9..2b8f922 100644 --- a/distribution/client/test/storage.test.js +++ b/distribution/client/test/storage.test.ts @@ -3,8 +3,9 @@ jest.mock('fs'); const fs = require('fs'); const mkdirp = require('mkdirp'); const path = require('path'); -const h = require('./helpers'); -const Storage = require('../src/lib/storage'); + +import h from '../testlib/helpers'; +import Storage from '../src/lib/storage'; describe('The storage module', () => { let dir = '/tmp'; diff --git a/distribution/client/test/ui.test.js b/distribution/client/test/ui.test.ts similarity index 74% rename from distribution/client/test/ui.test.js rename to distribution/client/test/ui.test.ts index 4a1c863..4c9fc0b 100644 --- a/distribution/client/test/ui.test.js +++ b/distribution/client/test/ui.test.ts @@ -1,4 +1,5 @@ -const UI = require('../src/lib/ui'); + +import UI from '../src/lib/ui'; describe('The UI module', () => { it('should be a singleton', () => { diff --git a/distribution/client/test/update.test.js b/distribution/client/test/update.test.ts similarity index 92% rename from distribution/client/test/update.test.js rename to distribution/client/test/update.test.ts index d5d8dd6..1cf613f 100644 --- a/distribution/client/test/update.test.js +++ b/distribution/client/test/update.test.ts @@ -1,17 +1,19 @@ jest.mock('../src/lib/supervisord'); jest.mock('../src/lib/downloader'); -const tmp = require('tmp'); const fs = require('fs'); const feathers = require('@feathersjs/feathers'); -const h = require('./helpers'); -const Update = require('../src/lib/update'); -const HealthChecker = require('../src/lib/healthchecker'); -const Storage = require('../src/lib/storage'); -const Supervisord = require('../src/lib/supervisord'); -const Downloader = require('../src/lib/downloader'); const mkdirp = require('mkdirp'); +import tmp from 'tmp'; +import h from '../testlib/helpers'; + +import Update from '../src/lib/update'; +import HealthChecker from '../src/lib/healthchecker'; +import Storage from '../src/lib/storage'; +import Supervisord from '../src/lib/supervisord'; +import Downloader from '../src/lib/downloader'; + describe('The update module', () => { let app = null; let update = null; @@ -124,7 +126,7 @@ describe('The update module', () => { it ('should execute updates if passed in with no deletes', async () => { jest.setTimeout(10000); - Downloader.mockImplementationOnce(() => { + (Downloader as unknown as jest.Mock).mockImplementationOnce(() => { return require.requireActual('../src/lib/downloader').default(); }); @@ -146,7 +148,7 @@ describe('The update module', () => { }); it('should execute both updates and deletes if both passed in', async () => { - Downloader.mockImplementationOnce(() => { + (Downloader as unknown as jest.Mock).mockImplementationOnce(() => { return require.requireActual('../src/lib/downloader').default(); }); manifest.plugins.deletes = ['delete1']; diff --git a/distribution/client/test/helpers.js b/distribution/client/testlib/helpers.ts similarity index 89% rename from distribution/client/test/helpers.js rename to distribution/client/testlib/helpers.ts index b135ec9..060e3ee 100644 --- a/distribution/client/test/helpers.js +++ b/distribution/client/testlib/helpers.ts @@ -8,7 +8,7 @@ const open = promisify(fs.open); const close = promisify(fs.close); const access = promisify(fs.access); -class Helpers { +export class Helpers { constructor () { } @@ -23,4 +23,4 @@ class Helpers { } } -module.exports = new Helpers(); \ No newline at end of file +export default new Helpers(); diff --git a/distribution/client/tsconfig.json b/distribution/client/tsconfig.json index 5f012e2..f87a8d2 100644 --- a/distribution/client/tsconfig.json +++ b/distribution/client/tsconfig.json @@ -5,7 +5,7 @@ "outDir": "./build", "module" : "commonjs", "skipLibCheck": true, - "lib" : ["es2017"], + "lib" : ["es2015"], "module": "commonjs", "moduleResolution": "node", "esModuleInterop": true, diff --git a/node.mk b/node.mk index fb210b3..a906f20 100644 --- a/node.mk +++ b/node.mk @@ -12,8 +12,8 @@ fix-formatting: depends check:: lint $(MAKE) unit -unit: depends - if [ -z "$${SKIP_TESTS}" ]; then $(NODE) npm run jest; \ +unit:: depends + if [ -z "$${SKIP_TESTS}" ]; then $(NODE) npm run test; \ else echo "Tests are skipped!"; fi; debug-unit: depends