Skip to content

Commit

Permalink
Cypress Testing (#182)
Browse files Browse the repository at this point in the history
* Add login tests

* Add tests for client calendar add assignments

* Add test for assignment allocation flow

* Add feedback flow test

* Ensure that auth spec is ran first

Co-authored-by: elihuansen <[email protected]>
  • Loading branch information
weiyuan95 and eli-lim committed Nov 17, 2020
1 parent 2e8fba7 commit 57760f5
Show file tree
Hide file tree
Showing 21 changed files with 870 additions and 30 deletions.
10 changes: 8 additions & 2 deletions sadeaf-hasura/mockdata.sql
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,8 @@ INSERT INTO event (
(4, 'CodeIT Suisse', 3, 'Annual hackathon for recruitment and campus outreach', 'Workshop', true, true),
(5, 'COMM169 - Management Communication', 3, 'CORE SMU module', 'School', true, false),
(6, 'COMM169 - Management Communication', 4, 'CORE SMU module', 'School', false, true),
(7, 'COMM169 - Management Communication', 5, 'CORE SMU module', 'School', false, true);
(7, 'COMM169 - Management Communication', 5, 'CORE SMU module', 'School', false, true),
(8, 'Feedback Event', 12, 'CORE SMU module', 'School', false, true);

INSERT INTO assignment (
id, event_id, status, start_dt, end_dt,
Expand Down Expand Up @@ -232,10 +233,15 @@ INSERT INTO assignment (

(13, 2, 'PENDING', CURRENT_TIMESTAMP + interval '192 hour', CURRENT_TIMESTAMP + interval '194 hour',
'18 Cashew Ave', null, '123405', null, null, null,
null, 100);
null, 100),

(14, 8, 'MATCHED', CURRENT_TIMESTAMP + interval '24 hour', CURRENT_TIMESTAMP + interval '27 hour',
'18 Cashew Ave', null, '123405', null, null, null,
8, 100);

UPDATE assignment SET status = 'COMPLETE' WHERE id = 10;
UPDATE assignment SET status = 'COMPLETE' WHERE id = 9;
UPDATE assignment SET status = 'COMPLETE' WHERE id = 14;


-- TODO: Add more assignments for the other clients + volunteers
Expand Down
1 change: 1 addition & 0 deletions sadeaf-web/components/PendingAssignmentsMatchingList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ export default {
assignment.start_dt = DateUtils.utcToGmt8(assignment.start_dt);
assignment.end_dt = DateUtils.utcToGmt8(assignment.end_dt);
});
pending_assignments.sort((a, b) => a.id - b.id);
this.pendingAssignments = pending_assignments;
},
},
Expand Down
2 changes: 2 additions & 0 deletions sadeaf-web/components/calendars/VolunteerEventCalendar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,8 @@ export default {
}
});

filtered_assignments.sort((a, b) => a.id - b.id);

