Commit a188ceac by Peter Holmberg

invitees

parent 3c8820ab
......@@ -5,7 +5,6 @@ import OrgActionBar, { Props } from './OrgActionBar';
const setup = (propOverrides?: object) => {
const props: Props = {
searchQuery: '',
showLayoutMode: true,
setSearchQuery: jest.fn(),
linkButton: { href: 'some/url', title: 'test' },
};
......
import React from 'react';
import { shallow } from 'enzyme';
import InviteesTable, { Props } from './InviteesTable';
import { Invitee } from 'app/types';
import { getMockInvitees } from './__mocks__/userMocks';
const setup = (propOverrides?: object) => {
const props: Props = {
invitees: [] as Invitee[],
revokeInvite: jest.fn(),
};
Object.assign(props, propOverrides);
return shallow(<InviteesTable {...props} />);
};
describe('Render', () => {
it('should render component', () => {
const wrapper = setup();
expect(wrapper).toMatchSnapshot();
});
it('should render invitees', () => {
const wrapper = setup({
invitees: getMockInvitees(5),
});
expect(wrapper).toMatchSnapshot();
});
});
......@@ -7,10 +7,10 @@ export interface Props {
}
export default class InviteesTable extends PureComponent<Props> {
private copyRef = createRef<HTMLTextAreaElement>();
private copyUrlRef = createRef<HTMLTextAreaElement>();
copyToClipboard = () => {
const node = this.copyRef.current;
const node = this.copyUrlRef.current;
if (node) {
node.select();
......@@ -39,7 +39,12 @@ export default class InviteesTable extends PureComponent<Props> {
<td>{invitee.name}</td>
<td className="text-right">
<button className="btn btn-inverse btn-mini" onClick={this.copyToClipboard}>
<textarea readOnly={true} value={invitee.url} style={{ display: 'none' }} ref={this.copyRef} />
<textarea
readOnly={true}
value={invitee.url}
style={{ position: 'absolute', right: -1000 }}
ref={this.copyUrlRef}
/>
<i className="fa fa-clipboard" /> Copy Invite
</button>
&nbsp;
......
import React from 'react';
import { shallow } from 'enzyme';
import { UsersActionBar, Props } from './UsersActionBar';
const setup = (propOverrides?: object) => {
const props: Props = {
searchQuery: '',
setUsersSearchQuery: jest.fn(),
showInvites: false,
pendingInvitesCount: 0,
canInvite: false,
externalUserMngLinkUrl: '',
externalUserMngLinkName: '',
};
Object.assign(props, propOverrides);
return shallow(<UsersActionBar {...props} />);
};
describe('Render', () => {
it('should render component', () => {
const wrapper = setup();
expect(wrapper).toMatchSnapshot();
});
it('should render pending invites button', () => {
const wrapper = setup({
pendingInvitesCount: 5,
});
expect(wrapper).toMatchSnapshot();
});
it('should show invite button', () => {
const wrapper = setup({
canInvite: true,
});
expect(wrapper).toMatchSnapshot();
});
it('should show external user management button', () => {
const wrapper = setup({
externalUserMngLinkUrl: 'some/url',
});
expect(wrapper).toMatchSnapshot();
});
});
import React from 'react';
import { shallow } from 'enzyme';
import { UsersListPage, Props } from './UsersListPage';
import { NavModel, User } from 'app/types';
import { Invitee, NavModel, User } from 'app/types';
import { getMockUser } from './__mocks__/userMocks';
import appEvents from '../../core/app_events';
......@@ -13,7 +13,11 @@ const setup = (propOverrides?: object) => {
const props: Props = {
navModel: {} as NavModel,
users: [] as User[],
invitees: [] as Invitee[],
searchQuery: '',
externalUserMngInfo: '',
revokeInvite: jest.fn(),
loadInvitees: jest.fn(),
loadUsers: jest.fn(),
updateUser: jest.fn(),
removeUser: jest.fn(),
......
......@@ -29,3 +29,28 @@ export const getMockUser = () => {
userId: 2,
};
};
export const getMockInvitees = (amount: number) => {
const invitees = [];
for (let i = 0; i <= amount; i++) {
invitees.push({
code: `asdfasdfsadf-${i}`,
createdOn: '2018-10-02',
email: `invitee-${i}@test.com`,
emailSent: true,
emailSentOn: '2018-10-02',
id: i,
invitedByEmail: 'admin@grafana.com',
invitedByLogin: 'admin',
invitedByName: 'admin',
name: `invitee-${i}`,
orgId: 1,
role: 'viewer',
status: 'not accepted',
url: `localhost/invite/$${i}`,
});
}
return invitees;
};
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Render should render component 1`] = `
<table
className="filter-table form-inline"
>
<thead>
<tr>
<th>
Email
</th>
<th>
Name
</th>
<th />
<th
style={
Object {
"width": "34px",
}
}
/>
</tr>
</thead>
<tbody />
</table>
`;
exports[`Render should render invitees 1`] = `
<table
className="filter-table form-inline"
>
<thead>
<tr>
<th>
Email
</th>
<th>
Name
</th>
<th />
<th
style={
Object {
"width": "34px",
}
}
/>
</tr>
</thead>
<tbody>
<tr
key="0-0"
>
<td>
invitee-0@test.com
</td>
<td>
invitee-0
</td>
<td
className="text-right"
>
<button
className="btn btn-inverse btn-mini"
onClick={[Function]}
>
<textarea
readOnly={true}
style={
Object {
"position": "absolute",
"right": -1000,
}
}
value="localhost/invite/$0"
/>
<i
className="fa fa-clipboard"
/>
Copy Invite
</button>
 
</td>
<td>
<button
className="btn btn-danger btn-mini"
onClick={[Function]}
>
<i
className="fa fa-remove"
/>
</button>
</td>
</tr>
<tr
key="1-1"
>
<td>
invitee-1@test.com
</td>
<td>
invitee-1
</td>
<td
className="text-right"
>
<button
className="btn btn-inverse btn-mini"
onClick={[Function]}
>
<textarea
readOnly={true}
style={
Object {
"position": "absolute",
"right": -1000,
}
}
value="localhost/invite/$1"
/>
<i
className="fa fa-clipboard"
/>
Copy Invite
</button>
 
</td>
<td>
<button
className="btn btn-danger btn-mini"
onClick={[Function]}
>
<i
className="fa fa-remove"
/>
</button>
</td>
</tr>
<tr
key="2-2"
>
<td>
invitee-2@test.com
</td>
<td>
invitee-2
</td>
<td
className="text-right"
>
<button
className="btn btn-inverse btn-mini"
onClick={[Function]}
>
<textarea
readOnly={true}
style={
Object {
"position": "absolute",
"right": -1000,
}
}
value="localhost/invite/$2"
/>
<i
className="fa fa-clipboard"
/>
Copy Invite
</button>
 
</td>
<td>
<button
className="btn btn-danger btn-mini"
onClick={[Function]}
>
<i
className="fa fa-remove"
/>
</button>
</td>
</tr>
<tr
key="3-3"
>
<td>
invitee-3@test.com
</td>
<td>
invitee-3
</td>
<td
className="text-right"
>
<button
className="btn btn-inverse btn-mini"
onClick={[Function]}
>
<textarea
readOnly={true}
style={
Object {
"position": "absolute",
"right": -1000,
}
}
value="localhost/invite/$3"
/>
<i
className="fa fa-clipboard"
/>
Copy Invite
</button>
 
</td>
<td>
<button
className="btn btn-danger btn-mini"
onClick={[Function]}
>
<i
className="fa fa-remove"
/>
</button>
</td>
</tr>
<tr
key="4-4"
>
<td>
invitee-4@test.com
</td>
<td>
invitee-4
</td>
<td
className="text-right"
>
<button
className="btn btn-inverse btn-mini"
onClick={[Function]}
>
<textarea
readOnly={true}
style={
Object {
"position": "absolute",
"right": -1000,
}
}
value="localhost/invite/$4"
/>
<i
className="fa fa-clipboard"
/>
Copy Invite
</button>
 
</td>
<td>
<button
className="btn btn-danger btn-mini"
onClick={[Function]}
>
<i
className="fa fa-remove"
/>
</button>
</td>
</tr>
<tr
key="5-5"
>
<td>
invitee-5@test.com
</td>
<td>
invitee-5
</td>
<td
className="text-right"
>
<button
className="btn btn-inverse btn-mini"
onClick={[Function]}
>
<textarea
readOnly={true}
style={
Object {
"position": "absolute",
"right": -1000,
}
}
value="localhost/invite/$5"
/>
<i
className="fa fa-clipboard"
/>
Copy Invite
</button>
 
</td>
<td>
<button
className="btn btn-danger btn-mini"
onClick={[Function]}
>
<i
className="fa fa-remove"
/>
</button>
</td>
</tr>
</tbody>
</table>
`;
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Render should render component 1`] = `
<div
className="page-action-bar"
>
<div
className="gf-form gf-form--grow"
>
<label
className="gf-form--has-input-icon"
>
<input
className="gf-form-input width-20"
onChange={[Function]}
placeholder="Filter by name or type"
type="text"
value=""
/>
<i
className="gf-form-input-icon fa fa-search"
/>
</label>
<div
className="page-action-bar__spacer"
/>
</div>
</div>
`;
exports[`Render should render pending invites button 1`] = `
<div
className="page-action-bar"
>
<div
className="gf-form gf-form--grow"
>
<label
className="gf-form--has-input-icon"
>
<input
className="gf-form-input width-20"
onChange={[Function]}
placeholder="Filter by name or type"
type="text"
value=""
/>
<i
className="gf-form-input-icon fa fa-search"
/>
</label>
<div
className="page-action-bar__spacer"
/>
<button
className="btn btn-inverse"
onClick={false}
>
Pending Invites (
5
)
</button>
</div>
</div>
`;
exports[`Render should show external user management button 1`] = `
<div
className="page-action-bar"
>
<div
className="gf-form gf-form--grow"
>
<label
className="gf-form--has-input-icon"
>
<input
className="gf-form-input width-20"
onChange={[Function]}
placeholder="Filter by name or type"
type="text"
value=""
/>
<i
className="gf-form-input-icon fa fa-search"
/>
</label>
<div
className="page-action-bar__spacer"
/>
<a
className="btn btn-success"
href="some/url"
target="_blank"
>
<i
className="fa fa-external-link-square"
/>
</a>
</div>
</div>
`;
exports[`Render should show invite button 1`] = `
<div
className="page-action-bar"
>
<div
className="gf-form gf-form--grow"
>
<label
className="gf-form--has-input-icon"
>
<input
className="gf-form-input width-20"
onChange={[Function]}
placeholder="Filter by name or type"
type="text"
value=""
/>
<i
className="gf-form-input-icon fa fa-search"
/>
</label>
<div
className="page-action-bar__spacer"
/>
<a
className="btn btn-success"
href="org/users/invite"
>
<i
className="fa fa-plus"
/>
<span>
Invite
</span>
</a>
</div>
</div>
`;
......@@ -8,16 +8,8 @@ exports[`Render should render component 1`] = `
<div
className="page-container page-body"
>
<OrgActionBar
linkButton={
Object {
"href": "/org/users/add",
"title": "Add user",
}
}
searchQuery=""
setSearchQuery={[MockFunction]}
showLayoutMode={false}
<Connect(UsersActionBar)
showInvites={[Function]}
/>
<UsersTable
onRemoveUser={[Function]}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment