Move old enterpirse code into archive
parent
127ea6f98b
commit
cab1a37740
archive
cluster_accounts
database_manager
retention_policies
ui
spec
access_control
retention_policies
|
@ -214,7 +214,6 @@
|
|||
'react/jsx-curly-spacing': [2, 'never'],
|
||||
'react/jsx-equals-spacing': [2, 'never'],
|
||||
'react/jsx-indent-props': [2, 2],
|
||||
'react/jsx-indent': [2, 2],
|
||||
'react/jsx-key': 2,
|
||||
'react/jsx-no-duplicate-props': 2,
|
||||
'react/jsx-no-undef': 2,
|
||||
|
|
|
@ -1,195 +0,0 @@
|
|||
/* eslint-disable */
|
||||
import React from 'react';
|
||||
import {mount} from 'enzyme';
|
||||
import sinon from 'sinon';
|
||||
import * as api from 'src/shared/apis';
|
||||
import * as metaQueryApi from 'src/shared/apis/metaQuery';
|
||||
|
||||
import {RolePageContainer} from 'src/access_control/containers/RolePageContainer';
|
||||
import {Tab, TabList} from 'src/shared/components/Tabs';
|
||||
|
||||
const clusterID = '1000';
|
||||
|
||||
const rolesResponse = {
|
||||
data: {
|
||||
roles: [
|
||||
{
|
||||
name: "Marketing",
|
||||
permissions: {
|
||||
"": [
|
||||
"ViewAdmin",
|
||||
"CreateDatabase",
|
||||
],
|
||||
},
|
||||
users: [
|
||||
"will@influxdb.com",
|
||||
"jon@influxdb.com",
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Global Admin",
|
||||
permissions: {
|
||||
db1: [
|
||||
"Monitor",
|
||||
"CopyShard",
|
||||
],
|
||||
},
|
||||
users: [
|
||||
"will@influxdb.com",
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Role with no permissions",
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
const roleSlug = rolesResponse.data.roles[0].name;
|
||||
|
||||
const databasesResponse = {
|
||||
data: {"results":[{"series":[{"name":"databases","columns":["name"],"values":[["db1", "db2"]]}]}]},
|
||||
};
|
||||
|
||||
function setup(customProps = {}) {
|
||||
const props = Object.assign({}, {
|
||||
params: {
|
||||
clusterID,
|
||||
roleSlug,
|
||||
},
|
||||
router: {
|
||||
push: sinon.spy(),
|
||||
},
|
||||
addFlashMessage() {},
|
||||
dataNodes: ['localhost:8086'],
|
||||
}, customProps);
|
||||
return mount(<RolePageContainer {...props} />);
|
||||
}
|
||||
|
||||
xdescribe('Role edit page', function() {
|
||||
beforeEach(function() {
|
||||
this.fakes = sinon.collection;
|
||||
this.fakes.stub(api, 'getRoles').returns(Promise.resolve(rolesResponse));
|
||||
this.fakes.stub(metaQueryApi, 'showDatabases').returns(Promise.resolve(databasesResponse));
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
this.fakes.restore();
|
||||
});
|
||||
|
||||
describe('on the permissions tab', function() {
|
||||
it('renders tabs for the role\'s permissions and cluster accounts', function(done) {
|
||||
const wrapper = setup();
|
||||
then(() => {
|
||||
expect(wrapper.find(Tab).length).to.equal(2);
|
||||
expect(wrapper.find(TabList).text()).to.match(/Permissions/);
|
||||
expect(wrapper.find(TabList).text()).to.match(/Cluster Accounts/);
|
||||
}, done);
|
||||
});
|
||||
|
||||
it('renders a list of permissions and locations', function(done) {
|
||||
const wrapper = setup();
|
||||
then(() => {
|
||||
expect(wrapper.find('.permissions-table tr').at(0).text()).to.match(/View Admin/);
|
||||
expect(wrapper.find('.permissions-table tr').at(1).text()).to.match(/Create Database/);
|
||||
}, done);
|
||||
});
|
||||
|
||||
it('renders a "+" button to add a location to a permission', function(done) {
|
||||
const wrapper = setup();
|
||||
then(() => {
|
||||
expect(wrapper.find('.icon.plus').length).to.equal(2);
|
||||
}, done);
|
||||
});
|
||||
});
|
||||
|
||||
describe('on the cluster accounts tab', function() {
|
||||
beforeEach(function() {
|
||||
this.wrapper = setup();
|
||||
then(() => {
|
||||
this.wrapper.find(Tab).at(1).simulate('click'); // Cluster accounts tab
|
||||
});
|
||||
});
|
||||
|
||||
it('renders an empty state for users and roles');
|
||||
|
||||
it('renders a table of cluster accounts', function(done) {
|
||||
then(() => {
|
||||
const table = this.wrapper.find('.cluster-accounts');
|
||||
expect(table.length).to.equal(1);
|
||||
expect(table.find('tr').length).to.equal(3); // Two accounts + header
|
||||
}, done);
|
||||
});
|
||||
});
|
||||
|
||||
describe('after clicking "Delete role" and clicking "Confirm"', function(done) {
|
||||
beforeEach(function() {
|
||||
window.$ = sinon.stub().returns({ modal: () => {} }); // More bootstrap modal requirements
|
||||
this.fakes.stub(api, 'deleteRole').returns(Promise.resolve({
|
||||
data: {},
|
||||
}));
|
||||
this.wrapper = setup();
|
||||
then(() => {
|
||||
this.wrapper.find('button[children="Delete Role"]').simulate('click');
|
||||
this.wrapper.find('#deleteRoleModal button[children="Delete"]').simulate('click');
|
||||
});
|
||||
});
|
||||
|
||||
it('makes the right request', function(done) {
|
||||
then(() => {
|
||||
expect(api.deleteRole.calledWith(clusterID, rolesResponse.data.roles[0].name)).to.be.true
|
||||
}, done);
|
||||
});
|
||||
|
||||
it('navigates back to the roles index', function(done) {
|
||||
then(() => {
|
||||
expect(this.wrapper.props().router.push.calledWith('/clusters/1000/roles')).to.be.true
|
||||
}, done);
|
||||
});
|
||||
it('renders a success notification');
|
||||
});
|
||||
|
||||
describe('after opening the "Add permission" modal and selecting a permission to add', function() {
|
||||
it('renders a list of available databases for that permission');
|
||||
|
||||
describe('and picking a database and confirming', function() {
|
||||
it('makes the right request');
|
||||
it('updates the role\'s list of permissions');
|
||||
it('renders a success notification');
|
||||
});
|
||||
});
|
||||
|
||||
describe('after opening the "Add cluster account" modal and choosing a cluster account', function() {
|
||||
it('makes the right request');
|
||||
it('renders a success notification');
|
||||
});
|
||||
|
||||
describe('after removing a permission from a role', function() {
|
||||
beforeEach(function() {
|
||||
window.$ = sinon.stub().returns({ modal: () => {} }); // More bootstrap modal requirements
|
||||
this.fakes.stub(api, 'removePermissionFromRole').returns(Promise.resolve({
|
||||
data: {},
|
||||
}));
|
||||
this.wrapper = setup();
|
||||
then(() => {
|
||||
this.wrapper.find('button[children="Remove"]').at(0).simulate('click');
|
||||
});
|
||||
});
|
||||
|
||||
it('makes the right request', function(done) {
|
||||
then(() => {
|
||||
const args = api.removePermissionFromRole.args[0];
|
||||
expect(args[0]).to.equal(clusterID);
|
||||
expect(args[1]).to.equal(roleSlug);
|
||||
expect(args[2].name).to.equal('ViewAdmin');
|
||||
}, done);
|
||||
});
|
||||
|
||||
it('removes the permission from the page', function(done) {
|
||||
then(() => {
|
||||
expect(this.wrapper.find('.permissions-table tr').length).to.equal(1);
|
||||
}, done);
|
||||
});
|
||||
});
|
||||
});
|
||||
/* eslint-enable */
|
|
@ -1,176 +0,0 @@
|
|||
/* eslint-disable */
|
||||
import React from 'react';
|
||||
import {mount} from 'enzyme';
|
||||
import sinon from 'sinon';
|
||||
import * as api from 'src/shared/apis';
|
||||
|
||||
import RolesPageContainer from 'src/access_control/containers/RolesPageContainer';
|
||||
|
||||
const rolesResponse = {
|
||||
data: {
|
||||
roles: [
|
||||
{
|
||||
name: "Marketing",
|
||||
permissions: {
|
||||
"": [
|
||||
"ViewAdmin",
|
||||
"CreateDatabase",
|
||||
],
|
||||
},
|
||||
users: [
|
||||
"will@influxdb.com",
|
||||
"jon@influxdb.com",
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Global Admin",
|
||||
permissions: {
|
||||
db1: [
|
||||
"Monitor",
|
||||
"CopyShard",
|
||||
],
|
||||
},
|
||||
users: [
|
||||
"will@influxdb.com",
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Role with no permissions"
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
const clusterID = '1000';
|
||||
|
||||
function setup(customProps = {}) {
|
||||
const props = Object.assign({}, {
|
||||
params: {
|
||||
clusterID,
|
||||
},
|
||||
addFlashMessage: () => {},
|
||||
}, customProps);
|
||||
return mount(<RolesPageContainer {...props} />);
|
||||
}
|
||||
|
||||
function submitRoleForm(wrapper, roleName = 'new role') {
|
||||
const input = wrapper.find('#roleName');
|
||||
const form = wrapper.find('#createRoleModal form');
|
||||
|
||||
input.node.value = roleName;
|
||||
form.simulate('submit');
|
||||
}
|
||||
|
||||
describe('Roles page', function() {
|
||||
// TODO: tests seem better when using the fake server, but for some reason it isn't cooperating.
|
||||
// In the the meantime I'm just stubbing AJAX related.
|
||||
// before(function() { this.server = sinon.fakeServer.create(); });
|
||||
// after(function() { this.server.restore() });
|
||||
// beforeEach(function() {
|
||||
// this.server.respondWith("GET", '/api/int/v1/clusters/1000/roles', [
|
||||
// 200, { "Content-Type": "application/json" },
|
||||
// JSON.stringify(rolesResponse)
|
||||
// ]);
|
||||
// this.server.respondWith("POST", '/api/int/v1/clusters/1000/roles', [
|
||||
// 201, { "Content-Type": "application/json" },
|
||||
// JSON.stringify(createRoleResponse)
|
||||
// ]);
|
||||
// });
|
||||
|
||||
beforeEach(function() {
|
||||
this.fakes = sinon.collection;
|
||||
this.fakes.stub(api, 'getRoles').returns(Promise.resolve(rolesResponse));
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
this.fakes.restore();
|
||||
});
|
||||
|
||||
it('renders a panel for each role', function(done) {
|
||||
const wrapper = setup();
|
||||
then(() => {
|
||||
expect(wrapper.find('.roles .panel').length).to.equal(3);
|
||||
expect(wrapper.find('.roles .panel-heading').at(0).text()).to.match(/Marketing/);
|
||||
expect(wrapper.find('.roles .panel-heading').at(1).text()).to.match(/Global Admin/);
|
||||
}, done);
|
||||
});
|
||||
|
||||
it('renders how many users belong to the role', function(done) {
|
||||
const wrapper = setup();
|
||||
then(() => {
|
||||
expect(wrapper.find('.roles .panel-heading').at(0).text()).to.match(/2 Users/);
|
||||
expect(wrapper.find('.roles .panel-heading').at(1).text()).to.match(/1 User/);
|
||||
}, done);
|
||||
});
|
||||
|
||||
it('renders a "Go to role" link', function(done) {
|
||||
const wrapper = setup();
|
||||
then(() => {
|
||||
const links = wrapper.find('a').findWhere(n => n.text().match(/Go To Role/));
|
||||
expect(links.length).to.equal(3);
|
||||
}, done);
|
||||
});
|
||||
|
||||
describe('when a role has no permissions', function() {
|
||||
it('renders an empty state', function(done) {
|
||||
const wrapper = setup();
|
||||
then(() => {
|
||||
expect(wrapper.find('.roles .generic-empty-state').length).to.equal(1);
|
||||
}, done);
|
||||
});
|
||||
});
|
||||
|
||||
it('renders a list of permissions and locations for each role', function(done) {
|
||||
const wrapper = setup();
|
||||
then(() => {
|
||||
expect(wrapper.find('tr').at(0).text()).to.match(/View Admin/);
|
||||
expect(wrapper.find('tr').at(1).text()).to.match(/Create Databases/);
|
||||
}, done);
|
||||
});
|
||||
|
||||
it('renders all databases associated with each permission', function(done) {
|
||||
const wrapper = setup();
|
||||
then(() => {
|
||||
expect(wrapper.find('tr').at(0).text()).to.match(/All Databases/);
|
||||
expect(wrapper.find('table').at(1).find('tr').at(0).text()).to.match(/db1/);
|
||||
}, done);
|
||||
});
|
||||
|
||||
it('renders a "create role" button', function(done) {
|
||||
const wrapper = setup();
|
||||
then(() => {
|
||||
expect(wrapper.find('button[children="Create Role"]').length).to.equal(1);
|
||||
}, done);
|
||||
});
|
||||
|
||||
describe('after clicking "Create role"', function() {
|
||||
beforeEach(function() {
|
||||
window.$ = sinon.stub().returns({modal: () => {}}); // More bootstrap modal requirements
|
||||
});
|
||||
|
||||
it('makes the right request', function(done) {
|
||||
this.fakes.stub(api, 'createRole').returns(Promise.resolve({data: {}}));
|
||||
const wrapper = setup();
|
||||
submitRoleForm(wrapper, 'new role');
|
||||
|
||||
then(() => {
|
||||
expect(api.createRole.calledWith('1000', 'new role')).to.be.true;
|
||||
}, done);
|
||||
});
|
||||
|
||||
// Un-xit me when https://github.com/influxdata/plutonium/issues/538 is resolved
|
||||
xit('adds the role to the page', function(done) {
|
||||
this.fakes.stub(api, 'createRole').returns(Promise.resolve({data: {}}));
|
||||
const startingRolesLen = rolesResponse.data.roles.length;
|
||||
const wrapper = setup();
|
||||
|
||||
submitRoleForm(wrapper, 'new role');
|
||||
|
||||
then(() => {
|
||||
expect(wrapper.find('.roles .panel').length).to.equal(startingRolesLen + 1);
|
||||
expect(wrapper.find('.roles .panel').at(startingRolesLen).text()).to.match(/new role/);
|
||||
}, done);
|
||||
});
|
||||
});
|
||||
});
|
||||
/* eslint-enable */
|
|
@ -1,150 +0,0 @@
|
|||
/* eslint-disable */
|
||||
import React from 'react';
|
||||
import {mount} from 'enzyme';
|
||||
import sinon from 'sinon';
|
||||
import * as api from 'src/shared/apis';
|
||||
|
||||
import {ClusterAccountContainer} from 'src/cluster_accounts/containers/ClusterAccountContainer';
|
||||
import RolePanels from 'src/shared/components/RolePanels';
|
||||
// import {Tab, TabList} from 'src/shared/components/Tabs';
|
||||
|
||||
const clusterID = '1000';
|
||||
const accountID = 'nedstark';
|
||||
|
||||
const rolesResponse = {
|
||||
data: {
|
||||
roles: [
|
||||
{
|
||||
name: "Role1",
|
||||
permissions: {
|
||||
"": [
|
||||
"ViewAdmin",
|
||||
"CreateDatabase",
|
||||
],
|
||||
},
|
||||
users: [
|
||||
"will",
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Role2",
|
||||
permissions: {
|
||||
db1: [
|
||||
"Monitor",
|
||||
"CopyShard",
|
||||
],
|
||||
},
|
||||
users: [
|
||||
"will",
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Role3",
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
const clusterAccountResponse = {
|
||||
data: {
|
||||
users: [
|
||||
{
|
||||
name: "will",
|
||||
hash: "xxxx",
|
||||
permissions: {
|
||||
"": [
|
||||
"ViewAdmin",
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
function setup(customProps = {}) {
|
||||
const props = Object.assign({}, {
|
||||
params: {
|
||||
clusterID,
|
||||
accountID,
|
||||
},
|
||||
router: {
|
||||
push: sinon.spy(),
|
||||
},
|
||||
addFlashMessage() {},
|
||||
dataNodes: ['localhost:8086'],
|
||||
}, customProps);
|
||||
return mount(<ClusterAccountContainer {...props} />);
|
||||
}
|
||||
|
||||
xdescribe('Cluster Account page', function() {
|
||||
beforeEach(function() {
|
||||
this.fakes = sinon.collection;
|
||||
this.fakes.stub(api, 'getClusterAccount').returns(Promise.resolve(clusterAccountResponse));
|
||||
this.fakes.stub(api, 'getRoles').returns(Promise.resolve(rolesResponse));
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
this.fakes.restore();
|
||||
});
|
||||
|
||||
describe('Roles tab', function() {
|
||||
it('renders a list of roles', function(done) {
|
||||
const wrapper = setup();
|
||||
|
||||
then(() => {
|
||||
expect(wrapper.find(RolePanels).length).to.equal(1);
|
||||
}, done);
|
||||
});
|
||||
|
||||
describe('after confirming to remove a role from the cluster account', function() {
|
||||
beforeEach(function() {
|
||||
window.$ = sinon.stub().returns({ modal: () => {} }); // More bootstrap modal requirements
|
||||
this.fakes.stub(api, 'removeAccountsFromRole').returns(Promise.resolve({data: {}}));
|
||||
this.wrapper = setup();
|
||||
then(() => {
|
||||
this.wrapper.find(RolePanels).find('button[children="Remove"]').at(0).simulate('click');
|
||||
this.wrapper.find('#removeAccountFromRoleModal button[children="Remove"]').simulate('click');
|
||||
});
|
||||
});
|
||||
|
||||
it('makes the right request', function(done) {
|
||||
then(() => {
|
||||
expect(api.removeAccountsFromRole.called).to.be.true;
|
||||
expect(api.removeAccountsFromRole.calledWith(clusterID, 'Role1', [accountID])).to.be.true;
|
||||
}, done);
|
||||
});
|
||||
|
||||
it('removes the role from the page', function(done) {
|
||||
then(() => {
|
||||
expect(this.wrapper.find(RolePanels).text()).not.to.match(/Role1/);
|
||||
}, done);
|
||||
});
|
||||
});
|
||||
|
||||
describe('after choosing a role to add to a user', function() {
|
||||
beforeEach(function() {
|
||||
window.$ = sinon.stub().returns({ modal: () => {} }); // More bootstrap modal requirements
|
||||
this.fakes.stub(api, 'addAccountsToRole').returns(Promise.resolve({data: {}}));
|
||||
this.wrapper = setup();
|
||||
then(() => {
|
||||
this.wrapper.find('button[children="Add to Role"]').simulate('click');
|
||||
this.wrapper.find('#addRoleModal select').simulate('change', {target: {value: 'Role3'}});
|
||||
this.wrapper.find('#addRoleModal form').simulate('submit');
|
||||
});
|
||||
});
|
||||
|
||||
it('makes the right request', function(done) {
|
||||
then(() => {
|
||||
expect(api.addAccountsToRole.calledWith(clusterID, 'Role3', [accountID])).to.be.true;
|
||||
}, done);
|
||||
});
|
||||
|
||||
it('adds the role to the page', function(done) {
|
||||
then(() => {
|
||||
expect(this.wrapper.find(RolePanels).text()).to.match(/Role3/);
|
||||
}, done);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
/* eslint-enable */
|
|
@ -1,165 +0,0 @@
|
|||
/* eslint-disable */
|
||||
import React from 'react';
|
||||
import {mount} from 'enzyme';
|
||||
import sinon from 'sinon';
|
||||
import * as api from 'src/shared/apis';
|
||||
|
||||
import {ClusterAccountsPageContainer} from 'src/cluster_accounts/containers/ClusterAccountsPageContainer';
|
||||
|
||||
const clusterID = '1000';
|
||||
|
||||
const rolesResponse = {
|
||||
data: {
|
||||
roles: [
|
||||
{
|
||||
name: 'wills_role',
|
||||
permissions: {
|
||||
'': [
|
||||
'ViewAdmin',
|
||||
'CreateDatabase',
|
||||
],
|
||||
},
|
||||
users: [
|
||||
'will',
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'bobs_role',
|
||||
permissions: {
|
||||
db1: [
|
||||
'Monitor',
|
||||
'CopyShard',
|
||||
],
|
||||
},
|
||||
users: [
|
||||
'bob',
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
const clusterAccountsResponse = {
|
||||
data: {
|
||||
users: [
|
||||
// cluster account linked to current user should be unable to be deleted
|
||||
{
|
||||
name: 'will',
|
||||
hash: 'xxxx',
|
||||
permissions: {
|
||||
'': [
|
||||
'ViewAdmin',
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "bob",
|
||||
hash: "xxxx",
|
||||
permissions: {
|
||||
'': [
|
||||
'ViewAdmin',
|
||||
'ViewChronograf',
|
||||
]
|
||||
}
|
||||
},
|
||||
// No permissions, no roles
|
||||
{
|
||||
name: "alice",
|
||||
hash: "xxxx",
|
||||
},
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
const meResponse = {
|
||||
data: {
|
||||
id: 1,
|
||||
first_name: "will",
|
||||
last_name: "watkins",
|
||||
email: "will@influxdb.com",
|
||||
admin: true,
|
||||
cluster_links: [
|
||||
{
|
||||
id: 1,
|
||||
user_id: 1,
|
||||
cluster_id: "2525931939964385968",
|
||||
cluster_user: "will",
|
||||
created_at: "2016-08-22T22:56:28.347266007-07:00",
|
||||
updated_at: "2016-08-25T18:00:41.46349321-07:00"
|
||||
}
|
||||
],
|
||||
name: "will watkins"
|
||||
},
|
||||
};
|
||||
|
||||
function setup(customProps = {}) {
|
||||
const props = Object.assign({}, {
|
||||
params: {
|
||||
clusterID,
|
||||
},
|
||||
addFlashMessage() {},
|
||||
}, customProps);
|
||||
return mount(<ClusterAccountsPageContainer {...props} />);
|
||||
}
|
||||
|
||||
describe('Cluster Accounts page', function() {
|
||||
beforeEach(function() {
|
||||
this.fakes = sinon.collection;
|
||||
this.fakes.stub(api, 'getClusterAccounts').returns(Promise.resolve(clusterAccountsResponse));
|
||||
this.fakes.stub(api, 'getRoles').returns(Promise.resolve(rolesResponse));
|
||||
this.fakes.stub(api, 'meShow').returns(Promise.resolve(meResponse));
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
this.fakes.restore();
|
||||
});
|
||||
|
||||
it('renders a list of cluster accounts and their roles', function(done) {
|
||||
const wrapper = setup();
|
||||
|
||||
then(() => {
|
||||
expect(wrapper.find('[data-test="user-row"]').length).to.equal(clusterAccountsResponse.data.users.length);
|
||||
expect(wrapper.find('table').text()).to.match(/will/);
|
||||
expect(wrapper.find('table').text()).to.match(/wills_role/);
|
||||
}, done);
|
||||
});
|
||||
|
||||
describe('after creating a new cluster account', function() {
|
||||
beforeEach(function() {
|
||||
this.wrapper = setup();
|
||||
window.$ = sinon.stub().returns({ modal: () => {} }); // More bootstrap modal requirements
|
||||
this.fakes.stub(api, 'createClusterAccount').returns(Promise.resolve({}));
|
||||
this.fakes.stub(api, 'addUsersToRole').returns(Promise.resolve({}));
|
||||
|
||||
then(() => {
|
||||
this.wrapper.find('[data-test="create-cluster-account"]').simulate('click');
|
||||
this.wrapper.find('[data-test="account-name"]').node.value = 'new_user';
|
||||
this.wrapper.find('[data-test="account-password"]').node.value = 'password';
|
||||
this.wrapper.find('[data-test="cluster-account-form"]').simulate('submit');
|
||||
});
|
||||
});
|
||||
|
||||
it('makes the right request', function(done) {
|
||||
then(() => {
|
||||
expect(api.createClusterAccount.calledWith(clusterID, 'new_user', 'password')).to.be.true;
|
||||
expect(api.addUsersToRole.calledWith(clusterID, 'wills_role', ['new_user'])).to.be.true;
|
||||
}, done);
|
||||
});
|
||||
|
||||
it('adds the cluster account to the table', function(done) {
|
||||
then(() => {
|
||||
expect(this.wrapper.find('[data-test="user-row"]').length).to.equal(clusterAccountsResponse.data.users.length + 1);
|
||||
}, done);
|
||||
});
|
||||
});
|
||||
|
||||
describe('after deleting a cluster account', function() {
|
||||
it('makes the right request');
|
||||
it('removes the cluster account from the table');
|
||||
});
|
||||
|
||||
describe('when the cluster account is linked to the current user', function() {
|
||||
it('disables the "Delete" control');
|
||||
});
|
||||
});
|
||||
/* eslint-enable */
|
|
@ -1,72 +0,0 @@
|
|||
import React from 'react';
|
||||
import {shallow, mount} from 'enzyme';
|
||||
import sinon from 'sinon';
|
||||
|
||||
import CreateRetentionPolicyModal from 'src/retention_policies/components/CreateRetentionPolicyModal';
|
||||
|
||||
const SHARD = {
|
||||
shardId: '1234',
|
||||
database: "db1",
|
||||
retentionPolicy: "rp1",
|
||||
shardGroup: '9',
|
||||
startTime: "2006-01-02T00:00:00Z",
|
||||
endTime: "2006-01-09T00:00:00Z",
|
||||
owners: [
|
||||
{id: "1", tcpAddr: "localhost:8088"},
|
||||
{id: "2", tcpAddr: "localhost:8188"},
|
||||
],
|
||||
};
|
||||
|
||||
function setup(customProps = {}) {
|
||||
const props = Object.assign({}, {
|
||||
onCreate: () => {},
|
||||
dataNodes: ['localhost:8086', 'localhost:8186'],
|
||||
}, customProps);
|
||||
return shallow(<CreateRetentionPolicyModal {...props} />);
|
||||
}
|
||||
|
||||
describe('RetentionPolicies.Components.CreateRetentionPolicyModal', function() {
|
||||
before(function() {
|
||||
// Allows us to test with things like `$(selector).modal('hide') in the code
|
||||
window.$ = sinon.stub().returns({
|
||||
modal: () => {},
|
||||
});
|
||||
});
|
||||
|
||||
it('renders a name input and label', function() {
|
||||
const wrapper = setup();
|
||||
expect(wrapper.find('input[type="text"]').length).to.equal(1);
|
||||
});
|
||||
|
||||
it('renders a dropdown for retention policy duration', function() {
|
||||
const wrapper = setup();
|
||||
expect(wrapper.find('select#replicationFactor').length).to.equal(1);
|
||||
});
|
||||
|
||||
it('renders a dropdown for replication factor', function() {
|
||||
const wrapper = setup();
|
||||
expect(wrapper.find('select#durationSelect').length).to.equal(1);
|
||||
});
|
||||
|
||||
describe('after filling out and submitting the form', function() {
|
||||
it('fires a callback with the correct arguments', function() {
|
||||
const wrapper = mount(
|
||||
<CreateRetentionPolicyModal
|
||||
onCreate={sinon.spy()}
|
||||
dataNodes={['localhost:8086', 'localhost:8188']}
|
||||
/>
|
||||
);
|
||||
|
||||
wrapper.find('input[type="text"]').node.value = 'my new rp';
|
||||
wrapper.find('select#durationSelect').node.value = '7d';
|
||||
wrapper.find('select#replicationFactor').node.value = '2';
|
||||
wrapper.find('form').simulate('submit', { preventDefault() {} });
|
||||
|
||||
expect(wrapper.props().onCreate).to.have.been.calledWith({
|
||||
rpName: 'my new rp',
|
||||
duration: '7d',
|
||||
replicationFactor: '2',
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,54 +0,0 @@
|
|||
import React from 'react';
|
||||
import {renderIntoDocument, Simulate} from 'react-addons-test-utils';
|
||||
import {findDOMNode} from 'react-dom';
|
||||
import sinon from 'sinon';
|
||||
import RetentionPoliciesHeader from 'src/retention_policies/components/RetentionPoliciesHeader';
|
||||
|
||||
describe('RetentionPolicies.Components.RetentionPoliciesHeader', () => {
|
||||
it('renders the currently selected database', () => {
|
||||
const component = renderIntoDocument(
|
||||
<RetentionPoliciesHeader
|
||||
databases={['db1', 'db2']}
|
||||
selectedDatabase={'db1'}
|
||||
onChooseDatabase={() => {}}
|
||||
/>
|
||||
);
|
||||
|
||||
const node = findDOMNode(component).querySelectorAll('.dropdown-toggle')[0];
|
||||
|
||||
expect(node.textContent).to.equal('db1');
|
||||
});
|
||||
|
||||
it('renders a dropdown list of all databases', () => {
|
||||
const component = renderIntoDocument(
|
||||
<RetentionPoliciesHeader
|
||||
databases={['db1', 'db2']}
|
||||
selectedDatabase={'db1'}
|
||||
onChooseDatabase={() => {}}
|
||||
/>
|
||||
);
|
||||
|
||||
const dropdownItems = findDOMNode(component).querySelectorAll('.dropdown-menu li');
|
||||
|
||||
expect(dropdownItems[0].textContent).to.equal('db1');
|
||||
expect(dropdownItems[1].textContent).to.equal('db2');
|
||||
});
|
||||
|
||||
describe('when a database is selected', () => {
|
||||
it('fires a callback', () => {
|
||||
const onChooseDatabaseCallback = sinon.spy();
|
||||
|
||||
const component = renderIntoDocument(
|
||||
<RetentionPoliciesHeader
|
||||
databases={['db1', 'db2']}
|
||||
selectedDatabase={'db1'}
|
||||
onChooseDatabase={onChooseDatabaseCallback}
|
||||
/>
|
||||
);
|
||||
|
||||
Simulate.click(findDOMNode(component).querySelectorAll('.dropdown-menu li')[0]);
|
||||
|
||||
expect(onChooseDatabaseCallback).to.have.been.calledWith('db1');
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,50 +0,0 @@
|
|||
import React from 'react';
|
||||
import {shallow} from 'enzyme';
|
||||
import RetentionPoliciesList from 'src/retention_policies/components/RetentionPoliciesList';
|
||||
import RetentionPolicyCard from 'src/retention_policies/components/RetentionPolicyCard';
|
||||
|
||||
function setup(customProps = {}) {
|
||||
const defaultProps = {
|
||||
retentionPolicies: [
|
||||
{name: "default", duration: "0", shardGroupDuration: "168h0m0s", replication: 2, isDefault: true},
|
||||
{name: "other", duration: "0", shardGroupDuration: "168h0m0s", replication: 2, isDefault: false},
|
||||
],
|
||||
shardDiskUsage: {
|
||||
1: [
|
||||
{diskUsage: 100, nodeID: "localhost:8088"},
|
||||
{diskUsage: 100, nodeID: "localhost:8188"},
|
||||
],
|
||||
2: [
|
||||
{diskUsage: 100, nodeID: "localhost:8088"},
|
||||
{diskUsage: 100, nodeID: "localhost:8188"},
|
||||
]
|
||||
},
|
||||
shards: {
|
||||
'db1..default': [
|
||||
{shardId: '1', database: "stress", retentionPolicy: "default", shardGroup: '9', startTime: "2006-01-02T00:00:00Z", endTime: "2006-01-09T00:00:00Z", owners: [1, 2]},
|
||||
],
|
||||
'db1..other': [
|
||||
{shardId: '2', database: "stress", retentionPolicy: "default", shardGroup: '9', startTime: "2006-01-02T00:00:00Z", endTime: "2006-01-09T00:00:00Z", owners: [1, 2]},
|
||||
]
|
||||
},
|
||||
onDropShard: () => {},
|
||||
selectedDatabase: 'db1',
|
||||
};
|
||||
const props = Object.assign({}, defaultProps, customProps);
|
||||
return shallow(<RetentionPoliciesList {...props} />);
|
||||
}
|
||||
|
||||
describe('RetentionPolicies.Components.RetentionPoliciesList', () => {
|
||||
it('renders a RetentionPolicyCard for each retention policy', () => {
|
||||
const wrapper = setup();
|
||||
const cards = wrapper.find(RetentionPolicyCard);
|
||||
|
||||
expect(cards.length).to.equal(2);
|
||||
});
|
||||
|
||||
describe('with no shard disk usage data', function() {
|
||||
it('doesn\'t throw', function() {
|
||||
expect(setup.bind(this, {shardDiskUsage: {}})).not.to.throw();
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,123 +0,0 @@
|
|||
import React from 'react';
|
||||
import {mount} from 'enzyme';
|
||||
import sinon from 'sinon';
|
||||
|
||||
import RetentionPolicyCard from 'src/retention_policies/components/RetentionPolicyCard';
|
||||
|
||||
const SHARD = {
|
||||
shardId: '1234',
|
||||
database: "db1",
|
||||
retentionPolicy: "rp1",
|
||||
shardGroup: '9',
|
||||
startTime: "2006-01-02T00:00:00Z",
|
||||
endTime: "2006-01-09T00:00:00Z",
|
||||
owners: [
|
||||
{id: "1", tcpAddr: "localhost:8088"},
|
||||
{id: "2", tcpAddr: "localhost:8188"},
|
||||
],
|
||||
};
|
||||
|
||||
function setup(customProps = {}) {
|
||||
const defaultProps = {
|
||||
rp: {
|
||||
name: "rp1",
|
||||
duration: "0",
|
||||
shardGroupDuration: "168h0m0s",
|
||||
replication: 2,
|
||||
isDefault: true
|
||||
},
|
||||
shards: [SHARD],
|
||||
shardDiskUsage: {
|
||||
1234: [
|
||||
{diskUsage: 100, nodeID: "localhost:8088"},
|
||||
{diskUsage: 200, nodeID: "localhost:8188"},
|
||||
],
|
||||
},
|
||||
index: 0,
|
||||
onDropShard: () => {},
|
||||
};
|
||||
|
||||
const props = Object.assign({}, defaultProps, customProps);
|
||||
|
||||
return mount(<RetentionPolicyCard {...props} />);
|
||||
}
|
||||
|
||||
describe('RetentionPolicies.Components.RetentionPolicyCard', function() {
|
||||
before(function() {
|
||||
// Allows us to test with things like `$(selector).modal('hide') in the code
|
||||
window.$ = sinon.stub().returns({
|
||||
on: () => {},
|
||||
modal: () => {},
|
||||
});
|
||||
});
|
||||
|
||||
it('renders the retention policy name, total disk usage, and if it\'s the default', function() {
|
||||
const wrapper = setup();
|
||||
|
||||
const header = wrapper.find('.js-rp-card-header');
|
||||
|
||||
expect(header.text()).to.match(/rp1/);
|
||||
expect(header.text()).to.match(/300 Bytes/);
|
||||
expect(header.text()).to.match(/Default/);
|
||||
});
|
||||
|
||||
it('renders a row for each shard', function() {
|
||||
const wrapper = setup();
|
||||
|
||||
const shards = wrapper.find('tbody tr');
|
||||
|
||||
expect(shards.length).to.equal(1);
|
||||
});
|
||||
|
||||
it('renders the shard ID', function() {
|
||||
const wrapper = setup();
|
||||
|
||||
const shards = wrapper.find('tbody tr');
|
||||
|
||||
expect(shards.text()).to.match(/1234/);
|
||||
});
|
||||
|
||||
it('renders the addresses of all nodes that the shard belongs to', function() {
|
||||
const wrapper = setup();
|
||||
|
||||
const shards = wrapper.find('tbody tr');
|
||||
|
||||
expect(shards.text()).to.match(/localhost:8088/);
|
||||
expect(shards.text()).to.match(/localhost:8188/);
|
||||
})
|
||||
|
||||
it('renders disk usage for each node that a shard belongs to', function() {
|
||||
const wrapper = setup();
|
||||
|
||||
const shards = wrapper.find('tbody tr');
|
||||
|
||||
expect(shards.text()).to.match(/100 Bytes/);
|
||||
expect(shards.text()).to.match(/200 Bytes/);
|
||||
});
|
||||
|
||||
describe('clicking `Drop Shard`', function() {
|
||||
it('fires a callback', function() {
|
||||
const onDropShardSpy = sinon.spy();
|
||||
const wrapper = setup({onDropShard: onDropShardSpy});
|
||||
|
||||
// Because we're still using bootstrap to open modals, we can't test dropping shards
|
||||
// only using `Simulate` :(. I don't advocate this approach, we should try
|
||||
// to exercise components only via their 'public interface' -- aka the DOM.
|
||||
wrapper.setState({shardIdToDelete: SHARD.shardId});
|
||||
wrapper.find('input#confirmation').simulate('change', {target: {value: 'delete'}});
|
||||
wrapper.find('form').simulate('submit');
|
||||
|
||||
expect(onDropShardSpy).to.have.been.calledWith(SHARD);
|
||||
});
|
||||
|
||||
it('fails to submit unless "delete" is entered into the input', function() {
|
||||
const onDropShardSpy = sinon.spy();
|
||||
const wrapper = setup({onDropShard: onDropShardSpy});
|
||||
|
||||
wrapper.setState({shardIdToDelete: SHARD.shardId});
|
||||
wrapper.find('form').simulate('submit');
|
||||
|
||||
expect(onDropShardSpy).not.to.have.been.called;
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,43 +0,0 @@
|
|||
import React from 'react';
|
||||
import TestUtils, {renderIntoDocument} from 'react-addons-test-utils';
|
||||
import {findDOMNode} from 'react-dom';
|
||||
import sinon from 'sinon';
|
||||
|
||||
import RetentionPoliciesApp from 'src/retention_policies/containers/RetentionPoliciesApp';
|
||||
|
||||
xdescribe('RetentionPolicies.Containers.RetentionPoliciesApp', () => {
|
||||
let server;
|
||||
before(() => { server = sinon.fakeServer.create(); });
|
||||
after(() => { server.restore() });
|
||||
|
||||
let component;
|
||||
beforeEach(() => {
|
||||
server.respondWith("GET", "/proxy?proxy_url=http%3A%2F%2Flocalhost%3A8086%2Fquery%3Fepoch%3Dms%26q%3DSHOW%20DATABASES",
|
||||
[200, { "Content-Type": "application/json" },
|
||||
'{"results":[{"series":[{"name":"databases","columns":["name"],"values":[["_internal"],["hello"],["demo"],["asdf"]]}]}]}']);
|
||||
|
||||
server.respondWith("GET", "/proxy?proxy_url=http%3A%2F%2Flocalhost%3A8086%2Fquery%3Fepoch%3Dms%26q%3DSHOW%20RETENTION%20POLICIES%20ON%20%22_internal%22",
|
||||
[200, { "Content-Type": "application/json" },
|
||||
'{"results":[{"series":[{"columns":["name","duration","shardGroupDuration","replicaN","default"],"values":[["monitor","168h0m0s","24h0m0s",2,true],["asdf","24h0m0s","1h0m0s",1,false]]}]}]}']);
|
||||
|
||||
server.respondWith("GET", "/proxy?proxy_url=http%3A%2F%2Flocalhost%3A8086%2Fquery%3Fepoch%3Dms%26q%3DSELECT%20last(diskBytes)%20FROM%20%22shard%22%20WHERE%20%22database%22%3D%27_internal%27%20AND%20clusterID%100%27%20GROUP%20BY%20nodeID%2C%20path%2C%20retentionPolicy%26db%3D_internal",
|
||||
[200, { "Content-Type": "application/json" },
|
||||
'{"results":[{"series":[{"name":"shard","tags":{"nodeID":"localhost:8088","path":"/Users/will/.influxdb/data/_internal/monitor/15","retentionPolicy":"monitor"},"columns":["time","last"],"values":[[1469068381000000000,1036740]]}]},{"series":[{"name":"shard","tags":{"nodeID":"localhost:8088","path":"/Users/will/.influxdb/data/_internal/monitor/16","retentionPolicy":"monitor"},"columns":["time","last"],"values":[[1469068381000000000,8771759]]}]}]}']);
|
||||
|
||||
server.respondWith("GET", "/api/int/v1/clusters/show-shards",
|
||||
[200, { "Content-Type": "application/json" },
|
||||
'[{"id": "1", "database": "_internal", "retention-policy": "monitor", "replica-n": 2, "shard-group-id": "1", "start-time": "2016-07-15T00:00:00Z", "end-time": "2016-07-16T00:00:00Z", "expire-time": "2016-07-23T00:00:00Z", "truncated-at": "0001-01-01T00:00:00Z", "owners": [ { "id": "2", "tcpAddr": "localhost:8088" } ] }, { "id": "2", "database": "_internal", "retention-policy": "monitor", "replica-n": 2, "shard-group-id": "2", "start-time": "2016-07-16T00:00:00Z", "end-time": "2016-07-17T00:00:00Z", "expire-time": "2016-07-24T00:00:00Z", "truncated-at": "0001-01-01T00:00:00Z", "owners": [] } ]']);
|
||||
|
||||
component = renderIntoDocument(
|
||||
<RetentionPoliciesApp dataNodes={['localhost:8086']} params={{clusterID: '100'}} addFlashMessage={() => {}} />
|
||||
);
|
||||
});
|
||||
|
||||
it('fetches all databases in a cluster', (done) => {
|
||||
server.respond();
|
||||
setTimeout(() => {
|
||||
expect(server.requests[0].url).to.match(/SHOW%20DATABASES/);
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue