Skip to content

Commit

Permalink
test!: Getting downloader functionality working for github end to end
Browse files Browse the repository at this point in the history
  • Loading branch information
ajfisher committed Dec 9, 2019
1 parent 523bfc5 commit 39459bb
Show file tree
Hide file tree
Showing 3 changed files with 183 additions and 59 deletions.
155 changes: 109 additions & 46 deletions lib/downloader.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
// This module executes the downloading of the files properly.
const axios = require('axios');
const child_process = require('child_process');
const colors = require('colors');
const Download = require('download');
const fs = require('fs');
const fsextra = require('fs-extra');
const http = require('http');
const path = require('path');
const tmp = require('tmp');

Expand All @@ -21,50 +20,6 @@ class Downloader {
}
}

download(firmware, options) {
// manages the download of the firmware
return new Promise((resolve, reject) => {
// check and see if firmware is specified
if (typeof(firmware) === 'undefined') {
// set it to the constructor value
firmware = this.fw;
}

// if we're still undefined then throw an error.
if (typeof(firmware) === 'undefined') {
const err = new Error('There is no firmware supplied');
reject(err);
}

// now we choose what way to download the file
// now check if the firmware is in npm or github.
let downloader_to_use;
if (firmware.npm == undefined) {
// use git repo
console.log('about to call git');
downloader_to_use = this.download_from_github;
} else {
// get from npm now
// console.log('about to call npm');
downloader_to_use = this.download_from_npm.bind(this);
}

downloader_to_use(firmware, options)
.then(hex_path => resolve(hex_path))
.catch(err => reject(err));
});
}

get_manifest_from_github(firmware, options) {
// gets the manifest file from github and returns it.
}

download_from_github(firmware) {
// downloads the file from github and returns the path to the hex file
return new Promise((resolve, reject) => {
resolve('/path/to/hex/file');
});
}

