Skip to content

Commit 29f1b07

Browse files
authored
feat: fixed stylistic issues, added deleteproject button, fixed cypress tests (#610)
1 parent 007a84c commit 29f1b07

File tree

29 files changed

+404
-377
lines changed

29 files changed

+404
-377
lines changed

compose/neurosynth-frontend/cypress/e2e/pages/AuthenticatedLandingPage.cy.tsx

Lines changed: 0 additions & 78 deletions
This file was deleted.

compose/neurosynth-frontend/cypress/e2e/pages/LandingPage.cy.tsx

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,24 @@ const PAGE_NAME = 'LandingPage';
77
describe(PAGE_NAME, () => {
88
beforeEach(() => {
99
cy.intercept('GET', 'https://api.appzi.io/**', { fixture: 'appzi' }).as('appziFixture');
10+
cy.intercept('GET', `**/api/base-studies/**`, { fixture: 'baseStudies' }).as(
11+
'baseStudiesFixture'
12+
);
13+
cy.intercept('GET', `**/api/points/**`, { fixture: 'points' }).as('pointsFixture');
1014
});
1115

1216
it('should load successfully', () => {
13-
cy.visit('/');
17+
cy.visit('/').wait('@baseStudiesFixture').wait('@pointsFixture');
18+
});
19+
20+
it('should authenticate for real and redirect to projects page', () => {
21+
cy.login('real').visit('/');
22+
cy.contains('Projects');
23+
});
24+
25+
it('should authenticate and redirect to the projects page', () => {
26+
cy.login('mocked').visit('/');
27+
cy.contains('Projects');
1428
});
1529

1630
it('should change the viewport property', () => {

compose/neurosynth-frontend/cypress/e2e/pages/NotFound.cy.tsx

Lines changed: 0 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -9,38 +9,4 @@ describe('NotFoundPage', () => {
99
cy.visit('/page-that-doesnt-exist');
1010
cy.contains('Requested resource not found');
1111
});
12-
13-
// it('should route the non existent studyset resource to the not found page', () => {
14-
// cy.intercept('GET', '**/api/studysets/*', { statusCode: 404 }).as('studysetsRequestError');
15-
// cy.intercept('GET', '**/api/annotations/*', { statusCode: 404 }).as(
16-
// 'annotationsRequestError'
17-
// );
18-
19-
// cy.visit('/studysets/studyset-that-doesnt-exist')
20-
// .wait(['@studysetsRequestError', '@annotationsRequestError'])
21-
// .get('body')
22-
// .contains('Requested resource not found');
23-
// });
24-
25-
// it('should route the non existent meta-analysis resource to the not found page', () => {
26-
// cy.intercept('GET', '**/api/meta-analyses/**', { statusCode: 404 }).as(
27-
// 'metaAnalysisRequestError'
28-
// );
29-
30-
// cy.visit('/meta-analyses/meta-analysis-that-doesnt-exist')
31-
// .wait(['@metaAnalysisRequestError'])
32-
// .get('body')
33-
// .contains('Requested resource not found');
34-
// });
35-
36-
// it('should route the non existent annotation resource to the not found page', () => {
37-
// cy.intercept('GET', '**/api/annotations/*', {
38-
// statusCode: 404,
39-
// }).as('annotationRequestError');
40-
41-
// cy.visit('/annotations/annotation-doesnt-exist')
42-
// .wait(['@annotationRequestError'])
43-
// .get('body')
44-
// .contains('Requested resource not found');
45-
// });
4612
});
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"metadata": {
3+
"total_count": 100
4+
}
5+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"metadata": {
3+
"total_count": 100
4+
}
5+
}

compose/neurosynth-frontend/cypress/support/commands.ts

Lines changed: 9 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -10,34 +10,6 @@ import * as jose from 'jose';
1010
// commands please read more here:
1111
// https://on.cypress.io/custom-commands
1212
// ***********************************************
13-
//
14-
//
15-
// -- This is a parent command --
16-
// Cypress.Commands.add('login', (email, password) => { ... })
17-
//
18-
//
19-
// -- This is a child command --
20-
// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... })
21-
//
22-
//
23-
// -- This is a dual command --
24-
// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... })
25-
//
26-
//
27-
// -- This will overwrite an existing command --
28-
// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
29-
//
30-
// declare global {
31-
// namespace Cypress {
32-
// interface Chainable {
33-
// login(email: string, password: string): Chainable<void>
34-
// drag(subject: string, options?: Partial<TypeOptions>): Chainable<Element>
35-
// dismiss(subject: string, options?: Partial<TypeOptions>): Chainable<Element>
36-
// visit(originalFn: CommandOriginalFn, url: string, options: Partial<VisitOptions>): Chainable<Element>
37-
// }
38-
// }
39-
// }
40-
4113
const constructMockAuthJWT = async (jwtPayload = {}): Promise<string> => {
4214
const jwt = await new jose.SignJWT({ ...jwtPayload })
4315
.setProtectedHeader({ alg: 'HS256' })
@@ -51,6 +23,7 @@ const createMockRequest = async (
5123
audience: string,
5224
client_id: string,
5325
domain: string,
26+
scope: string,
5427
extraClaims = {}
5528
) => {
5629
const access_token = await constructMockAuthJWT({
@@ -60,7 +33,7 @@ const createMockRequest = async (
6033
iat: 1659719697,
6134
exp: 1659806097,
6235
azp: 'EmcOFhu0XAINM4EyslaKpZ3u09QlBvef',
63-
scope: 'openid profile email',
36+
scope: scope,
6437
});
6538

6639
const id_token = await constructMockAuthJWT({
@@ -85,7 +58,7 @@ const createMockRequest = async (
8558
access_token: access_token,
8659
expires_in: 86400,
8760
id_token: id_token,
88-
scope: 'openid profile email read:current_user update:current_user_metadata delete:current_user_metadata create:current_user_metadata create:current_user_device_credentials delete:current_user_device_credentials update:current_user_identities',
61+
scope: scope,
8962
token_type: 'Bearer',
9063
},
9164
};
@@ -99,12 +72,14 @@ Cypress.Commands.add('login', (loginMode = 'mocked', extraClaims = {}) => {
9972
const password = Cypress.env('auth0Password');
10073
const domain = Cypress.env('auth0Domain');
10174

75+
const scope = 'openid profile email offline_access';
76+
10277
/**
10378
* To prevent rate limiting errors form auth0, we stub our own request func and return a mocked response
10479
*/
10580
if (loginMode === 'mocked') {
10681
cy.stub(cy, 'request').callsFake(() =>
107-
cy.wrap(createMockRequest(audience, client_id, domain, extraClaims))
82+
cy.wrap(createMockRequest(audience, client_id, domain, scope, extraClaims))
10883
);
10984
}
11085

@@ -121,7 +96,7 @@ Cypress.Commands.add('login', (loginMode = 'mocked', extraClaims = {}) => {
12196
username,
12297
password,
12398
audience,
124-
scope: 'openid profile email',
99+
scope,
125100
client_id,
126101
client_secret,
127102
},
@@ -153,7 +128,7 @@ Cypress.Commands.add('login', (loginMode = 'mocked', extraClaims = {}) => {
153128
},
154129
expires_in,
155130
id_token,
156-
scope: 'openid profile email read:current_user update:current_user_metadata delete:current_user_metadata create:current_user_metadata create:current_user_device_credentials delete:current_user_device_credentials update:current_user_identities',
131+
scope,
157132
token_type: 'Bearer',
158133
},
159134
expiresAt: Math.floor(Date.now() / 1000) + expires_in,
@@ -165,13 +140,10 @@ Cypress.Commands.add('login', (loginMode = 'mocked', extraClaims = {}) => {
165140
* the isAuthenticated state. This code is in tandem with setting the auth0 provider cacheLocation=localstorage.
166141
*/
167142
cy.addToLocalStorage(
168-
`@@auth0spajs@@::${client_id}::${audience}::openid profile email`,
143+
`@@auth0spajs@@::${client_id}::${audience}::${scope}`,
169144
JSON.stringify(session)
170145
);
171146
});
172-
173-
// this will always run after the previous commands are complete
174-
cy.visit('/');
175147
});
176148

177149
Cypress.Commands.add('clearSessionStorage', () => {
@@ -192,7 +164,6 @@ declare global {
192164
namespace Cypress {
193165
interface Chainable {
194166
login(loginMode: 'real' | 'mocked', extraClaims?: any): Chainable<void>;
195-
mockLogin(extraClaims?: any): Chainable<void>;
196167
clearSessionStorage(): Chainable<void>;
197168
addToLocalStorage(key: string, value: string): Chainable<void>;
198169
}

compose/neurosynth-frontend/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@
5959
"test-with-coverage": "npm run test -- --coverage --watchAll=false",
6060
"cy:e2e-headless": "cypress run",
6161
"cy:e2e-headless-local": "env-cmd -f .env.dev cypress run",
62-
"cy:e2e-browser": "env-cmd -f .env.dev cypress open -b chrome --e2e",
62+
"cy:e2e-browser": "env-cmd -f .env.staging cypress open -b chrome --e2e",
6363
"cy:install": "cypress install",
6464
"cy:ci": "start-server-and-test start-ci:dev 3000 cy:e2e-headless",
6565
"eject": "react-scripts eject"

compose/neurosynth-frontend/src/components/Dialogs/ConfirmationDialog/ConfirmationDialog.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ const ConfirmationDialog: React.FC<IConfirmationDialog> = (props) => {
4646
</DialogTitle>
4747
<DialogContent>
4848
{props.dialogMessage && dialogContent}
49-
<Box sx={{ display: 'flex', justifyContent: 'space-between' }}>
49+
<Box sx={{ display: 'flex', justifyContent: 'space-between', marginTop: '1rem' }}>
5050
<Button
5151
sx={{ width: '250px', marginRight: '15px' }}
5252
onClick={() => props.onCloseDialog(false, props.data)}

compose/neurosynth-frontend/src/components/DisplayStudy/DisplayStudyChipLinks/FullTextChip.tsx

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,6 @@ const FullTextChip: React.FC<{ name?: string | null }> = (props) => {
2828
isError: getFullTextIsError,
2929
} = useGetFullText(debouncedName);
3030

31-
console.log({
32-
debouncedName,
33-
getFullTextIsError,
34-
getFullTextIsLoading,
35-
fullTextURL,
36-
});
37-
3831
if (getFullTextIsLoading || !debouncedName) {
3932
return (
4033
<Box sx={{ display: 'inline-block', textAlign: 'center', width: '200px' }}>

compose/neurosynth-frontend/src/components/EditStudyComponents/EditStudySaveButton/EditStudySaveButton.tsx

Lines changed: 41 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -83,42 +83,57 @@ const EditStudySaveButton: React.FC = React.memo((props) => {
8383
const [isCloning, setIsCloning] = useState(false);
8484

8585
const handleUpdateBothInDB = async () => {
86-
const updatedStudy = await updateStudyInDB(annotationId as string);
87-
const updatedNotes = [...(notes || [])];
88-
updatedNotes.forEach((note, index) => {
89-
if (note.isNew) {
90-
const foundAnalysis = ((updatedStudy.analyses || []) as AnalysisReturn[]).find(
91-
(analysis) => analysis.name === note.analysis_name
92-
);
93-
if (!foundAnalysis) return;
86+
try {
87+
const updatedStudy = await updateStudyInDB(annotationId as string);
88+
const updatedNotes = [...(notes || [])];
89+
updatedNotes.forEach((note, index) => {
90+
if (note.isNew) {
91+
const foundAnalysis = ((updatedStudy.analyses || []) as AnalysisReturn[]).find(
92+
(analysis) => analysis.name === note.analysis_name
93+
);
94+
if (!foundAnalysis) return;
9495

95-
updatedNotes[index] = {
96-
...updatedNotes[index],
97-
analysis: foundAnalysis.id,
98-
};
99-
}
100-
});
101-
updateAnnotationNotes(updatedNotes);
102-
await updateAnnotationInDB();
96+
updatedNotes[index] = {
97+
...updatedNotes[index],
98+
analysis: foundAnalysis.id,
99+
};
100+
}
101+
});
102+
updateAnnotationNotes(updatedNotes);
103+
await updateAnnotationInDB();
103104

104-
queryClient.invalidateQueries('studies');
105-
queryClient.invalidateQueries('annotations');
105+
queryClient.invalidateQueries('studies');
106+
queryClient.invalidateQueries('annotations');
106107

107-
enqueueSnackbar('Study and annotation saved', { variant: 'success' });
108+
enqueueSnackbar('Study and annotation saved', { variant: 'success' });
109+
} catch (e) {
110+
console.error(e);
111+
enqueueSnackbar('There was an error', { variant: 'error' });
112+
}
108113
};
109114

110115
const handleUpdateStudyInDB = async () => {
111-
await updateStudyInDB(annotationId as string);
112-
queryClient.invalidateQueries('studies');
113-
queryClient.invalidateQueries('annotations');
116+
try {
117+
await updateStudyInDB(annotationId as string);
118+
queryClient.invalidateQueries('studies');
119+
queryClient.invalidateQueries('annotations');
114120

115-
enqueueSnackbar('Study saved', { variant: 'success' });
121+
enqueueSnackbar('Study saved', { variant: 'success' });
122+
} catch (e) {
123+
console.error(e);
124+
enqueueSnackbar('There was an error saving the study', { variant: 'error' });
125+
}
116126
};
117127

118128
const handleUpdateAnnotationInDB = async () => {
119-
await updateAnnotationInDB();
120-
queryClient.invalidateQueries('annotations');
121-
enqueueSnackbar('Annotation saved', { variant: 'success' });
129+
try {
130+
await updateAnnotationInDB();
131+
queryClient.invalidateQueries('annotations');
132+
enqueueSnackbar('Annotation saved', { variant: 'success' });
133+
} catch (e) {
134+
console.error(e);
135+
enqueueSnackbar('There was an issue saving the annotation', { variant: 'error' });
136+
}
122137
};
123138

124139
const handleUpdateDB = () => {

0 commit comments

Comments
 (0)