Skip to content

Commit

Permalink
Add cypress and tests for election
Browse files Browse the repository at this point in the history
  • Loading branch information
PeterJFB committed Jun 5, 2023
1 parent e2e770b commit 24fcfc7
Show file tree
Hide file tree
Showing 18 changed files with 1,025 additions and 73 deletions.
37 changes: 32 additions & 5 deletions .drone.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ steps:
- push
commands:
- yarn install --frozen-lockfile
volumes:
- name: cache
path: /root/.cache

- name: lint
image: node:16-alpine
Expand Down Expand Up @@ -83,18 +86,36 @@ steps:
REDIS_URL: redis
HOST: 0.0.0.0

- name: playwright
image: mcr.microsoft.com/playwright:v1.30.0-focal
- name: cypress
image: cypress/base:16.18.1
when:
event:
- push
depends_on:
- build
commands:
- ./wait-for-it.sh server:3000 -t 30
- yarn playwright test
- yarn cypress run
environment:
BASE_URL: http://server:3000
MONGO_URL: mongodb://mongodb:27017/vote-test
NODE_ENV: test
volumes:
- name: cache
path: /root/.cache

# - name: playwright
# image: mcr.microsoft.com/playwright:v1.30.0-focal
# when:
# event:
# - push
# depends_on:
# - build
# commands:
# - ./wait-for-it.sh server:3000 -t 30
# - yarn playwright test
# environment:
# BASE_URL: http://server:3000

- name: docker
image: plugins/docker
Expand All @@ -106,7 +127,7 @@ steps:
depends_on:
- lint
- test
- playwright
- cypress
- build
settings:
repo: abakus/vote
Expand Down Expand Up @@ -150,6 +171,12 @@ services:
- name: redis
image: redis:6.0

volumes:
- name: cache
temp: {}

---
kind: signature
hmac: 3d344951a86035c2f80e867438ae2f3ba3f9369ac1b6425ed2bf3bcf641ad5ed
hmac: 869299edaec22c8835972ce311032d280a1a719d964599c315326baa4e49ebbb

...
2 changes: 1 addition & 1 deletion app/controllers/vote.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ export const retrieve: RequestHandler = async (req, res) => {

const vote = await Vote.findOne({ hash: hash }).populate([
{ path: 'priorities' },
{ path: 'election', select: 'title _id' },
{ path: 'election', select: 'title _id type' },
]);

if (!vote) throw new errors.NotFoundError('vote');
Expand Down
170 changes: 170 additions & 0 deletions cypress.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
import { defineConfig } from 'cypress';

import mongoose from 'mongoose';
import env from './env';
import Alternative from './app/models/alternative';
import Election from './app/models/election';
import Vote from './app/models/vote';
import User from './app/models/user';
import Register from './app/models/register';
import { ElectionSystems as ElectionTypes } from './app/types/types';

mongoose.connect(env.MONGO_URL, { dbName: env.MONGO_DB });

export const dropDatabase = () =>
mongoose.connection.dropDatabase().then(() => mongoose.disconnect());

const activeSTVElectionData = {
title: 'activeElectionSTV',
type: ElectionTypes.STV,
description: 'active election STV',
active: true,
};

const activeNormalElectionData = {
title: 'activeElection NORMAL',
type: ElectionTypes.NORMAL,
description: 'active election NORMAL',
active: false,
};

const activeBlankElectionData = {
title: 'activeElection NORMAL - Blank',
type: ElectionTypes.NORMAL,
description: 'active election NORMAL',
active: false,
};

const testAlternative = {
description: 'first test alternative',
};
const testAlternative2 = {
description: 'another test alternative',
};
const testAlternative3 = {
description: 'last test alternative',
};

export default defineConfig({
env: {
NODE_ENV: env.NODE_ENV,
},
e2e: {
baseUrl: process.env.BASE_URL || 'http://localhost:3000',
setupNodeEvents(on, config) {
on('task', {
async clearCollections() {
await Promise.all(
[Alternative, Register, Election, Vote, User].map((collection) =>
collection.deleteMany(null)
)
);
return null;
},
log(m) {
console.log(m);
return null;
},
async createElections() {
const alternatives = [
testAlternative,
testAlternative2,
testAlternative3,
];

const stvElection = await new Election(activeSTVElectionData);

const normalElection = await new Election(activeNormalElectionData);
const blankElection = await new Election(activeBlankElectionData);

const normalAlternatives = await Promise.all(
alternatives.map((alternative) => new Alternative(alternative))
);

const stvAlternatives = await Promise.all(
alternatives.map((alternative) => new Alternative(alternative))
);
const blankAlternatives = await Promise.all(
alternatives.map((alternative) => new Alternative(alternative))
);

for (let i = 0; i < alternatives.length; i++) {
await stvElection.addAlternative(stvAlternatives[i]);
await normalElection.addAlternative(normalAlternatives[i]);
await blankElection.addAlternative(blankAlternatives[i]);
}

return [
stvElection,
normalElection,
blankElection,
stvAlternatives,
normalAlternatives,
];
},
async createUsers() {
const hash =
'$2a$10$qxTI.cWwa2kwcjx4SI9KAuV4KxuhtlGOk33L999UQf1rux.4PBz7y'; // 'password'

const testUser = {
username: 'testuser',
cardKey: '99TESTCARDKEY',
hash,
};

const adminUser = {
username: 'admin',
admin: true,
moderator: true,
cardKey: '55TESTCARDKEY',
hash,
};

const moderatorUser = {
username: 'moderator',
admin: false,
moderator: true,
cardKey: '67TESTCARDKEY',
hash,
};

return await Promise.all(
[testUser, adminUser, moderatorUser].map(async (u) => {
const exists = await User.exists({ username: u.username });
if (exists) return User.findOne({ username: u.username });
return User.create(u);
})
);
},
async setNormalElection() {
const normalElection = await Election.findOne({
title: activeNormalElectionData.title,
});
const stvElection = await Election.findOne({
title: activeSTVElectionData.title,
});
stvElection.active = false;
stvElection.save();

normalElection.active = true;
normalElection.save();
return null;
},
async setBlankElection() {
const normalElection = await Election.findOne({
title: activeNormalElectionData.title,
});
const blankElection = await Election.findOne({
title: activeBlankElectionData.title,
});
normalElection.active = false;
normalElection.save();

blankElection.active = true;
blankElection.save();
return null;
},
});
},
},
});
21 changes: 21 additions & 0 deletions cypress.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import type { AlternativeType } from './app/types/types';

declare global {
namespace Cypress {
interface Chainable {
// drag(subject: string, options?: Partial<TypeOptions>): Chainable<Element>
// dismiss(subject: string, options?: Partial<TypeOptions>): Chainable<Element>
// visit(originalFn: CommandOriginalFn, url: string, options: Partial<VisitOptions>): Chainable<Element>

// cypress/support/commands.ts
login(username: string, password: string): Chainable<Element>;
loginAsUser(): Chainable<Element>;
loginAsModerator(): Chainable<Element>;
loginAsAdmin(): Chainable<Element>;
ensurePriorityOrder(alternatives: AlternativeType[]): Chainable<Element>;
ensureConfirmationOrder(
alternatives: AlternativeType[]
): Chainable<Element>;
}
}
}

0 comments on commit 24fcfc7

Please sign in to comment.