get_path_from_manifest(manifest, firmware, options) {
// takes the manifest data and returns the path to the hex file
Expand Down Expand Up @@ -134,6 +89,80 @@ class Downloader {
return path.join('.', 'node_modules', firmware.npm.package);
}

async get_file_from_github(uri) {
// gets the manifest file from github and returns it.
return await axios.get(uri)
.then((response) => {
if (response.status == '200') {
// got the data
return response.data;
}
})
.catch(err => reject(new Error('Unable to retrieve file')));
}

download_from_github(firmware, options) {
// downloads the file from github and returns the path to the hex file
return new Promise(async(resolve, reject) => {
// setup GH

if (firmware === undefined) {
reject(new Error('No firmware provided'));
}

console.info(colors.magenta(`Installing ${firmware.name} from github`));
// work out where the manifest file is
if (firmware.repo === undefined) {
reject(new Error('No github repo specified'));
}

let manifest_uri = null;
let base_uri = null;
let branch = 'master';
let repo = '';

console.log(firmware);
if (firmware.repo.indexOf('git+https') == 0) {
if (firmware.repo.indexOf('#') > 0 ) {
// we want a branch so get that out of the URL
branch = '/' + firmware.repo.substring(firmware.repo.indexOf('#') + 1);
repo = firmware.repo.substring(22, firmware.repo.indexOf('#'));
} else {
repo = firmware.repo.substring(22);
branch = '/master';
}

base_uri = `https://raw.githubusercontent.com${repo}${branch}`;
manifest_uri = `${base_uri}/manifest.json?${(new Date().getTime())}`;
} else {
reject(new Error('Wrong protocol used for github'));
}

const manifest = await this.get_file_from_github(manifest_uri);
const bin_path = this.get_path_from_manifest(manifest, firmware, options);
const bin_uri = `${base_uri}${bin_path}?${(new Date().getTime())}`;

// save the hex file
this.get_file_from_github(bin_uri)
.then(hexdata => {
const tmpdir = tmp.dirSync();
const hexpath = `${tmpdir.name}/bin.hex`;

fs.writeFile(hexpath, hexdata, (err) => {
if (err) {
fsextra.removeSync(tmpdir.name);
tmpdir.removeCallback();
reject(err);
}

// send this back as an object
resolve({hexpath, tmpdir});
});
})
.catch(err => reject(err));
});
}

download_from_npm(firmware, options) {
// downloads the file from npm and returns the path to the hex file.
return new Promise((resolve, reject) => {
Expand Down Expand Up @@ -176,6 +205,40 @@ class Downloader {
resolve(hex_path);
});
}

download(firmware, options) {
// manages the download of the firmware
return new Promise((resolve, reject) => {
// check and see if firmware is specified
if (typeof(firmware) === 'undefined') {
// set it to the constructor value
firmware = this.fw;
}

// if we're still undefined then throw an error.
if (typeof(firmware) === 'undefined') {
const err = new Error('There is no firmware supplied');
reject(err);
}

// now we choose what way to download the file
// now check if the firmware is in npm or github.
let downloader_to_use;
if (firmware.npm == undefined) {
// use git repo
downloader_to_use = this.download_from_github.bind(this);
} else {
// get from npm now
downloader_to_use = this.download_from_npm.bind(this);
}

downloader_to_use(firmware, options)
.then((values) => {
resolve(values);
})
.catch(err => reject(err));
});
}
}

module.exports = Downloader;
24 changes: 16 additions & 8 deletions lib/interchange.js
Original file line number Diff line number Diff line change
Expand Up @@ -131,9 +131,11 @@ Interchange.prototype.install_firmware = function(firmware, opts = {}) {

try {
this.check_firmware(firmware, settings, function(hex_path, tmp_dir, options) {
this.flash_firmware(hex_path, options, function() {
this.flash_firmware(hex_path, tmp_dir, options, function() {
// once complete destory the tmp_dir.
console.log('flash completed', tmp_dir);
if (tmp_dir) {
console.log('about to clean up');
this.clean_temp_dir(tmp_dir);
}
}.bind(this));
Expand Down Expand Up @@ -181,7 +183,7 @@ Interchange.prototype.set_firmware_details = function(port, opts, cb) {
});
};

Interchange.prototype.flash_firmware = function(firmware, opts, cb) {
Interchange.prototype.flash_firmware = function(firmware, tmp_dir, opts, cb) {
// flashes the board with the options provided.

const board = opts.board || 'nano'; // assumes nano if none provided
Expand Down Expand Up @@ -269,7 +271,7 @@ Interchange.prototype.download_from_npm = function(firmware, options, cb) {
cb(hex_path, null, options);
};
**/

/**
Interchange.prototype.download_from_github = function(firmware, options, cb) {
// downloads the firmware from the GH repo
Expand Down Expand Up @@ -385,6 +387,7 @@ Interchange.prototype.download_from_github = function(firmware, options, cb) {
console.log(err);
});
};
**/

Interchange.prototype.check_firmware = (firmware, options = {}, cb) => {
// checks if the firmware makes sense and downloads the hex file
Expand Down Expand Up @@ -439,19 +442,24 @@ Interchange.prototype.check_firmware = (firmware, options = {}, cb) => {
// now check if the firmware is in npm or github.
if (fw.npm == undefined) {
// use git repo
this.download_from_github(fw, opts, cb);
const dl = new Downloader({fw});
dl.download(fw, opts)
.then(({hexpath, tmpdir}) => {
console.log(hexpath, 'made it to flasing stuff');
cb(hexpath, tmpdir, opts);
})
.catch((err) => console.log(err));
// this.download_from_github(fw, opts, cb);
} else {
// get from npm now
const dl = new Downloader({fw});
// about to try to download from npm
dl.download(fw, opts)
.then((hexpath) => {
console.log(hexpath, 'made it to the point of flashing stuff');
// calling back to write
.then(({hexpath, tmpdir}) => {
// calling back to write firmware
cb(hexpath, null, opts);
})
.catch((err) => console.log(err));
// this.download_from_npm(fw, opts, cb);
}
};

Expand Down
63 changes: 58 additions & 5 deletions test/downloader.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,29 @@ const npm_fw = {
'firmata': false
};

const gh_fw = {
'name': 'test_firmware',
'deviceID': 0x01,
'creatorID': 0x00,
'repo': 'git+https://github.com/test/test-package',
'firmata': false
};

const gh_fw2 = {
'name': 'test_firmware2',
'deviceID': 0x01,
'creatorID': 0x00,
'firmata': false
};

const gh_fw3 = {
'name': 'test_firmware3',
'deviceID': 0x01,
'creatorID': 0x00,
'repo': 'https://github.com/test/test-package',
'firmata': false
};

const manifest = {
'backpack': {
'bins': '/firmware/bin/backpack/',
Expand All @@ -42,6 +65,7 @@ const options = {
firmataName: ''
};


const download_actions = () => describe('1. Download options return hex files', () => {
beforeEach(() => jest.resetModules());

Expand All @@ -66,21 +90,35 @@ const download_actions = () => describe('1. Download options return hex files',
test('1.4 Firmware in NPM chooses NPM download method', async() => {
const dl = new Downloader({fw: npm_fw});

// set up a mock implementation for this test.
const mock_npm_download = jest.fn()
// set up a mock implementation for the download instance which passes and fails
const mock_download = jest.fn()
.mockResolvedValue('mock/filepath')
.mockResolvedValueOnce('mock-firstpath')
.mockRejectedValueOnce(new Error('not downloadable'));

dl.download_from_npm = mock_npm_download;
dl.download_from_npm = mock_download;

const hexfile = await dl.download();
expect(mock_npm_download).toBeCalled();
expect(mock_download).toBeCalled();
// test rejection form
expect(dl.download()).rejects.toThrow(/not downloadable/);
});

test('1.5 Firmware in Github chooses Github download method', () => {
test('1.5 Firmware in Github chooses Github download method', async() => {
const dl = new Downloader({fw: gh_fw});

// set up a mock implementation for the download instance which passes and fails
const mock_download = jest.fn()
.mockResolvedValue('mock/filepath')
.mockResolvedValueOnce('mock-firstpath')
.mockRejectedValueOnce(new Error('not downloadable'));

dl.download_from_github = mock_download;

const hexfile = await dl.download();
expect(mock_download).toBeCalled();
// test rejection form
expect(dl.download()).rejects.toThrow(/not downloadable/);
});


Expand Down Expand Up @@ -155,7 +193,22 @@ const npm_actions = () => describe('3. NPM related actions for the downloader',
});
});

const github_actions = () => describe('4. Github related actions for the downloader', () => {
// test actions relating to the GH way of getting the files
test('4.1 Getting GH manifest fails if no repo supplied', () => {
const dl = new Downloader();
expect(dl.download_from_github()).rejects.toThrow(/firmware/);
});

test('4.2 getting GH manifest fails if GH configuration is wrong', () => {
const dl = new Downloader();
expect(dl.download_from_github(gh_fw2)).rejects.toThrow(/github/);
expect(dl.download_from_github(gh_fw3)).rejects.toThrow(/protocol/);
});
});


download_actions();
download_utilities();
npm_actions();
github_actions();

0 comments on commit 39459bb

Please sign in to comment.