Skip to content
Permalink
Browse files
Merge remote-tracking branch 'origin/login-page-acceptance-tests' int…
…o feature/individual-page
  • Loading branch information
drumevp committed Nov 29, 2019
2 parents 4151588 + e9b83c8 commit 6e2c524b69c3ef26ffd4f6589a42ce23979a15aa
Show file tree
Hide file tree
Showing 13 changed files with 326 additions and 21 deletions.
@@ -1,4 +1,9 @@
#!/bin/sh

echo "running the 'pre-commit' script"

echo "running eslint..."
./node_modules/.bin/eslint .

echo "running tests..."
npm test
@@ -12,7 +12,7 @@ Run `npm run add-data` to fill database with game data.

To run the server, run `npm start`.

To live-reloading, run `npm run watch`.
To start live-reloading, run `npm run watch`.

## Debugging

@@ -30,4 +30,5 @@ This project is split into a few folders:
- `public/`: contains the site's front-end static pages and JavaScript.
- `utils/`: contains shared utility code.
- `views/`: contains dynamic HTML templates.
- `tests/`: contains all tests for the project.
- `./`: contains code that is used directly by the Koa app.
@@ -51,3 +51,118 @@ CREATE TABLE IF NOT EXISTS 'platforms'
);


INSERT INTO `games` VALUES
(1,
'The Last of Us',
'31',
'Hope is the key to survival.',
'Set in the post-apocalyptic United States, the game tells the story of survivors Joel and Ellie as they work together to survive their westward journey across what remains of the country to find a possible cure for the modern fungal plague that has nearly decimated the entire human race.',
'04/06/2013',
'Naughty Dog',
'Sony Computer Entertainment',
1,
'yes',
'tlou.jpg',
'tlousplash.jpg');

INSERT INTO `games` VALUES
(2,
'The Legend of Zelda: Breath of the Wild',
'34,37',
'Step into a world of discovery, exploration and adventure.',
'No kingdom. No memories. After a 100-year slumber, Link wakes up alone in a world he no longer remembers. Now the legendary hero must explore a vast and dangerous land and regain his memories before Hyrule is lost forever. Armed only with what he can scavenge, Link sets out to find answers and the resources needed to survive.',
'03/03/2017',
'Nintendo EPD',
'Nintendo',
2,
'yes',
'botw.jpg',
'botwsplash.jpg');

INSERT INTO `games` VALUES
(3,
"Marvel's Spider-Man",
'36',
'Be Greater.',
'After eight years behind the mask, Peter Parker is a crime-fighting expert. Feel the full power of a more experienced Spider-Man with improvisational combat, dynamic acrobatics, fluid urban traversal, and environmental interactions. A rookie no longer, this is the most masterful Spider-Man you’ve ever played.',
'07/09/2018',
'Insomniac Games',
'Sony Interactive Entertainment',
2,
'yes',
'spiderman.jpg',
'spidermansplash.jpg');

INSERT INTO `games` VALUES
(4,
"Football Manager 2020",
'38,37,39,40,41',
'Your club, your way.',
'Manage your football club, your way. Every decision counts in FM20 with new features rewarding planning and progression like never before, empowering managers to develop both your club’s and your own unique managerial identity.',
'19/11/2019',
'Sports Interactive',
'SEGA',
1,
'yes',
'fm20poster.jpg',
'fm20splash.jpg');

INSERT INTO `games` VALUES
(5,
"Star Wars Jedi: Fallen Order",
'36,35,38',
'Become a Jedi.',
'The Empire seeks to eradicate all Jedi after the execution of Order 66. You, a Jedi Padawan-turned-fugitive, must fight for your survival as you explore the mysteries of a long-extinct civilization in hopes of rebuilding the Jedi Order.',
'15/11/2019',
'Respawn Entertainment',
'Electronic Arts',
2,
'yes',
'starwarsjfoposter.jpg',
'starwarsjfosplash.jpg');

