Merge pull request #556 from kitematic/integration-tests

Docker Hub Integration tests
This commit is contained in:
Jeffrey Morgan 2015-05-27 14:44:22 -07:00
Родитель c8067c92c0 a3aec13850
Коммит 48613c9e45
9 изменённых файлов: 131 добавлений и 35 удалений

3
.gitignore поставляемый
Просмотреть файл

@ -9,6 +9,9 @@ npm-debug.log
# Signing Identity
identity*
# Integration test environment
integration
# Resources
resources/docker-*
resources/boot2docker-*

Просмотреть файл

@ -1,23 +1,32 @@
jest.autoMockOff();
let hubUtil = require('../src/utils/HubUtil');
let Promise = require('bluebird');
jasmine.getEnv().DEFAULT_TIMEOUT_INTERVAL = 60000;
describe('HubUtil Integration Tests', () => {
describe('token refresh', () => {
it('re-auths if the token has expired', () => {
expect(true).toBe(true);
describe('auth', () => {
pit('successfully authenticates', () => {
return new Promise((resolve) => {
hubUtil.auth(process.env.INTEGRATION_USER, process.env.INTEGRATION_PASSWORD, (error, response, body) => {
expect(response.statusCode).toBe(200);
expect(error).toBe(null);
let data = JSON.parse(body);
expect(data.token).toBeTruthy();
resolve();
});
});
});
describe('signup', () => {
it('returns a 204 and sets localstorage data', () => {
pit('provides a 401 if credentials are incorrect', () => {
return new Promise((resolve) => {
hubUtil.auth(process.env.INTEGRATION_USER, 'incorrectpassword', (error, response) => {
expect(response.statusCode).toBe(401);
resolve();
});
});
describe('login', () => {
it('Returns a 401 with account not active string if not active', () => {
});
it('Returns a 401 if the password is wrong', () => {
});
});
});

Просмотреть файл

@ -1,9 +1,59 @@
jest.autoMockOff();
// One minute timeout for integration tests
jasmine.getEnv().DEFAULT_TIMEOUT_INTERVAL = 60000;
let _ = require('underscore');
let regHubUtil = require('../src/utils/RegHubUtil');
let hubUtil = require('../src/utils/HubUtil');
let Promise = require('bluebird');
describe('RegHubUtil Integration Tests', () => {
describe('repos', () => {
it('returns set of repos', () => {
describe('with login', () => {
pit('lists private repos', () => {
return new Promise((resolve) => {
hubUtil.login(process.env.INTEGRATION_USER, process.env.INTEGRATION_PASSWORD, () => {
regHubUtil.repos((error, repos) => {
expect(_.findWhere(repos, {name: 'test_private', is_private: true})).toBeTruthy();
resolve();
});
});
});
});
pit('lists tags for a private repo', () => {
return new Promise((resolve) => {
hubUtil.login(process.env.INTEGRATION_USER, process.env.INTEGRATION_PASSWORD, () => {
regHubUtil.tags(`${process.env.INTEGRATION_USER}/test_private`, (error, tags) => {
expect(error).toBeFalsy();
expect(tags).toEqual(['latest']);
resolve();
});
});
});
});
});
describe('public repos', () => {
pit('lists repos', () => {
return new Promise((resolve) => {
hubUtil.login(process.env.INTEGRATION_USER, process.env.INTEGRATION_PASSWORD, () => {
regHubUtil.repos((error, repos) => {
expect(_.findWhere(repos, {name: 'test'})).toBeTruthy();
resolve();
});
});
});
});
pit('lists tags for a repo', () => {
return new Promise((resolve) => {
hubUtil.login(process.env.INTEGRATION_USER, process.env.INTEGRATION_PASSWORD, () => {
regHubUtil.tags(`${process.env.INTEGRATION_USER}/test`, (error, tags) => {
expect(error).toBeFalsy();
expect(tags).toEqual(['latest']);
resolve();
});
});
});
});
});
});

Просмотреть файл

@ -6,7 +6,8 @@ class RepositoryServerActions {
'reposLoading',
'resultsUpdated',
'recommendedUpdated',
'reposUpdated'
'reposUpdated',
'error'
);
}
}

Просмотреть файл

@ -3,7 +3,8 @@ import alt from '../alt';
class TagServerActions {
constructor () {
this.generateActions(
'tagsUpdated'
'tagsUpdated',
'error'
);
}
}

Просмотреть файл

@ -38,6 +38,11 @@ class TagStore {
this.tags = {};
this.emitChange();
}
error ({repo}) {
this.loading[repo] = false;
this.emitChange();
}
}
export default alt.createStore(TagStore);

Просмотреть файл

@ -2,6 +2,8 @@ var _ = require('underscore');
var request = require('request');
var accountServerActions = require('../actions/AccountServerActions');
let HUB2_ENDPOINT = process.env.HUB2_ENDPOINT || 'https://hub.docker.com/v2';
module.exports = {
init: function () {
accountServerActions.prompted({prompted: localStorage.getItem('auth.prompted')});
@ -95,10 +97,11 @@ module.exports = {
localStorage.removeItem('auth.config');
},
login: function (username, password) {
login: function (username, password, callback) {
this.auth(username, password, (error, response, body) => {
if (error) {
accountServerActions.errors({errors: {detail: error.message}});
callback(error);
return;
}
@ -112,9 +115,11 @@ module.exports = {
localStorage.setItem('auth.config', new Buffer(username + ':' + password).toString('base64'));
accountServerActions.loggedin({username, verified: true});
accountServerActions.prompted({prompted: true});
if (callback) { callback(); }
require('./RegHubUtil').repos();
} else {
accountServerActions.errors({errors: {detail: 'Did not receive login token.'}});
if (callback) { callback(new Error('Did not receive login token.')); }
}
} else if (response.statusCode === 401) {
if (data && data.detail && data.detail.indexOf('Account not active yet') !== -1) {
@ -123,15 +128,17 @@ module.exports = {
localStorage.setItem('auth.username', username);
localStorage.setItem('auth.verified', false);
localStorage.setItem('auth.config', new Buffer(username + ':' + password).toString('base64'));
if (callback) { callback(); }
} else {
accountServerActions.errors({errors: data});
if (callback) { callback(new Error(data.detail)); }
}
}
});
},
auth: function (username, password, callback) {
request.post('https://hub.docker.com/v2/users/login/', {form: {username, password}}, (error, response, body) => {
request.post(`${HUB2_ENDPOINT}/users/login/`, {form: {username, password}}, (error, response, body) => {
callback(error, response, body);
});
},
@ -153,7 +160,7 @@ module.exports = {
// Signs up and places a token under ~/.dockercfg and saves a jwt to localstore
signup: function (username, password, email, subscribe) {
request.post('https://hub.docker.com/v2/users/signup/', {
request.post('${HUB2_ENDPOINT}/users/signup/', {
form: {
username,
password,

Просмотреть файл

@ -5,7 +5,9 @@ var util = require('../utils/Util');
var hubUtil = require('../utils/HubUtil');
var repositoryServerActions = require('../actions/RepositoryServerActions');
var tagServerActions = require('../actions/TagServerActions');
var Promise = require('bluebird');
let REGHUB2_ENDPOINT = process.env.REGHUB2_ENDPOINT || 'https://registry.hub.docker.com/v2';
let searchReq = null;
module.exports = {
@ -38,7 +40,7 @@ module.exports = {
qs: {q: query, page}
}, (error, response, body) => {
if (error) {
repositoryServerActions.searchError({error});
repositoryServerActions.error({error});
}
let data = JSON.parse(body);
@ -66,7 +68,7 @@ module.exports = {
}
request.get({
url: `https://registry.hub.docker.com/v2/repositories/${name}`,
url: `${REGHUB2_ENDPOINT}/repositories/${name}`,
}, (error, response, body) => {
if (error) {
repositoryServerActions.error({error});
@ -86,28 +88,38 @@ module.exports = {
});
},
tags: function (repo) {
tags: function (repo, callback) {
hubUtil.request({
url: `https://registry.hub.docker.com/v2/repositories/${repo}/tags`
url: `${REGHUB2_ENDPOINT}/repositories/${repo}/tags`
}, (error, response, body) => {
if (response.statusCode === 200) {
let data = JSON.parse(body);
tagServerActions.tagsUpdated({repo, tags: data.tags});
} else if (response.statusCude === 401) {
return;
if (callback) { callback(null, data.tags); }
} else if (error || response.statusCode === 401) {
repositoryServerActions.error({repo});
if (callback) { callback(new Error('Failed to fetch repos')); }
}
});
},
// Returns the base64 encoded index token or null if no token exists
repos: function () {
repos: function (callback) {
repositoryServerActions.reposLoading({repos: []});
hubUtil.request({
url: 'https://registry.hub.docker.com/v2/namespaces/',
url: `${REGHUB2_ENDPOINT}/namespaces/`,
}, (error, response, body) => {
if (error) {
repositoryServerActions.reposError({error});
repositoryServerActions.error({error});
if (callback) { callback(error); }
return;
}
if (response.statusCode !== 200) {
let generalError = new Error('Failed to fetch repos');
repositoryServerActions.error({error: generalError});
if (callback) { callback({error: generalError}); }
return;
}
@ -115,10 +127,11 @@ module.exports = {
let namespaces = data.namespaces;
async.map(namespaces, (namespace, cb) => {
hubUtil.request({
url: `https://registry.hub.docker.com/v2/repositories/${namespace}`
url: `${REGHUB2_ENDPOINT}/repositories/${namespace}`
}, (error, response, body) => {
if (error) {
repositoryServerActions.reposError({error});
repositoryServerActions.error({error});
if (callback) { callback(error); }
return;
}
@ -126,6 +139,12 @@ module.exports = {
cb(null, data.results);
});
}, (error, lists) => {
if (error) {
repositoryServerActions.error({error});
if (callback) { callback(error); }
return;
}
let repos = [];
for (let list of lists) {
repos = repos.concat(list);
@ -136,6 +155,7 @@ module.exports = {
});
repositoryServerActions.reposUpdated({repos});
if (callback) { callback(null, repos); }
});
});
}