filtered_assignments.forEach((assignment) => {
assignment.start_dt = DateUtils.utcToGmt8(assignment.start_dt);
assignment.end_dt = DateUtils.utcToGmt8(assignment.end_dt);
Expand Down
6 changes: 3 additions & 3 deletions sadeaf-web/components/forms/ClientCreateEventForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
</el-form-item>
<el-form-item label="Purpose" prop="purpose" required>
<div class="field-purpose">
<el-select v-model="form.purpose" placeholder="School">
<el-select data-test="client-create-event-purpose" v-model="form.purpose" placeholder="School">
<el-option v-for="option in EVENT_PURPOSE_OPTIONS" :key="'opt-' + option" :value="option">
{{ option }}
</el-option>
Expand All @@ -26,14 +26,14 @@
</div>
</el-form-item>
<el-form-item label="Topic">
<el-select v-model="form.category" placeholder="Choose one">
<el-select data-test="client-create-event-category" v-model="form.category" placeholder="Choose one">
<el-option v-for="option in EVENT_CATEGORY_OPTIONS" :key="'t-opt-' + option" :value="option">
{{ option }}
</el-option>
</el-select>
</el-form-item>
<el-form-item label="Edu Level Needed">
<el-select v-model="form.education" placeholder="Choose one">
<el-select data-test="client-create-event-education" v-model="form.education" placeholder="Choose one">
<el-option v-for="option in EVENT_EDUCATION_OPTIONS" :key="'e-opt-' + option" :value="option">
{{ option }}
</el-option>
Expand Down
2 changes: 1 addition & 1 deletion sadeaf-web/components/navbar/BaseNavbar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<el-menu-item index="/account/notifications"> Notification Preferences </el-menu-item>
</el-submenu>
<el-menu-item>
<logout-button />
<logout-button data-test="logout-button" />
</el-menu-item>
</el-menu>
</template>
Expand Down
2 changes: 1 addition & 1 deletion sadeaf-web/components/navbar/admin.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<base-navbar v-on="$listeners">
<template v-slot:user-nav>
<el-menu-item index="/admin"> Service Requests </el-menu-item>
<el-menu-item index="/admin/feedback"> Feedback </el-menu-item>
<el-menu-item data-test="admin-feedback" index="/admin/feedback"> Feedback </el-menu-item>
<el-submenu index="/admin/users">
<template slot="title">User Management</template>
<el-menu-item index="/admin/users?type=client,service_requestor,volunteer,admin"> All Users </el-menu-item>
Expand Down
2 changes: 1 addition & 1 deletion sadeaf-web/components/navbar/client.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<template v-slot:user-nav>
<el-menu-item index="/client"> Service Requests </el-menu-item>

<el-menu-item index="/client/feedback"> Feedback </el-menu-item>
<el-menu-item data-test="client-feedback" index="/client/feedback"> Feedback </el-menu-item>
</template>
</base-navbar>
</template>
Expand Down
5 changes: 5 additions & 0 deletions sadeaf-web/cypress.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"includeShadowDom": true,
"watchForFileChanges": false,
"baseUrl": "http://localhost:3000"
}
5 changes: 5 additions & 0 deletions sadeaf-web/cypress/fixtures/example.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "Using fixtures to represent data",
"email": "[email protected]",
"body": "Fixtures are a great way to mock data for responses to routes"
}
39 changes: 39 additions & 0 deletions sadeaf-web/cypress/helpers/login-helpers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
export function enterClientHomepage() {
cy.visit('/');
cy.wait(1500);
cy.get('[data-test=sign-in-email-input]').first().type('[email protected]', { force: true });
cy.get('[data-test=sign-in-password-input]').first().type('password123', { force: true });
cy.get('[data-test="sign-in-sign-in-button"]').first().click();
cy.wait(3000);
}

export function enterVolunteerHomepage() {
cy.visit('/');
cy.wait(1500);
cy.get('[data-test=sign-in-email-input]').first().type('[email protected]', { force: true });
cy.get('[data-test=sign-in-password-input]').first().type('password123', { force: true });
cy.get('[data-test="sign-in-sign-in-button"]').first().click();
cy.wait(3000);
}

export function enterAdminHomepage() {
cy.visit('/');
cy.wait(1500);
cy.get('[data-test=sign-in-email-input]').first().type('[email protected]', { force: true });
cy.get('[data-test=sign-in-password-input]').first().type('password123', { force: true });
cy.get('[data-test="sign-in-sign-in-button"]').first().click();
cy.wait(3000);
}

export function enterNonEnabledUserHomepage() {
cy.visit('/');
cy.wait(1500);
cy.get('[data-test=sign-in-email-input]').first().type('[email protected]', { force: true });
cy.get('[data-test=sign-in-password-input]').first().type('password123', { force: true });
cy.get('[data-test="sign-in-sign-in-button"]').first().click();
cy.wait(3000);
}

export function clickLogoutButton() {
cy.get('[data-test=logout-button]').click({ force: true });
}
40 changes: 40 additions & 0 deletions sadeaf-web/cypress/integration/01-auth.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import {
enterAdminHomepage,
enterClientHomepage,
enterNonEnabledUserHomepage,
enterVolunteerHomepage,
} from '../helpers/login-helpers';

describe('Login', () => {
beforeEach(() => {
cy.visit('/');
});

it('should redirect to login page and show login form', () => {
cy.location('pathname').should('equals', '/sign-in');
cy.get('amplify-authenticator').should('exist');
});

it('should show /registration for non-enabled users', () => {
enterNonEnabledUserHomepage();
cy.location('pathname').should('equals', '/registration');
});

it('should show /client for clients', () => {
enterClientHomepage();
cy.location('pathname').should('equals', '/client');
cy.get('.el-calendar__body');
cy.get('.el-table');
});

it('should show /admin for admin', () => {
enterAdminHomepage();
cy.location('pathname').should('equals', '/admin');
});

it('should show /volunteer for volunteer', () => {
enterVolunteerHomepage();
cy.location('pathname').should('equals', '/volunteer');
cy.get('.volunteer-cal');
});
});
86 changes: 86 additions & 0 deletions sadeaf-web/cypress/integration/assignment-allocated-flow.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import {
clickLogoutButton,
enterAdminHomepage,
enterClientHomepage,
enterVolunteerHomepage,
} from '../helpers/login-helpers';