INSERT INTO 'platforms' VALUES (1, 'Atari 2600');
INSERT INTO 'platforms' VALUES (2, 'Color TV-Game');
INSERT INTO 'platforms' VALUES (3, 'Magnavox Odyssey');
INSERT INTO 'platforms' VALUES (4, 'Intellivision');
INSERT INTO 'platforms' VALUES (5, 'Atari 5200');
INSERT INTO 'platforms' VALUES (6, 'ColecoVision');
INSERT INTO 'platforms' VALUES (7, 'Nintendo Entertainment System');
INSERT INTO 'platforms' VALUES (8, 'Master System');
INSERT INTO 'platforms' VALUES (9, 'TurboGrafx-16');
INSERT INTO 'platforms' VALUES (10, 'Sega Genesis');
INSERT INTO 'platforms' VALUES (11, 'Atari Lynx');
INSERT INTO 'platforms' VALUES (12, 'Game Boy');
INSERT INTO 'platforms' VALUES (13, 'SNES');
INSERT INTO 'platforms' VALUES (14, 'Sega Game Gear');
INSERT INTO 'platforms' VALUES (15, 'Philips CD-i');
INSERT INTO 'platforms' VALUES (16, 'Sega Pico');
INSERT INTO 'platforms' VALUES (17, 'Sega Saturn');
INSERT INTO 'platforms' VALUES (18, 'PlayStation');
INSERT INTO 'platforms' VALUES (19, 'Nintendo 64');
INSERT INTO 'platforms' VALUES (20, 'Dreamcast');
INSERT INTO 'platforms' VALUES (21, 'WonderSwan');
INSERT INTO 'platforms' VALUES (22, 'PlayStation 2');
INSERT INTO 'platforms' VALUES (23, 'Xbox');
INSERT INTO 'platforms' VALUES (24, 'Game Boy Advance');
INSERT INTO 'platforms' VALUES (25, 'GameCube');
INSERT INTO 'platforms' VALUES (26, 'N-Gage');
INSERT INTO 'platforms' VALUES (27, 'Nintendo DS');
INSERT INTO 'platforms' VALUES (28, 'PlayStation Portable');
INSERT INTO 'platforms' VALUES (29, 'Xbox 360');
INSERT INTO 'platforms' VALUES (30, 'Nintendo Wii');
INSERT INTO 'platforms' VALUES (31, 'PlayStation 3');
INSERT INTO 'platforms' VALUES (32, 'Nintendo 3DS ');
INSERT INTO 'platforms' VALUES (33, 'PlayStation Vita');
INSERT INTO 'platforms' VALUES (34, 'Wii U');
INSERT INTO 'platforms' VALUES (35, 'Xbox One');
INSERT INTO 'platforms' VALUES (36, 'PlayStation 4');
INSERT INTO 'platforms' VALUES (37, 'Nintendo Switch');
INSERT INTO 'platforms' VALUES (38, 'Microsoft Windows');
INSERT INTO 'platforms' VALUES (39, 'macOS');
INSERT INTO 'platforms' VALUES (40, 'iOS');
INSERT INTO 'platforms' VALUES (41, 'Google Stadia');
INSERT INTO 'platforms' VALUES (42, 'Linux');

INSERT INTO `users` (`username`, `hash`, `isAdmin`) VALUES ('admin', '$2b$12$niVK8DnXKSyYzAIOUun2C.PZ51waVc2NU/e7DQ9cYM6zxNwUiiOCG', 'yes');
INSERT INTO `users` (`username`, `hash`, `isAdmin`) VALUES ('user', '$2b$12$niVK8DnXKSyYzAIOUun2C.PZ51waVc2NU/e7DQ9cYM6zxNwUiiOCG', 'no');
@@ -0,0 +1,18 @@
'use strict'

const fs = require('fs')

async function runSQLScript(db, filename) {
return new Promise((resolve, reject) => {
fs.readFile(filename, 'utf8', async(err, sql) => {
if (err) {
return reject(err)
}
resolve(db.exec(sql))
})
})
}

module.exports = {
runSQLScript
}
@@ -5,12 +5,16 @@ const bcrypt = require('bcrypt')
//Using koabody and bodyparser together breaks the code
const login = new Router({ prefix: '/login' })

const { EntityNotFound } = require('../utils/errors')


login.get('/', async ctx => ctx.render('login.hbs'))

