Skip to content

Commit

Permalink
Merge branch 'refs/heads/develop' into gr-DCJ-659-ecm-for-era-commons
Browse files Browse the repository at this point in the history
  • Loading branch information
rushtong committed Nov 18, 2024
2 parents 59640c9 + 32a96aa commit 9a411b1
Show file tree
Hide file tree
Showing 30 changed files with 639 additions and 161 deletions.
2 changes: 2 additions & 0 deletions DEVNOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ docker build . -t duos
docker compose up -d
```

Visit https://local.dsde-dev.broadinstitute.org/ to see the instance running under docker.

# Testing

## Cypress Tests
Expand Down
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ ENV PATH /usr/src/app/node_modules/.bin:$PATH

# install and cache app dependencies
COPY src /usr/src/app/src
COPY types /usr/src/app/types
COPY public /usr/src/app/public
COPY package.json /usr/src/app/package.json
COPY package-lock.json /usr/src/app/package-lock.json
Expand Down
27 changes: 27 additions & 0 deletions cypress/component/DataSearch/dataset_search_filters.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/* eslint-disable no-undef */

import { mount } from 'cypress/react';
import React from 'react';
import {Storage} from '../../../src/libs/storage';
import DatasetFilterList from '../../../src/components/data_search/DatasetFilterList';

const duosUser = {
isSigningOfficial: false,
};

describe('Data Library Filters', () => {
// Intercept configuration calls
beforeEach(() => {
cy.intercept({
method: 'GET',
url: '/config.json',
hostname: 'localhost',
}, { 'env': 'ci' });
});

it('Renders the data library filters', () => {
const props = { datasets: [], filters: [], filterHandler: () => {}, isFiltered: () => {}};
mount(<DatasetFilterList {...props} />);
cy.get('div').should('contain', 'Filters');
});
});
65 changes: 65 additions & 0 deletions cypress/component/DataSearch/dataset_search_footer.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/* eslint-disable no-undef */
import {mount} from 'cypress/react';
import {React} from 'react';
import {DatasetSearchFooter} from '../../../src/components/data_search/DatasetSearchFooter';

const datasets = [
{
datasetId: 123456,
study: {
studyId: 1,
}
},
{
datasetId: 234567,
study: {
studyId: 1,
}
},
{
datasetId: 345678,
study: {
studyId: 2,
}
},
];

const oneDatasetProps = {
selectedDatasets: [123456],
datasets: datasets,
onClick: () => {},
};

const oneStudyProps = {
selectedDatasets: [123456, 234567],
datasets: datasets,
onClick: () => {},
};

const twoStudiesProps = {
selectedDatasets: [123456, 234567, 345678],
datasets: datasets,
onClick: () => {},
};

describe('Dataset Search Footer renders correct text and button', () => {

it('Shows button and single dataset and study text', () => {
mount(<DatasetSearchFooter {...oneDatasetProps} />);
cy.contains('1 dataset selected from 1 study');
cy.contains('Apply for Access');
});


it('Shows button and two datasets from one study text', () => {
mount(<DatasetSearchFooter {...oneStudyProps} />);
cy.contains('2 datasets selected from 1 study');
cy.contains('Apply for Access');
});

it('Shows button and three datasets from two studies text', () => {
mount(<DatasetSearchFooter {...twoStudiesProps} />);
cy.contains('3 datasets selected from 2 studies');
cy.contains('Apply for Access');
});
});
33 changes: 33 additions & 0 deletions cypress/component/DataSearch/dataset_search_page.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/* eslint-disable no-undef */

import { mount } from 'cypress/react';
import React from 'react';
import {Storage} from '../../../src/libs/storage';
import DatasetSearch from '../../../src/pages/DatasetSearch';

const duosUser = {
isSigningOfficial: false,
};

describe('Data Library', () => {
// Intercept configuration calls
beforeEach(() => {
cy.intercept({
method: 'GET',
url: '/config.json',
hostname: 'localhost',
}, { 'env': 'ci' });
});

it('Renders the data library without a query', () => {
const props = { match: { params: { query: undefined } } };
cy.stub(Storage, 'getCurrentUser').returns(duosUser);
mount(<DatasetSearch {...props} />);
});

it('Renders the data library with a query', () => {
const props = { match: { params: { query: 'test' } } };
cy.stub(Storage, 'getCurrentUser').returns(duosUser);
mount(<DatasetSearch {...props} />);
});
});
43 changes: 43 additions & 0 deletions cypress/component/DataSearch/dataset_search_table.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/* eslint-disable no-undef */
import {React} from 'react';
import {mount} from 'cypress/react';
import DatasetSearchTable from '../../../src/components/data_search/DatasetSearchTable';
import {TerraDataRepo} from '../../../src/libs/ajax/TerraDataRepo';

const datasets = [
{
datasetId: 123456,
datasetIdentifier: `DUOS-123456`,
datasetName: 'Some Dataset 1',
study: {
studyId: 1,
dataCustodianEmail: ['Some Data Custodian Email 1'],
}
}
];

const props = {
datasets: datasets,
history: {}
};

describe('Dataset Search Table tests', () => {

describe('Data library with three datasets', () => {
beforeEach(() => {
cy.stub(TerraDataRepo, 'listSnapshotsByDatasetIds').returns({});
mount(<DatasetSearchTable {...props} />);
});

it('When no datasets are selected the footer does not appear', () => {
cy.contains('1 dataset selected from 1 study').should('not.exist');
});


it('When a dataset is selected the footer appears', () => {
cy.get('#header-checkbox').click();
cy.contains('1 dataset selected from 1 study');
});

});
});
34 changes: 24 additions & 10 deletions cypress/component/SignIn/sign_in_button.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,18 @@ import {Metrics} from '../../../src/libs/ajax/Metrics';
import {StackdriverReporter} from '../../../src/libs/stackdriverReporter';
import {ToS} from '../../../src/libs/ajax/ToS';
import {mockOidcUser} from '../Auth/mockOidcUser';

const signInText = 'Sign In';

const duosUser = {
displayName: 'display name',
email: '[email protected]',
isAdmin: true,
isAlumni: false,
isChairPerson: false,
isDataSubmitter: false,
isMember: false,
isResearcher: false,
isSigningOfficial: false,
roles: [{
name: 'Admin'
}]
Expand All @@ -33,6 +39,11 @@ const notAcceptedUserStatus = Object.assign({}, userStatus, {'tosAccepted': fals

describe('Sign In: Component Loads', function () {

// Intercept configuration calls
beforeEach(() => {
cy.initApplicationConfig();
});

it('Sign In Button Loads', function () {
cy.viewport(600, 300);
mount(<SignInButton history={undefined}/>);
Expand All @@ -42,14 +53,15 @@ describe('Sign In: Component Loads', function () {
it('Sign In: On Success', function () {
cy.viewport(600, 300);
cy.stub(Auth, 'signIn').returns(Promise.resolve(mockOidcUser));
cy.stub(User, 'getMe').returns(duosUser);
cy.intercept({method: 'GET', url: '**/api/user/me'}, {statusCode: 200, body: duosUser}).as('getMe');
cy.stub(StackdriverReporter, 'report');
cy.stub(Metrics, 'identify');
cy.stub(Metrics, 'syncProfile');
cy.stub(Metrics, 'captureEvent');
cy.stub(ToS, 'getStatus').returns(userStatus);
mount(<SignInButton history={[]}/>);
cy.get('button').click().then(() => {
cy.get('button').click();
cy.wait('@getMe').then(() => {
expect(Storage.getCurrentUser()).to.deep.equal(duosUser);
expect(Storage.getAnonymousId()).to.not.be.null;
expect(StackdriverReporter.report).to.not.be.called;
Expand All @@ -63,29 +75,31 @@ describe('Sign In: Component Loads', function () {
const bareUser = {email: '[email protected]'};
cy.viewport(600, 300);
cy.stub(Auth, 'signIn').returns(Promise.resolve(mockOidcUser));
cy.stub(User, 'getMe').returns(bareUser);
cy.intercept({method: 'GET', url: '**/api/user/me'}, {statusCode: 200, body: bareUser}).as('getMe');
cy.stub(StackdriverReporter, 'report');
cy.stub(Metrics, 'identify');
cy.stub(Metrics, 'syncProfile');
cy.stub(Metrics, 'captureEvent');
cy.stub(ToS, 'getStatus').returns(userStatus);
mount(<SignInButton history={[]}/>);
cy.get('button').click().then(() => {
cy.get('button').click();
cy.wait('@getMe').then(() => {
expect(StackdriverReporter.report).to.be.called;
});
});

it('Sign In: Redirects to ToS if not accepted', function () {
cy.viewport(600, 300);
cy.stub(Auth, 'signIn').returns(Promise.resolve(mockOidcUser));
cy.stub(User, 'getMe').returns(duosUser);
cy.intercept({method: 'GET', url: '**/api/user/me'}, {statusCode: 200, body: duosUser}).as('getMe');
cy.stub(ToS, 'getStatus').returns(notAcceptedUserStatus);
cy.stub(Metrics, 'identify');
cy.stub(Metrics, 'syncProfile');
cy.stub(Metrics, 'captureEvent');
let history = [];
mount(<SignInButton history={history}/>);
cy.get('button').click().then(() => {
cy.get('button').click();
cy.wait('@getMe').then(() => {
expect(history).to.not.be.empty;
expect(history[0].includes('tos_acceptance')).to.be.true;
});
Expand All @@ -96,15 +110,15 @@ describe('Sign In: Component Loads', function () {
cy.stub(Auth, 'signIn').returns(Promise.resolve(mockOidcUser));
// Simulate user not found
cy.stub(User, 'getMe').throws();
cy.stub(User, 'registerUser').returns(duosUser);
cy.intercept({method: 'POST', url: '**/api/user'}, {statusCode: 200, body: duosUser}).as('registerUser');
cy.stub(ToS, 'getStatus').returns(notAcceptedUserStatus);
cy.stub(Metrics, 'identify');
cy.stub(Metrics, 'syncProfile');
cy.stub(Metrics, 'captureEvent');
let history = [];
mount(<SignInButton history={history}/>);
cy.get('button').click().then(() => {
expect(User.registerUser).to.be.called;
cy.get('button').click();
cy.wait('@registerUser').then(() => {
expect(history).to.not.be.empty;
expect(history[0].includes('tos_acceptance')).to.be.true;
});
Expand Down
50 changes: 50 additions & 0 deletions cypress/component/UserProfile/user_profile.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/* eslint-disable no-undef */

import {mount} from 'cypress/react';
import React from 'react';
import {Storage} from '../../../src/libs/storage';
import {User} from '../../../src/libs/ajax/User';
import {Institution} from '../../../src/libs/ajax/Institution';
import UserProfile from '../../../src/pages/user_profile/UserProfile';

const duosUser = {
isSigningOfficial: false,
};

describe('User Profile', () => {
// Intercept configuration calls
beforeEach(() => {
cy.intercept({
method: 'GET',
url: '/config.json',
hostname: 'localhost',
}, {'env': 'ci'});
});

it('Renders the user profile page', () => {
cy.stub(Storage, 'getCurrentUser').returns(duosUser);
cy.stub(Institution, 'list').returns([]);
cy.stub(User, 'getMe').returns(duosUser);
cy.stub(User, 'getApprovedDatasets').returns([]);
cy.stub(User, 'getAcknowledgements').returns({});
mount(<UserProfile/>);
cy.get('h2').should('contain', 'Your Profile');
});

it('Updates the user email preferences', () => {
cy.stub(Storage, 'getCurrentUser').returns(duosUser);
cy.stub(Institution, 'list').returns([]);
cy.stub(User, 'getMe').returns(duosUser);
cy.stub(User, 'getApprovedDatasets').returns([]);
cy.stub(User, 'getAcknowledgements').returns({});
cy.intercept(
{method: 'PUT', url: '**/user'},
{statusCode: 200, body: duosUser}
).as('updateSelf');
mount(<UserProfile/>);
cy.get('input[id="profileEmailEnabled_yes"]').check();
cy.wait('@updateSelf').then(() => {
cy.get('div').contains('Email preference updated successfully!');
});
});
});
42 changes: 42 additions & 0 deletions cypress/component/utils/metrics.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/* eslint-disable no-undef */
import {Metrics} from '../../../src/libs/ajax/Metrics';
import eventList from '../../../src/libs/events';

describe('Metrics Tests', function () {

// Intercept configuration calls
beforeEach(() => {
cy.intercept({
method: 'GET',
url: '/config.json',
hostname: 'localhost',
}, {'env': 'ci'});
});

Cypress._.each(Object.keys(eventList), (eventType) => {
it(`Captures ${eventType} Event`, function () {
cy.intercept('**/event').as('event');
Metrics.captureEvent(eventType);
cy.wait('@event').then(interception => {
expect(interception).to.exist;
});
});
});

it('Sync Profile', function () {
cy.intercept('**/syncProfile').as('sync');
Metrics.syncProfile();
cy.wait('@sync').then(interception => {
expect(interception).to.exist;
});
});

it('Identify', function () {
cy.intercept('**/identify').as('identify');
Metrics.identify('anonymousId');
cy.wait('@identify').then(interception => {
expect(interception).to.exist;
});
});

});
Loading

0 comments on commit 9a411b1

Please sign in to comment.