describe('Correct Opt-In flow', () => {
const newAssignmentName = 'Volunteer opt in success test';

it('should allow clients to create an assignment', () => {
enterClientHomepage();
// open calendar on 21th day
cy.get(':nth-child(5) > :nth-child(6) > .el-calendar-day').click();
// event name
cy.get('.el-form > :nth-child(1) > .el-form-item__content > .el-input > .el-input__inner')
.click()
.type(newAssignmentName);
// event skill
cy.get('.el-checkbox-group > :nth-child(1)').click();
// event purpose
cy.get('[data-test=client-create-event-purpose]').click().type('{downarrow}{enter}');
// event category
cy.get('[data-test=client-create-event-category]').click().type('{downarrow}{enter}');
// event education
cy.get('[data-test=client-create-event-education]').click().type('{downarrow}{enter}');
// assignment timing
cy.get(':nth-child(2) > .el-form-item > .el-form-item__content > :nth-child(1) > .el-input__inner')
.click()
.focus()
.type('{selectall}{backspace} 10:00 {enter}');
cy.get('.el-form-item__content > :nth-child(2) > .el-input__inner')
.click()
.focus()
.type('{selectall}{backspace} 16:00 {enter}');
// address field
cy.get('.el-autocomplete > .el-input > .el-input__inner')
.click()
.type('Singapore Management University')
.wait(4000)
.type('{downarrow}{enter}');
// submit
cy.get('.el-form-item__content > .el-button-group > :nth-child(1)').click();
cy.get(':nth-child(5) > :nth-child(6) > .el-calendar-day').contains(newAssignmentName);
clickLogoutButton();
});

it('should allow volunteers to opt in for an assignment created by a client', () => {
enterVolunteerHomepage();
cy.get('#tab-pendingAssignments').click();
cy.get('#tab-pendingAssignments').click();
cy.wait(1000);
cy.get(':nth-last-child(1) > .header > .el-button').eq(0).click({ force: true });
cy.get('.el-dialog__footer > div > .el-button').click();
cy.get('#tab-optInHistory').click();
cy.get('#pane-optInHistory > :nth-last-child(1) > .assignment-card').contains(newAssignmentName);
clickLogoutButton();
});

it('should allow an admin to match the volunteer', () => {
enterAdminHomepage();
cy.get(
':nth-last-child(1)> .opt-in > .opt-in-details > .select-container > .el-select > .el-input > .el-input__inner'
)
.click()
.type('{downarrow}{enter}', { force: true });
cy.get(':nth-last-child(1) > .opt-in > .opt-in-details > .select-container > .el-button').click({ force: true });
clickLogoutButton();
});

it('should show as matched on volunteer homepage', () => {
enterVolunteerHomepage();
cy.get(':nth-child(5) > :nth-child(6) > .el-calendar-day').click();
cy.get('.el-dialog__body').contains(newAssignmentName);
cy.get('.el-dialog__body').contains('MATCHED');
clickLogoutButton();
});

it('should show as matched on client homepage', () => {
enterClientHomepage();
cy.get(':nth-child(5) > :nth-child(6) > .el-calendar-day').click();
cy.get('.el-dialog__body').contains(newAssignmentName);
cy.get('.el-dialog__body').contains('MATCHED');
cy.get('.el-dialog__body').contains('Test Volunteer');
});
});
63 changes: 63 additions & 0 deletions sadeaf-web/cypress/integration/client-page.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { enterClientHomepage } from '../helpers/login-helpers';

