mirror of
https://github.com/docker/docs.git
synced 2026-03-27 06:18:55 +07:00
Unit tests for url opener
This commit is contained in:
@@ -66,6 +66,7 @@
|
||||
"mixpanel": "0.2.0",
|
||||
"node-uuid": "^1.4.3",
|
||||
"object-assign": "^2.0.0",
|
||||
"parseUri": "^1.2.3-2",
|
||||
"react": "^0.13.1",
|
||||
"react-bootstrap": "^0.20.3",
|
||||
"react-retina-image": "^1.1.2",
|
||||
|
||||
41
src/app.js
41
src/app.js
@@ -11,7 +11,9 @@ var metrics = require('./utils/MetricsUtil');
|
||||
var router = require('./router');
|
||||
var template = require('./menutemplate');
|
||||
var webUtil = require('./utils/WebUtil');
|
||||
var util = require ('./utils/Util');
|
||||
var urlUtil = require ('./utils/URLUtil');
|
||||
var app = remote.require('app');
|
||||
var request = require('request');
|
||||
|
||||
webUtil.addWindowSizeSaving();
|
||||
webUtil.addLiveReload();
|
||||
@@ -28,12 +30,6 @@ setInterval(function () {
|
||||
|
||||
router.run(Handler => React.render(<Handler/>, document.body));
|
||||
|
||||
ipc.on('application:quitting', opts => {
|
||||
if (!opts.updating && localStorage.getItem('settings.closeVMOnQuit') === 'true') {
|
||||
machine.stop();
|
||||
}
|
||||
});
|
||||
|
||||
SetupStore.setup().then(() => {
|
||||
if (ContainerStore.pending()) {
|
||||
router.transitionTo('pull');
|
||||
@@ -60,26 +56,15 @@ ipc.on('application:quitting', () => {
|
||||
}
|
||||
});
|
||||
|
||||
// Event fires when the app receives a docker:// URL such as
|
||||
// docker://repository/run/redis
|
||||
ipc.on('application:open-url', opts => {
|
||||
var parser = document.createElement('a');
|
||||
parser.href = opts.url;
|
||||
|
||||
if (parser.protocol !== 'docker:') {
|
||||
return;
|
||||
}
|
||||
|
||||
var pathname = parser.pathname.replace('//', '');
|
||||
var tokens = pathname.split('/');
|
||||
var type = tokens[0];
|
||||
var method = tokens[1];
|
||||
var repo = tokens.slice(2).join('/');
|
||||
|
||||
// Only accept official repos for now
|
||||
if (!util.isOfficialRepo(repo)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (type === 'repository' && method === 'run') {
|
||||
ContainerStore.setPending(repo, 'latest');
|
||||
}
|
||||
request.get('https://kitematic.com/flags.json', (flags, err) => {
|
||||
if (err || !flags) {
|
||||
return;
|
||||
}
|
||||
urlUtil.openUrl(opts.url, flags, app.getVersion());
|
||||
});
|
||||
});
|
||||
|
||||
urlUtil.openUrl('docker://repository/run/redis', {dockerURLEnabledVersion: '0.5.19'}, app.getVersion());
|
||||
|
||||
@@ -21,7 +21,7 @@ describe('SetupStore', function () {
|
||||
pit('downloads virtualbox if it is installed but has an outdated version', function () {
|
||||
virtualBox.installed.mockReturnValue(true);
|
||||
virtualBox.version.mockReturnValue(Promise.resolve('4.3.16'));
|
||||
setupUtil.compareVersions.mockReturnValue(-1);
|
||||
util.compareVersions.mockReturnValue(-1);
|
||||
setupUtil.download.mockReturnValue(Promise.resolve());
|
||||
util.packagejson.mockReturnValue({'virtualbox-filename': ''});
|
||||
util.supportDir.mockReturnValue('');
|
||||
@@ -50,7 +50,7 @@ describe('SetupStore', function () {
|
||||
|
||||
pit('only installs binaries if virtualbox is installed', function () {
|
||||
virtualBox.installed.mockReturnValue(true);
|
||||
setupUtil.compareVersions.mockReturnValue(0);
|
||||
util.compareVersions.mockReturnValue(0);
|
||||
setupUtil.needsBinaryFix.mockReturnValue(true);
|
||||
return setupStore.steps().install.run().then(() => {
|
||||
expect(util.exec).toBeCalledWith('macsudo copycmd && fixcmd');
|
||||
@@ -68,7 +68,7 @@ describe('SetupStore', function () {
|
||||
machine.stop.mockReturnValue(Promise.resolve());
|
||||
machine.start.mockReturnValue(Promise.resolve());
|
||||
machine.upgrade.mockReturnValue(Promise.resolve());
|
||||
setupUtil.compareVersions.mockReturnValue(-1);
|
||||
util.compareVersions.mockReturnValue(-1);
|
||||
machine.create.mockClear();
|
||||
machine.upgrade.mockClear();
|
||||
machine.start.mockClear();
|
||||
|
||||
@@ -76,7 +76,7 @@ var _steps = [{
|
||||
|
||||
var isoversion = machine.isoversion();
|
||||
var packagejson = util.packagejson();
|
||||
if (!isoversion || setupUtil.compareVersions(isoversion, packagejson['docker-version']) < 0) {
|
||||
if (!isoversion || util.compareVersions(isoversion, packagejson['docker-version']) < 0) {
|
||||
yield machine.start();
|
||||
yield machine.upgrade();
|
||||
}
|
||||
@@ -152,10 +152,10 @@ var SetupStore = assign(Object.create(EventEmitter.prototype), {
|
||||
var vboxNeedsInstall = !virtualBox.installed();
|
||||
required.download = vboxNeedsInstall && (!fs.existsSync(vboxfile) || setupUtil.checksum(vboxfile) !== packagejson['virtualbox-checksum']);
|
||||
required.install = vboxNeedsInstall || setupUtil.needsBinaryFix();
|
||||
required.init = required.install || !(yield machine.exists()) || (yield machine.state()) !== 'Running' || !isoversion || setupUtil.compareVersions(isoversion, packagejson['docker-version']) < 0;
|
||||
required.init = required.install || !(yield machine.exists()) || (yield machine.state()) !== 'Running' || !isoversion || util.compareVersions(isoversion, packagejson['docker-version']) < 0;
|
||||
|
||||
var exists = yield machine.exists();
|
||||
if (isoversion && setupUtil.compareVersions(isoversion, packagejson['docker-version']) < 0) {
|
||||
if (isoversion && util.compareVersions(isoversion, packagejson['docker-version']) < 0) {
|
||||
this.steps().init.seconds = 33;
|
||||
} else if (exists && (yield machine.state()) === 'Saved') {
|
||||
this.steps().init.seconds = 8;
|
||||
|
||||
@@ -108,55 +108,6 @@ var SetupUtil = {
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
},
|
||||
compareVersions: function (v1, v2, options) {
|
||||
var lexicographical = options && options.lexicographical,
|
||||
zeroExtend = options && options.zeroExtend,
|
||||
v1parts = v1.split('.'),
|
||||
v2parts = v2.split('.');
|
||||
|
||||
function isValidPart(x) {
|
||||
return (lexicographical ? /^\d+[A-Za-z]*$/ : /^\d+$/).test(x);
|
||||
}
|
||||
|
||||
if (!v1parts.every(isValidPart) || !v2parts.every(isValidPart)) {
|
||||
return NaN;
|
||||
}
|
||||
|
||||
if (zeroExtend) {
|
||||
while (v1parts.length < v2parts.length) {
|
||||
v1parts.push('0');
|
||||
}
|
||||
while (v2parts.length < v1parts.length) {
|
||||
v2parts.push('0');
|
||||
}
|
||||
}
|
||||
|
||||
if (!lexicographical) {
|
||||
v1parts = v1parts.map(Number);
|
||||
v2parts = v2parts.map(Number);
|
||||
}
|
||||
|
||||
for (var i = 0; i < v1parts.length; ++i) {
|
||||
if (v2parts.length === i) {
|
||||
return 1;
|
||||
}
|
||||
if (v1parts[i] === v2parts[i]) {
|
||||
continue;
|
||||
}
|
||||
else if (v1parts[i] > v2parts[i]) {
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (v1parts.length !== v2parts.length) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
53
src/utils/URLUtil-test.js
Normal file
53
src/utils/URLUtil-test.js
Normal file
@@ -0,0 +1,53 @@
|
||||
jest.dontMock('./URLUtil');
|
||||
jest.dontMock('parseUri');
|
||||
var urlUtil = require('./URLUtil');
|
||||
var util = require('./Util');
|
||||
|
||||
describe('URLUtil', function () {
|
||||
beforeEach(() => {
|
||||
util.compareVersions.mockClear();
|
||||
util.isOfficialRepo.mockClear();
|
||||
});
|
||||
|
||||
it('does nothing if the url is undefined', () => {
|
||||
util.compareVersions.mockReturnValue(1);
|
||||
util.isOfficialRepo.mockReturnValue(true);
|
||||
expect(urlUtil.openUrl()).toBe(false);
|
||||
});
|
||||
|
||||
it('does nothing if the flags are undefined', () => {
|
||||
util.compareVersions.mockReturnValue(1);
|
||||
util.isOfficialRepo.mockReturnValue(true);
|
||||
expect(urlUtil.openUrl('docker://repository/run/redis')).toBe(false);
|
||||
});
|
||||
|
||||
it('does nothing if the url enabled flag is falsy', () => {
|
||||
util.compareVersions.mockReturnValue(1);
|
||||
util.isOfficialRepo.mockReturnValue(true);
|
||||
expect(urlUtil.openUrl('docker://repository/run/redis', {dockerURLEnabledVersion: undefined})).toBe(false);
|
||||
});
|
||||
|
||||
it('does nothing if the url enabled flag is less than the flag version', () => {
|
||||
util.compareVersions.mockReturnValue(-1);
|
||||
util.isOfficialRepo.mockReturnValue(true);
|
||||
expect(urlUtil.openUrl('docker://repository/run/redis', {dockerURLEnabledVersion: '0.5.19'}, '0.5.18')).toBe(false);
|
||||
});
|
||||
|
||||
it('does nothing if protocol is not docker:', () => {
|
||||
util.compareVersions.mockReturnValue(1);
|
||||
util.isOfficialRepo.mockReturnValue(true);
|
||||
expect(urlUtil.openUrl('facetime://')).toBe(false);
|
||||
});
|
||||
|
||||
it('does nothing if repo is not official', () => {
|
||||
util.compareVersions.mockReturnValue(1);
|
||||
util.isOfficialRepo.mockReturnValue(false);
|
||||
expect(urlUtil.openUrl('docker://repository/run/not/official', {dockerURLEnabledVersion: '0.5.19'}, '0.5.20')).toBe(false);
|
||||
});
|
||||
|
||||
it('returns true if type and method are correct', () => {
|
||||
util.compareVersions.mockReturnValue(1);
|
||||
util.isOfficialRepo.mockReturnValue(true);
|
||||
expect(urlUtil.openUrl('docker://repository/run/redis', {dockerURLEnabledVersion: '0.5.19'}, '0.5.20')).toBe(true);
|
||||
});
|
||||
});
|
||||
44
src/utils/URLUtil.js
Normal file
44
src/utils/URLUtil.js
Normal file
@@ -0,0 +1,44 @@
|
||||
var util = require('./Util');
|
||||
var parseUri = require('parseUri');
|
||||
var containerStore = require('../Stores/ContainerStore');
|
||||
|
||||
module.exports = {
|
||||
openUrl: function (url, flags, appVersion) {
|
||||
if (!url || !flags || !flags.dockerURLEnabledVersion) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make sure this feature is enabled via the feature flag
|
||||
if (util.compareVersions(appVersion, flags.dockerURLEnabledVersion) < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var parser = parseUri(url);
|
||||
|
||||
if (parser.protocol !== 'docker') {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get the type of object we're operating on, e.g. 'repository'
|
||||
var type = parser.host;
|
||||
|
||||
// Separate the path into [run', 'redis']
|
||||
var tokens = parser.path.replace('/', '').split('/');
|
||||
|
||||
// Get the method trying to be executed, e.g. 'run'
|
||||
var method = tokens[0];
|
||||
|
||||
// Get the repository namespace and repo name, e.g. 'redis' or 'myusername/myrepo'
|
||||
var repo = tokens.slice(1).join('/');
|
||||
|
||||
// Only accept official repos for now
|
||||
if (!util.isOfficialRepo(repo)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (type === 'repository' && method === 'run') {
|
||||
containerStore.setPending(repo, 'latest');
|
||||
return true;
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -59,5 +59,54 @@ module.exports = {
|
||||
var repoRegexp = /^[a-z0-9]+(?:[._-][a-z0-9]+)*$/;
|
||||
return repoRegexp.test(name);
|
||||
},
|
||||
compareVersions: function (v1, v2, options) {
|
||||
var lexicographical = options && options.lexicographical,
|
||||
zeroExtend = options && options.zeroExtend,
|
||||
v1parts = v1.split('.'),
|
||||
v2parts = v2.split('.');
|
||||
|
||||
function isValidPart(x) {
|
||||
return (lexicographical ? /^\d+[A-Za-z]*$/ : /^\d+$/).test(x);
|
||||
}
|
||||
|
||||
if (!v1parts.every(isValidPart) || !v2parts.every(isValidPart)) {
|
||||
return NaN;
|
||||
}
|
||||
|
||||
if (zeroExtend) {
|
||||
while (v1parts.length < v2parts.length) {
|
||||
v1parts.push('0');
|
||||
}
|
||||
while (v2parts.length < v1parts.length) {
|
||||
v2parts.push('0');
|
||||
}
|
||||
}
|
||||
|
||||
if (!lexicographical) {
|
||||
v1parts = v1parts.map(Number);
|
||||
v2parts = v2parts.map(Number);
|
||||
}
|
||||
|
||||
for (var i = 0; i < v1parts.length; ++i) {
|
||||
if (v2parts.length === i) {
|
||||
return 1;
|
||||
}
|
||||
if (v1parts[i] === v2parts[i]) {
|
||||
continue;
|
||||
}
|
||||
else if (v1parts[i] > v2parts[i]) {
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (v1parts.length !== v2parts.length) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
},
|
||||
webPorts: ['80', '8000', '8080', '3000', '5000', '2368', '9200', '8983']
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user