Skip to content
This repository was archived by the owner on May 5, 2021. It is now read-only.

Commit bd1521c

Browse files
author
Jacob Peddicord
committed
Implement Selenium tests for ACLs
1 parent 621f92d commit bd1521c

File tree

3 files changed

+132
-10
lines changed

3 files changed

+132
-10
lines changed

browser/components/projects/acl/ProjectAclEditor.tsx

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import { connect } from 'react-redux';
1717
import { Link } from 'react-router-dom';
1818

1919
import { AccessLevel, AccessLevelStrength, WebProject } from '../../../../server/api/projects/interfaces';
20+
import history from '../../../history';
2021
import * as ProjectActions from '../../../modules/projects';
2122
import GroupSelect from './GroupSelect';
2223

@@ -72,7 +73,7 @@ class ProjectAclEditor extends React.Component<Props, State> {
7273
});
7374
}
7475

75-
save = (e) => {
76+
save = async (e) => {
7677
e.preventDefault();
7778
const { dispatch, project: { projectId } } = this.props;
7879
const { sortedAcl } = this.state;
@@ -82,18 +83,19 @@ class ProjectAclEditor extends React.Component<Props, State> {
8283
return acc;
8384
}, {});
8485

85-
dispatch(ProjectActions.patchProject(projectId, {
86+
await dispatch(ProjectActions.patchProject(projectId, {
8687
acl: newAcl,
8788
}));
89+
history.push(`/projects/${projectId}`);
8890
}
8991

9092
render() {
9193
const { groups } = this.props;
9294
const { sortedAcl } = this.state;
9395

94-
return <div>
96+
return <form onSubmit={this.save}>
9597
<h2>Manage project access</h2>
96-
<table className="table table-bordered">
98+
<table className="table table-bordered" id="project-acl-editor">
9799
<thead>
98100
<tr>
99101
<th style={{ width: '20%' }}>Permissions</th>
@@ -114,17 +116,17 @@ class ProjectAclEditor extends React.Component<Props, State> {
114116
</tbody>
115117
<tr>
116118
<td colSpan={3}>
117-
<button className="btn btn-secondary" onClick={this.addEntry}>
119+
<button type="button" id="acl-add" className="btn btn-secondary" onClick={this.addEntry}>
118120
<i className="fa fa-plus" /> Add
119121
</button>
120122
</td>
121123
</tr>
122124
</table>
123125

124-
<button className="btn btn-primary" onClick={this.save}>
126+
<button type="submit" className="btn btn-primary">
125127
Save
126128
</button>
127-
</div>;
129+
</form>;
128130
}
129131

130132
}
@@ -152,7 +154,7 @@ function AclRow(props: AclRowProps) {
152154
/>
153155
</td>
154156
<td>
155-
<button className="btn btn-secondary" onClick={props.onDelete}>
157+
<button type="button" className="btn btn-secondary" onClick={props.onDelete}>
156158
<i className="fa fa-times" />
157159
</button>
158160
</td>

browser/components/projects/editor/ProjectView.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,11 +112,11 @@ class ProjectView extends Component<Props, State> {
112112
return (
113113
<div className="pb-5">
114114
{project.access.level === 'owner' ?
115-
<div className="float-right text-muted small EditableText">
115+
<div id="acl-owner-info" className="float-right text-muted small EditableText">
116116
<Link to={`/projects/${project.projectId}/acl`}>owned by {this.getOwners()}</Link>
117117
</div>
118118
:
119-
<div className="float-right text-muted small">
119+
<div id="acl-owner-info" className="float-right text-muted small">
120120
owned by {this.getOwners()}
121121
</div>
122122
}

selenium/projects-auth.spec.ts

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
/* Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
*
3+
* Licensed under the Apache License, Version 2.0 (the "License").
4+
* You may not use this file except in compliance with the License.
5+
* A copy of the License is located at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* or in the "license" file accompanying this file. This file is distributed
10+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
11+
* express or implied. See the License for the specific language governing
12+
* permissions and limitations under the License.
13+
*/
14+
15+
import {By, Key, until} from 'selenium-webdriver';
16+
import build, { CustomDriver } from './driver';
17+
18+
const projectName = 'ACL Test ' + new Date().getTime();
19+
20+
describe('project authentication', function () {
21+
let driver: CustomDriver;
22+
beforeAll(async function () {
23+
driver = await build();
24+
await driver.manage().timeouts().implicitlyWait(1000);
25+
});
26+
afterAll(async function () {
27+
await driver.quit();
28+
});
29+
30+
it('bootstraps a project', async function () {
31+
driver.getRelative('/projects/new');
32+
driver.wait(until.elementLocated(By.id('onboarding-form')));
33+
34+
driver.findElement(By.id('title')).sendKeys(projectName);
35+
driver.findElement(By.id('version')).sendKeys('x');
36+
driver.findElement(By.id('description')).sendKeys('x');
37+
driver.findElement(By.css('input[name="openSourcing"][value="false"]')).click();
38+
driver.findElement(By.id('legalContact')).sendKeys('a-real-person');
39+
driver.findElement(By.id('plannedRelease')).sendKeys('1111-11-11');
40+
driver.findElement(By.css('#ownerGroup-container .Select-placeholder')).click();
41+
driver.findElement(
42+
By.xpath('//*[@id="ownerGroup-container"]//div[@class="Select-menu"]//div[text()="everyone"]')).click();
43+
44+
driver.findElement(By.css('form#onboarding-form button[type="submit"]')).click();
45+
46+
const headerText = await driver.findElement(By.id('project-heading')).getText();
47+
expect(headerText).toContain(projectName);
48+
});
49+
50+
it('can load the acl editor', async function () {
51+
driver.findElement(By.css('a[href$="/acl"]')).click();
52+
await driver.wait(until.elementLocated(By.id('project-acl-editor')));
53+
});
54+
55+
it('wont let a person disown a project', async function () {
56+
const input = driver.findElement(By.xpath('//form//tbody/tr[1]//input[@type="text"]'));
57+
input.clear();
58+
input.sendKeys('blah');
59+
driver.findElement(By.css('button[type="submit"]')).click();
60+
61+
driver.sleep(1000); // modal animation
62+
const errorText = await driver.findElement(By.css('#error-modal .modal-body')).getText();
63+
expect(errorText).toContain('cannot remove yourself');
64+
driver.findElement(By.css('#error-modal button.btn-primary')).click(); // close button
65+
driver.wait(until.elementIsNotVisible(driver.findElement(By.css('#error-modal'))));
66+
driver.sleep(1000); // modal animation
67+
68+
input.clear();
69+
await input.sendKeys('self:selenium');
70+
});
71+
72+
it('can add some friends to the list', async function () {
73+
driver.findElement(By.id('acl-add')).click();
74+
const select2 = driver.findElement(By.xpath('//form//tbody/tr[2]//select'));
75+
const input2 = driver.findElement(By.xpath('//form//tbody/tr[2]//input[@type="text"]'));
76+
select2.click();
77+
const select2editor = driver.findElement(By.xpath('//form//tbody/tr[2]//select/option[@value="editor"]'));
78+
select2editor.click();
79+
input2.sendKeys('self:fake-editor');
80+
81+
driver.findElement(By.id('acl-add')).click();
82+
const select3 = driver.findElement(By.xpath('//form//tbody/tr[3]//select'));
83+
const input3 = driver.findElement(By.xpath('//form//tbody/tr[3]//input[@type="text"]'));
84+
select3.click();
85+
const select3viewer = driver.findElement(By.xpath('//form//tbody/tr[3]//select/option[@value="viewer"]'));
86+
select3viewer.click();
87+
input3.sendKeys('self:fake-viewer');
88+
89+
await driver.findElement(By.css('button[type="submit"]')).click();
90+
});
91+
92+
it('cannot edit acl as editor', async function () {
93+
// switch users and return
94+
driver.wait(until.elementLocated(By.id('project-heading')));
95+
const projectUrl = await driver.getCurrentUrl();
96+
driver.setUser('fake-editor');
97+
await driver.get(projectUrl);
98+
99+
// ensure the acl link isn't clickable
100+
const info = driver.findElement(By.id('acl-owner-info'));
101+
const classes = await info.getAttribute('class');
102+
const text = await info.getText();
103+
expect(classes).not.toContain('EditableText');
104+
expect(text).toContain('owned by');
105+
106+
// but that main project details still are
107+
await driver.findElement(By.css('#project-heading .EditableText'));
108+
});
109+
110+
it('cannot edit project as viewer', async function () {
111+
const projectUrl = await driver.getCurrentUrl();
112+
driver.setUser('fake-viewer');
113+
await driver.get(projectUrl);
114+
115+
// nothing should be editable
116+
const numEditable = await driver.findElements(By.className('EditableText'));
117+
expect(numEditable.length).toEqual(0);
118+
});
119+
120+
});

0 commit comments

Comments
 (0)