describe('Client Create New Assignment', () => {
beforeEach(() => {
enterClientHomepage();
// open calendar on 20th day
cy.get(':nth-child(4) > :nth-child(5) > .el-calendar-day').click();
});

it('should error when submitting empty new assignment form', () => {
cy.get('.el-form-item__content > .el-button-group > :nth-child(1)').click();
cy.get('.el-dialog__body').contains('Please enter a name for this Event');
cy.get('.el-dialog__body').contains('Please enter a purpose');
cy.get('.el-dialog__body').contains('Please enter an event skill!');
cy.get('.el-dialog__body').contains('Please enter a valid address');
cy.get('.el-dialog__body').contains('Minimum duration is 2 hours');
});

it('should error when submitting assignment timing <2hrs apart', () => {
cy.get(':nth-child(2) > .el-form-item > .el-form-item__content > :nth-child(1) > .el-input__inner')
.click()
.focus()
.type('{selectall}{backspace} 11:00');
cy.get('.el-form-item__content > :nth-child(2) > .el-input__inner')
.click()
.focus()
.type('{selectall}{backspace} 12:00');
cy.get('.el-form-item__content > .el-button-group > :nth-child(1)').click();
cy.get('.el-dialog__body').contains('Minimum duration is 2 hours');
});

it('should submit the form when all fields are correctly filled', () => {
// event name
cy.get('.el-form > :nth-child(1) > .el-form-item__content > .el-input > .el-input__inner')
.click()
.type('Some new assignment');
// event skill
cy.get('.el-checkbox-group > :nth-child(1)').click();
// event purpose
cy.get('[data-test=client-create-event-purpose]').click().type('{downarrow}{enter}');
// event category
cy.get('[data-test=client-create-event-category]').click().type('{downarrow}{enter}');
// event education
cy.get('[data-test=client-create-event-education]').click().type('{downarrow}{enter}');
// assignment timing
cy.get(':nth-child(2) > .el-form-item > .el-form-item__content > :nth-child(1) > .el-input__inner')
.click()
.focus()
.type('{selectall}{backspace} 11:00 {enter}');
cy.get('.el-form-item__content > :nth-child(2) > .el-input__inner')
.click()
.focus()
.type('{selectall}{backspace} 15:00 {enter}');
// address field
cy.get('.el-autocomplete > .el-input > .el-input__inner')
.click()
.type('Singapore Management University')
.wait(4000)
.type('{downarrow}{enter}');
cy.get('.el-form-item__content > .el-button-group > :nth-child(1)').click();
cy.get(':nth-child(4) > :nth-child(5) > .el-calendar-day').contains('Some new assignment');
});
});
32 changes: 32 additions & 0 deletions sadeaf-web/cypress/integration/feedback-flow.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { enterAdminHomepage, enterClientHomepage } from '../helpers/login-helpers';

describe('Feedback Flow', () => {
it('should allow clients to give feedback to fully completed assignments', () => {
// note: there is already a fully completed assigment in mockdata.sql called Feedback Event
enterClientHomepage();
cy.get('[data-test=client-feedback]').click();
cy.get(
'.el-table__fixed-body-wrapper > .el-table__body > tbody > .el-table__row > .el-table_2_column_15 > .cell > .el-button'
).click();
cy.get(':nth-child(3) > .el-form-item__content > .el-radio-group > [tabindex="0"] > .el-radio__input').click();
cy.get(':nth-child(4) > .el-form-item__content > .el-radio-group > [tabindex="0"] > .el-radio__input').click();
cy.get(':nth-child(7) > .el-form-item__content > .el-radio-group > [tabindex="0"] > .el-radio__input').click();
cy.get(':nth-child(8) > .el-form-item__content > .el-radio-group > [tabindex="0"] > .el-radio__input').click();
cy.get(':nth-child(12) > .el-form-item__content > .el-radio-group > [tabindex="0"] > .el-radio__input').click();
cy.get(
':nth-child(19) > .el-form-item__content > .el-radio-group > :nth-child(1) > .el-radio > .el-radio__input'
).click();
cy.get(
':nth-child(20) > .el-form-item__content > .el-radio-group > :nth-child(1) > .el-radio > .el-radio__input'
).click();
cy.get('.el-form-item__content > .el-button').click();
});

it('should allow admins to see completed feedback', () => {
enterAdminHomepage();
cy.get('[data-test=admin-feedback]').click();
cy.get('.main').contains('Feedback Event');
cy.get('.main').contains('Test Client');
cy.get('.main').contains('Test Volunteer');
});
});
21 changes: 21 additions & 0 deletions sadeaf-web/cypress/plugins/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/// <reference types="cypress" />
// ***********************************************************
// This example plugins/index.js can be used to load plugins
//
// You can change the location of this file or turn off loading
// the plugins file with the 'pluginsFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/plugins-guide
// ***********************************************************

// This function is called when a project is opened or re-opened (e.g. due to
// the project's config changing)

/**
* @type {Cypress.PluginConfig}
*/
module.exports = (on, config) => {
// `on` is used to hook into various events Cypress emits
// `config` is the resolved Cypress config
};
Loading

0 comments on commit 57760f5

Please sign in to comment.