login.post('/', async ctx => {
const { username, password } = ctx.request.body
const redirect = ctx.query.refer || '/homepage'

const user = await ctx.db.getUser(username)
const user = await getUser(ctx.db, username)
if (!user) {
return ctx.render('login.hbs', { errorMsg: 'User does not exist',
user: ctx.session.authorised, admin: await ctx.db.isUserAdmin(ctx.session.userID)})
@@ -19,11 +23,27 @@ login.post('/', async ctx => {
if (await bcrypt.compare(password, user.hash)) {
ctx.session.authorised = true
ctx.session.userID = user.id
return ctx.redirect('homepage')
return ctx.redirect(redirect)
} else {
return ctx.render('login.hbs', { errorMsg: 'Password incorrect', user: ctx.session.authorised,
admin: await ctx.db.isUserAdmin(ctx.session.userID)})
}
})

async function getUser(db, username) {
try {
// try to get the user by username
const user = await db.getUser(username)
return user
} catch (error) {
// if an EntityNotFound error is thrown, return null
if (error instanceof EntityNotFound) {
return null
}

// else re-throw the error
throw error
}
}

module.exports = login
5 db.js
@@ -116,7 +116,8 @@ class DbContext {

async postComment(comment) {
throw new NotImplemented('postComment is not implemented')

}

async getCategories() {
throw new NotImplemented('getCategories is not implemented')
}
@@ -285,11 +286,9 @@ class SqliteDbContext extends DbContext {

async updateGame(game) {
const sqlite = await this.sqlitePromise

// throws errors if entities are nonexistent
await this.getGame(game.id)
await this.getUser(game.submittedBy)

await sqlite.run(
'UPDATE `games` SET `title`= ? , `platforms`=?, `slugline` = ?, `summary`= ? , `releaseDate`=?,'+
'`developer`=?, `publisher`=?, `submittedBy`= ?,`approved`=?,`poster`=?,`splash`=? WHERE `gameID`= ? ;',
@@ -16,5 +16,6 @@ module.exports = {
testPathIgnorePatterns: [
'/node_modules/',
'/__tests__/fixtures/',
'/tests/test.js'
]
}
@@ -7,8 +7,8 @@
"start": "node --use_strict index.js",
"watch": "npx nodemon --harmony --use_strict index.js",
"build-db": "node ./build/build_db.js",
"test": "jest --coverage --runInBand",
"add-data": "node ./build/add_data.js"
"add-data": "node ./build/add_data.js",
"test": "node ./tests/test.js"
},
"author": "",
"license": "ISC",
@@ -34,14 +34,16 @@
"supertest": "^4.0.2"
},
"devDependencies": {
"eslint": "^6.6.0",
"cucumber": "^6.0.5",
"eslint": "^6.5.1",
"eslint-config-standard": "^14.1.0",
"eslint-plugin-import": "^2.18.2",
"eslint-plugin-node": "^10.0.0",
"eslint-plugin-promise": "^4.2.1",
"eslint-plugin-standard": "^4.0.1",
"jest": "^24.9.0",
"nodemon": "^1.19.3",
"puppeteer": "^2.0.0",
"supertest": "^4.0.2"
}
}
@@ -3,18 +3,17 @@
const path = require('path')

const db = require('../db')

const { runSQLScript } = require('../build/utils')
const { runSQLScript } = require('../build/util')

const {
NotImplemented,
EntityNotFound
} = require('./utils/errors')
} = require('../utils/errors')

const User = require('./models/user')
const Game = require('./models/game')
const Game = require('../models/game')
const User = require('../models/user')

const BUILD_DB_SCRIPT = path.join(__dirname, 'build/build_db.sql')
const BUILD_DB_SCRIPT = path.join(__dirname, '../build/build_db.sql')

describe('abstract database context', () => {
const context = new db.DbContext()
@@ -64,20 +63,20 @@ describe('user database with sqlite', () => {
await db.exec('INSERT INTO `users` VALUES (10, \'hakasec\', \'test\'), (11, \'hello\', \'world\');')
})

test('should error when a user is not found', async() => {
await expect(sqliteContext.getUser(42))
.rejects
.toThrowError(new EntityNotFound('user with id 42 not found'))
})

test('should get a user by id', async() => {
expect(await sqliteContext.getUser(10))
.toEqual({ id: 10, username: 'hakasec', hash: 'test' })

expect(await sqliteContext.getUser(1234))
.toBe(null)
})

test('should get a user by username', async() => {
expect(await sqliteContext.getUser('hakasec'))
.toEqual({ id: 10, username: 'hakasec', hash: 'test' })

expect(await sqliteContext.getUser('notauser'))
.toBe(null)
})

test('should get all users', async() => {
@@ -0,0 +1,19 @@
Feature: Login Page

User should be able to log in and access user only parts

Scenario: User logs in successfully
Given username is 'admin' and password is 'hello'
When I try to log in
Then I should be logged in successfully
Then I should be redirected to '/'

Scenario: User provides incorrect password
Given username is 'admin' and password is 'nothello'
When I try to log in
Then I should be asked to try again with an error telling me the password was incorrect

Scenario: User provides incorrect username
Given username is 'notadmin' and password is 'hello'
When I try to log in
Then I should be asked to try again with an error telling me the username doesn't exist

0 comments on commit 6e2c524

Please sign in to comment.