Skip to content

Commit 1ae25b3

Browse files
authored
Merge pull request #1120 from andypols/fix-display-repo-add-errors
fix: display errors when adding a new repo
2 parents be77bbb + 4d3995f commit 1ae25b3

File tree

10 files changed

+200
-102
lines changed

10 files changed

+200
-102
lines changed

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ npm-debug.log*
1010
yarn-debug.log*
1111
yarn-error.log*
1212
lerna-debug.log*
13-
package-lock.json
1413

1514

1615
# Diagnostic reports (https://nodejs.org/api/report.html)

cypress/e2e/repo.cy.js

Lines changed: 143 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,82 +1,156 @@
11
describe('Repo', () => {
2-
let repoName;
3-
let cloneURL;
4-
let csrfToken;
52
let cookies;
6-
let repoId;
3+
let repoName;
4+
5+
describe('Anonymous users', () => {
6+
beforeEach(() => {
7+
cy.visit('/dashboard/repo');
8+
});
9+
10+
it('Prevents anonymous users from adding repos', () => {
11+
cy.get('[data-testid="repo-list-view"]')
12+
.find('[data-testid="add-repo-button"]')
13+
.should('not.exist');
14+
});
15+
});
716

8-
before(() => {
9-
cy.login('admin', 'admin');
17+
describe('Regular users', () => {
18+
beforeEach(() => {
19+
cy.login('user', 'user');
1020

11-
// Create a new repo
12-
cy.getCSRFToken().then((csrfToken) => {
21+
cy.visit('/dashboard/repo');
22+
});
23+
24+
after(() => {
25+
cy.logout();
26+
});
27+
28+
it('Prevents regular users from adding repos', () => {
29+
cy.get('[data-testid="repo-list-view"]')
30+
.find('[data-testid="add-repo-button"]')
31+
.should('not.exist');
32+
});
33+
});
34+
35+
describe('Admin users', () => {
36+
beforeEach(() => {
37+
cy.login('admin', 'admin');
38+
39+
cy.visit('/dashboard/repo');
40+
});
41+
42+
it('Admin users can add repos', () => {
1343
repoName = `${Date.now()}`;
14-
cloneURL = `http://localhost:8000/github.com/cypress-test/${repoName}.git`;
15-
16-
cy.request({
17-
method: 'POST',
18-
url: 'http://localhost:8080/api/v1/repo',
19-
body: {
20-
project: 'cypress-test',
21-
name: repoName,
22-
url: `https://github.com/cypress-test/${repoName}.git`,
23-
},
24-
headers: {
25-
cookie: cookies?.join('; ') || '',
26-
'X-CSRF-TOKEN': csrfToken,
27-
},
28-
}).then((res) => {
29-
expect(res.status).to.eq(200);
30-
repoId = res.body._id;
44+
45+
cy.get('[data-testid="repo-list-view"]').find('[data-testid="add-repo-button"]').click();
46+
47+
cy.get('[data-testid="add-repo-dialog"]').within(() => {
48+
cy.get('[data-testid="repo-project-input"]').type('cypress-test');
49+
cy.get('[data-testid="repo-name-input"]').type(repoName);
50+
cy.get('[data-testid="repo-url-input"]').type(
51+
`https://github.com/cypress-test/${repoName}.git`,
52+
);
53+
cy.get('[data-testid="add-repo-button"]').click();
3154
});
55+
56+
cy.contains('a', `cypress-test/${repoName}`, { timeout: 10000 }).click();
57+
58+
// cy.get('[data-testid="delete-repo-button"]').click();
3259
});
33-
});
3460

35-
it('Opens tooltip with correct content and can copy', () => {
36-
cy.visit('/dashboard/repo');
37-
cy.on('uncaught:exception', () => false);
38-
39-
const tooltipQuery = 'div[role="tooltip"]';
40-
41-
// Check the tooltip isn't open to start with
42-
cy.get(tooltipQuery).should('not.exist');
43-
44-
// Find the repo's Code button and click it
45-
cy.get(`a[href="/dashboard/repo/${repoId}"]`)
46-
.closest('tr')
47-
.find('span')
48-
.contains('Code')
49-
.should('exist')
50-
.click();
51-
52-
// Check tooltip is open and contains the correct clone URL
53-
cy.get(tooltipQuery)
54-
.should('exist')
55-
.find('span')
56-
.contains(cloneURL)
57-
.should('exist')
58-
.parent()
59-
.find('span')
60-
.next()
61-
.get('svg.octicon-copy')
62-
.should('exist')
63-
.click()
64-
.get('svg.octicon-copy')
65-
.should('not.exist')
66-
.get('svg.octicon-check')
67-
.should('exist');
61+
it('Displays an error when adding an existing repo', () => {
62+
cy.get('[data-testid="repo-list-view"]').find('[data-testid="add-repo-button"]').click();
63+
64+
cy.get('[data-testid="add-repo-dialog"]').within(() => {
65+
cy.get('[data-testid="repo-project-input"]').type('finos');
66+
cy.get('[data-testid="repo-name-input"]').type('git-proxy');
67+
cy.get('[data-testid="repo-url-input"]').type('https://github.com/finos/git-proxy.git');
68+
cy.get('[data-testid="add-repo-button"]').click();
69+
});
70+
71+
cy.get('[data-testid="repo-error"]')
72+
.should('be.visible')
73+
.and('contain.text', 'Repository https://github.com/finos/git-proxy.git already exists!');
74+
});
6875
});
6976

70-
after(() => {
71-
// Delete the repo
72-
cy.getCSRFToken().then((csrfToken) => {
73-
cy.request({
74-
method: 'DELETE',
75-
url: `http://localhost:8080/api/v1/repo/${repoName}/delete`,
76-
headers: {
77-
cookie: cookies?.join('; ') || '',
78-
'X-CSRF-TOKEN': csrfToken,
79-
},
77+
describe('Existing repo', () => {
78+
let cloneURL;
79+
let repoId;
80+
81+
before(() => {
82+
cy.login('admin', 'admin');
83+
84+
// Create a new repo
85+
cy.getCSRFToken().then((csrfToken) => {
86+
repoName = `${Date.now()}`;
87+
cloneURL = `http://localhost:8000/github.com/cypress-test/${repoName}.git`;
88+
89+
cy.request({
90+
method: 'POST',
91+
url: 'http://localhost:8080/api/v1/repo',
92+
body: {
93+
project: 'cypress-test',
94+
name: repoName,
95+
url: `https://github.com/cypress-test/${repoName}.git`,
96+
},
97+
headers: {
98+
cookie: cookies?.join('; ') || '',
99+
'X-CSRF-TOKEN': csrfToken,
100+
},
101+
}).then((res) => {
102+
expect(res.status).to.eq(200);
103+
repoId = res.body._id;
104+
});
105+
});
106+
});
107+
108+
it('Opens tooltip with correct content and can copy', () => {
109+
cy.visit('/dashboard/repo');
110+
cy.on('uncaught:exception', () => false);
111+
112+
const tooltipQuery = 'div[role="tooltip"]';
113+
114+
// Check the tooltip isn't open to start with
115+
cy.get(tooltipQuery).should('not.exist');
116+
117+
// Find the repo's Code button and click it
118+
cy.get(`a[href="/dashboard/repo/${repoId}"]`)
119+
.closest('tr')
120+
.find('span')
121+
.contains('Code')
122+
.should('exist')
123+
.click();
124+
125+
// Check tooltip is open and contains the correct clone URL
126+
cy.get(tooltipQuery)
127+
.should('exist')
128+
.find('span')
129+
.contains(cloneURL)
130+
.should('exist')
131+
.parent()
132+
.find('span')
133+
.next()
134+
.get('svg.octicon-copy')
135+
.should('exist')
136+
.click()
137+
.get('svg.octicon-copy')
138+
.should('not.exist')
139+
.get('svg.octicon-check')
140+
.should('exist');
141+
});
142+
143+
after(() => {
144+
// Delete the repo
145+
cy.getCSRFToken().then((csrfToken) => {
146+
cy.request({
147+
method: 'DELETE',
148+
url: `http://localhost:8080/api/v1/repo/${repoName}/delete`,
149+
headers: {
150+
cookie: cookies?.join('; ') || '',
151+
'X-CSRF-TOKEN': csrfToken,
152+
},
153+
});
80154
});
81155
});
82156
});

cypress/support/commands.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ Cypress.Commands.add('login', (username, password) => {
4040
});
4141
});
4242

43+
Cypress.Commands.add('logout', () => {
44+
Cypress.session.clearAllSavedSessions();
45+
});
46+
4347
Cypress.Commands.add('getCSRFToken', () => {
4448
return cy.request('GET', 'http://localhost:8080/api/v1/repo').then((res) => {
4549
let cookies = res.headers['set-cookie'];

package-lock.json

Lines changed: 9 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@
2424
"format": "prettier --write \"**/*.{js,jsx,ts,tsx,json,md,yml,yaml,css,scss}\" --ignore-path .gitignore --config ./.prettierrc",
2525
"format:check": "prettier --check \"**/*.{js,jsx,ts,tsx,json,md,yml,yaml,css,scss}\" --ignore-path .gitignore --config ./.prettierrc",
2626
"gen-schema-doc": "node ./scripts/doc-schema.js",
27-
"cypress:run": "cypress run"
27+
"cypress:run": "cypress run",
28+
"cypress:open": "cypress open"
2829
},
2930
"bin": {
3031
"git-proxy": "./index.js",

src/service/passport/local.js

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,18 @@ const configure = async (passport) => {
4242
};
4343

4444
/**
45-
* Create the default admin user if it doesn't exist
45+
* Create the default admin and regular test users.
4646
*/
4747
const createDefaultAdmin = async () => {
48-
const admin = await db.findUser('admin');
49-
if (!admin) {
50-
await db.createUser('admin', 'admin', '[email protected]', 'none', true);
51-
}
48+
const createIfNotExists = async (username, password, email, type, isAdmin) => {
49+
const user = await db.findUser(username);
50+
if (!user) {
51+
await db.createUser(username, password, email, type, isAdmin);
52+
}
53+
};
54+
55+
await createIfNotExists('admin', 'admin', '[email protected]', 'none', true);
56+
await createIfNotExists('user', 'user', '[email protected]', 'none', false);
5257
};
5358

5459
module.exports = { configure, createDefaultAdmin, type };

src/ui/services/repo.js

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -79,19 +79,21 @@ const getRepo = async (setIsLoading, setData, setAuth, setIsError, id) => {
7979
});
8080
};
8181

82-
const addRepo = async (onClose, setError, data) => {
82+
const addRepo = async (data) => {
8383
const url = new URL(`${baseUrl}/repo`);
8484

85-
return axios
86-
.post(url, data, getAxiosConfig())
87-
.then((response) => {
88-
onClose();
89-
return response.data;
90-
})
91-
.catch((error) => {
92-
console.log(error.response.data.message);
93-
setError(error.response.data.message);
94-
});
85+
try {
86+
const response = await axios.post(url, data, getAxiosConfig());
87+
return {
88+
success: true,
89+
repo: response.data,
90+
};
91+
} catch (error) {
92+
return {
93+
success: false,
94+
message: error.response?.data?.message || error.message,
95+
};
96+
}
9597
};
9698

9799
const addUser = async (repoId, user, action) => {

src/ui/views/RepoDetails/RepoDetails.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ const RepoDetails: React.FC = () => {
119119
<Button
120120
variant='contained'
121121
color='secondary'
122+
data-testid='delete-repo-button'
122123
onClick={() => removeRepository(data._id)}
123124
>
124125
<Delete />

0 commit comments

Comments
 (0)