Started adding some tests
parent
245c67188b
commit
61c59c8997
15
app.js
15
app.js
|
@ -315,7 +315,13 @@ MongoClient.connect(config.databaseConnectionString, {}, (err, client) => {
|
|||
|
||||
// select DB
|
||||
const dbUriObj = mongodbUri.parse(config.databaseConnectionString);
|
||||
const db = client.db(dbUriObj.database);
|
||||
let db;
|
||||
// if in testing, set the testing DB
|
||||
if(process.env.NODE_ENV === 'test'){
|
||||
db = client.db('testingdb');
|
||||
}else{
|
||||
db = client.db(dbUriObj.database);
|
||||
}
|
||||
|
||||
// setup the collections
|
||||
db.users = db.collection('users');
|
||||
|
@ -326,17 +332,20 @@ MongoClient.connect(config.databaseConnectionString, {}, (err, client) => {
|
|||
db.customers = db.collection('customers');
|
||||
|
||||
// add db to app for routes
|
||||
app.dbClient = client;
|
||||
app.db = db;
|
||||
app.config = config;
|
||||
app.port = app.get('port');
|
||||
|
||||
// run indexing
|
||||
common.runIndexing(app)
|
||||
.then(common.testData(db, app))
|
||||
.then(app.listen(app.get('port')))
|
||||
.then(() => {
|
||||
// lift the app
|
||||
app.emit('appStarted');
|
||||
console.log(colors.green('expressCart running on host: http://localhost:' + app.get('port')));
|
||||
})
|
||||
.catch(() => {
|
||||
.catch((err) => {
|
||||
console.error(colors.red('Error setting up indexes:' + err));
|
||||
process.exit(2);
|
||||
});
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
"productImage": "/uploads/duckworth-jacket/woolfill-jacket_6c39ae23-c0c8-4821-85f4-4b5d64333c62_grande.jpg"
|
||||
},
|
||||
{
|
||||
"productPermalink": "5-panel-cap",
|
||||
"productPermalink": "5-panel-camp-cap",
|
||||
"productTitle": "5 Panel Camp Cap",
|
||||
"productPrice": "48",
|
||||
"productDescription": "<p style=\"margin-bottom: 25px; text-rendering: optimizeLegibility;\">A classic 5 panel hat with our United By Blue logo on the front and an adjustable strap to keep fit and secure. Made with recycled polyester and organic cotton mix.<\/p><ul style=\"margin-right: 0px; margin-bottom: 25px; margin-left: 20px; padding: 0px; text-rendering: optimizeLegibility;\"><li style=\"margin-bottom: 0px;\">Made in New Jersey<\/li><li style=\"margin-bottom: 0px;\">7oz Eco-Twill fabric: 35% organic cotton, 65% recycled PET (plastic water and soda bottles) <\/li><li style=\"margin-bottom: 0px;\">Embossed leather patch<\/li><\/ul><ul class=\"tabs\" style=\"margin-right: 0px; margin-bottom: 25px; margin-left: 20px; padding: 0px; text-rendering: optimizeLegibility; color: rgb(28, 29, 29); font-family: Arapey, serif; line-height: 25.008px;\"><\/ul>",
|
||||
|
@ -79,7 +79,7 @@
|
|||
"productImage" : "/uploads/hudderton-backpack/hudderton-backpack_dc8afb13-448b-49d9-a042-5a163a97de8f_590x.jpg"
|
||||
},
|
||||
{
|
||||
"productPermalink" : "Ayres",
|
||||
"productPermalink" : "ayres-chambray",
|
||||
"productTitle" : "Ayres Chambray",
|
||||
"productPrice" : "77",
|
||||
"productDescription" : "<p style=\"margin-bottom: 25px; text-rendering: optimizeLegibility; color: rgb(34, 35, 35); font-family: Arapey, serif;\">Comfortable and practical, our chambray button down is perfect for travel or days spent on the go. The Ayres Chambray has a rich, washed out indigo color suitable to throw on for any event. Made with sustainable soft chambray featuring two chest pockets with sturdy and scratch resistant corozo buttons.</p><ul class=\"tabs-content\" style=\"margin-right: 0px; margin-bottom: 25px; margin-left: 20px; padding: 0px; text-rendering: optimizeLegibility; color: rgb(34, 35, 35); font-family: Arapey, serif;\"><li style=\"margin-bottom: 0px;\"><span style=\"line-height: 1.4;\">100% Organic Cotton Chambray, 4.9 oz Fabric.</span></li><li style=\"margin-bottom: 0px;\"><span style=\"line-height: 1.4;\">Natural Corozo Buttons.</span></li></ul>",
|
||||
|
@ -92,6 +92,28 @@
|
|||
"productImage" : "/uploads/Ayres Chambray/chambray_5f232530-4331-492a-872c-81c225d6bafd_590x.jpg"
|
||||
}
|
||||
],
|
||||
"customers": [
|
||||
{
|
||||
"email" : "test@test.com",
|
||||
"firstName" : "Testy",
|
||||
"lastName" : "Cles",
|
||||
"address1" : "1 test street",
|
||||
"address2" : "testvile",
|
||||
"country" : "Netherlands",
|
||||
"state" : "",
|
||||
"postcode" : "2000TW",
|
||||
"phone" : "123456789",
|
||||
"password" : "$2a$10$kKjnX1J/CAdgdmLI0WuPY.ILH1c7N8mD0H/ZyUXEfee1mJxJvZIS."
|
||||
}
|
||||
],
|
||||
"users": [
|
||||
{
|
||||
"usersName" : "test",
|
||||
"userEmail" : "test@test.com",
|
||||
"userPassword" : "$2a$10$7jQx/hQOWrRni531b/dHRuH8o1ZP8Yo8g..GpTOF4M7RrEH/pzTMy",
|
||||
"isAdmin" : "false"
|
||||
}
|
||||
],
|
||||
"menu": {
|
||||
"items": [
|
||||
{
|
||||
|
|
|
@ -600,25 +600,69 @@ exports.runIndexing = (app) => {
|
|||
});
|
||||
};
|
||||
|
||||
exports.testData = (db, app) => {
|
||||
db.products.count({})
|
||||
exports.dropTestData = (db) => {
|
||||
Promise.all([
|
||||
db.products.drop(),
|
||||
db.users.drop(),
|
||||
db.customers.drop()
|
||||
])
|
||||
.then((err) => {
|
||||
return Promise.resolve();
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log('Error dropping test data', err);
|
||||
});
|
||||
};
|
||||
|
||||
exports.sampleData = (app) => {
|
||||
const db = app.db;
|
||||
|
||||
db.products.count()
|
||||
.then((products) => {
|
||||
if(products > 0){
|
||||
if(products !== 0){
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
console.info(colors.cyan('No products, inserting test data'));
|
||||
|
||||
console.log('Inserting sample data');
|
||||
const testData = fs.readFileSync('./bin/testdata.json', 'utf-8');
|
||||
const jsonData = JSON.parse(testData);
|
||||
|
||||
// Add sample data
|
||||
return Promise.all([
|
||||
db.products.insertMany(jsonData.products),
|
||||
db.menu.insertOne(jsonData.menu),
|
||||
exports.runIndexing(app)
|
||||
db.menu.insertOne(jsonData.menu)
|
||||
]);
|
||||
});
|
||||
};
|
||||
|
||||
exports.testData = async (app) => {
|
||||
const db = app.db;
|
||||
const testData = fs.readFileSync('./bin/testdata.json', 'utf-8');
|
||||
const jsonData = JSON.parse(testData);
|
||||
|
||||
// TODO: A bit ugly, needs fixing
|
||||
return new Promise((resolve, reject) => {
|
||||
Promise.all([
|
||||
db.users.remove({}, {}),
|
||||
db.customers.remove({}, {}),
|
||||
db.products.remove({}, {})
|
||||
])
|
||||
.then(() => {
|
||||
Promise.all([
|
||||
db.users.insertMany(jsonData.users),
|
||||
db.customers.insertMany(jsonData.customers),
|
||||
db.products.insertMany(jsonData.products),
|
||||
db.menu.insertOne(jsonData.menu)
|
||||
])
|
||||
.then(() => {
|
||||
resolve();
|
||||
})
|
||||
.catch((err) => {
|
||||
console.info(colors.red('Error inserting test data. Check `/bin/testdata.json` is correctly formatted.', err));
|
||||
process.exit(2);
|
||||
reject(err);
|
||||
});
|
||||
})
|
||||
.catch((err) => {
|
||||
reject(err);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
|
File diff suppressed because it is too large
Load Diff
13
package.json
13
package.json
|
@ -5,7 +5,8 @@
|
|||
"private": false,
|
||||
"scripts": {
|
||||
"start": "node app.js",
|
||||
"deploy": "gulp deploy"
|
||||
"deploy": "gulp deploy",
|
||||
"test": "ava test/**/*.js --verbose"
|
||||
},
|
||||
"dependencies": {
|
||||
"ajv": "^6.0.0",
|
||||
|
@ -16,7 +17,7 @@
|
|||
"body-parser": "^1.17.2",
|
||||
"cheerio": "^0.22.0",
|
||||
"colors": "^1.1.2",
|
||||
"connect-mongodb-session": "^1.3.0",
|
||||
"connect-mongodb-session": "^1.4.0",
|
||||
"cookie-parser": "^1.4.3",
|
||||
"express": "^4.15.3",
|
||||
"express-handlebars": "^3.0.0",
|
||||
|
@ -27,8 +28,7 @@
|
|||
"lodash": "^4.13.1",
|
||||
"lunr": "^2.1.5",
|
||||
"moment": "^2.15.2",
|
||||
"mongodb": "^3.0.1",
|
||||
"mongodb-uri": "^0.9.7",
|
||||
"mongodb": "2.2.3",
|
||||
"morgan": "^1.9.0",
|
||||
"multer": "^1.1.0",
|
||||
"nodemailer": "^4.4.1",
|
||||
|
@ -42,6 +42,7 @@
|
|||
"uglifycss": "0.0.27"
|
||||
},
|
||||
"devDependencies": {
|
||||
"ava": "^0.25.0",
|
||||
"eslint": "^3.19.0",
|
||||
"eslint-config-airbnb-base": "^12.1.0",
|
||||
"eslint-config-standard": "^10.2.1",
|
||||
|
@ -53,7 +54,9 @@
|
|||
"gulp-clean-css": "^3.9.2",
|
||||
"gulp-minify": "^2.1.0",
|
||||
"gulp-rename": "^1.2.2",
|
||||
"run-sequence": "^2.2.1"
|
||||
"mongodb-uri": "^0.9.7",
|
||||
"run-sequence": "^2.2.1",
|
||||
"wait.for": "^0.6.6"
|
||||
},
|
||||
"main": "app.js",
|
||||
"keywords": [
|
||||
|
|
|
@ -344,6 +344,27 @@ $(document).ready(function (){
|
|||
}
|
||||
});
|
||||
|
||||
$('#loginForm').on('click', function(e){
|
||||
if(!e.isDefaultPrevented()){
|
||||
e.preventDefault();
|
||||
$.ajax({
|
||||
method: 'POST',
|
||||
url: '/admin/login_action',
|
||||
data: {
|
||||
email: $('#email').val(),
|
||||
password: $('#password').val()
|
||||
}
|
||||
})
|
||||
.done(function(msg){
|
||||
window.location = '/admin';
|
||||
})
|
||||
.fail(function(msg){
|
||||
showNotification(msg.responseJSON.message, 'danger');
|
||||
});
|
||||
}
|
||||
e.preventDefault();
|
||||
});
|
||||
|
||||
// call update settings API
|
||||
$('#customerLogin').on('click', function(e){
|
||||
if(!e.isDefaultPrevented()){
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -39,7 +39,7 @@ router.get('/admin/login', (req, res) => {
|
|||
res.render('login', {
|
||||
title: 'Login',
|
||||
referringUrl: req.header('Referer'),
|
||||
config: common.getConfig(),
|
||||
config: req.app.config,
|
||||
message: common.clearSessionValue(req.session, 'message'),
|
||||
messageType: common.clearSessionValue(req.session, 'messageType'),
|
||||
helpers: req.handlebars.helpers,
|
||||
|
@ -59,17 +59,13 @@ router.post('/admin/login_action', (req, res) => {
|
|||
|
||||
db.users.findOne({userEmail: req.body.email}, (err, user) => {
|
||||
if(err){
|
||||
req.session.message = 'Cannot find user.';
|
||||
req.session.messageType = 'danger';
|
||||
res.redirect('/admin/login');
|
||||
res.status(400).json({message: 'A user with that email does not exist.'});
|
||||
return;
|
||||
}
|
||||
|
||||
// check if user exists with that email
|
||||
if(user === undefined || user === null){
|
||||
req.session.message = 'A user with that email does not exist.';
|
||||
req.session.messageType = 'danger';
|
||||
res.redirect('/admin/login');
|
||||
res.status(400).json({message: 'A user with that email does not exist.'});
|
||||
}else{
|
||||
// we have a user under that email so we compare the password
|
||||
bcrypt.compare(req.body.password, user.userPassword)
|
||||
|
@ -79,12 +75,10 @@ router.post('/admin/login_action', (req, res) => {
|
|||
req.session.usersName = user.usersName;
|
||||
req.session.userId = user._id.toString();
|
||||
req.session.isAdmin = user.isAdmin;
|
||||
res.redirect('/admin');
|
||||
res.status(200).json({message: 'Login successful'});
|
||||
}else{
|
||||
// password is not correct
|
||||
req.session.message = 'Access denied. Check password and try again.';
|
||||
req.session.messageType = 'danger';
|
||||
res.redirect('/admin/login');
|
||||
res.status(400).json({message: 'Access denied. Check password and try again.'});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -106,7 +100,7 @@ router.get('/admin/setup', (req, res) => {
|
|||
req.session.needsSetup = true;
|
||||
res.render('setup', {
|
||||
title: 'Setup',
|
||||
config: common.getConfig(),
|
||||
config: req.app.config,
|
||||
helpers: req.handlebars.helpers,
|
||||
message: common.clearSessionValue(req.session, 'message'),
|
||||
messageType: common.clearSessionValue(req.session, 'messageType'),
|
||||
|
@ -165,9 +159,9 @@ router.get('/admin/settings', common.restrict, (req, res) => {
|
|||
message: common.clearSessionValue(req.session, 'message'),
|
||||
messageType: common.clearSessionValue(req.session, 'messageType'),
|
||||
helpers: req.handlebars.helpers,
|
||||
config: common.getConfig(),
|
||||
footerHtml: typeof common.getConfig().footerHtml !== 'undefined' ? escape.decode(common.getConfig().footerHtml) : null,
|
||||
googleAnalytics: typeof common.getConfig().googleAnalytics !== 'undefined' ? escape.decode(common.getConfig().googleAnalytics) : null
|
||||
config: req.app.config,
|
||||
footerHtml: typeof req.app.config.footerHtml !== 'undefined' ? escape.decode(req.app.config.footerHtml) : null,
|
||||
googleAnalytics: typeof req.app.config.googleAnalytics !== 'undefined' ? escape.decode(req.app.config.googleAnalytics) : null
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -218,7 +212,7 @@ router.get('/admin/settings/menu', common.restrict, async (req, res) => {
|
|||
message: common.clearSessionValue(req.session, 'message'),
|
||||
messageType: common.clearSessionValue(req.session, 'messageType'),
|
||||
helpers: req.handlebars.helpers,
|
||||
config: common.getConfig(),
|
||||
config: req.app.config,
|
||||
menu: common.sortMenu(await common.getMenu(db))
|
||||
});
|
||||
});
|
||||
|
@ -239,7 +233,7 @@ router.get('/admin/settings/pages', common.restrict, (req, res) => {
|
|||
message: common.clearSessionValue(req.session, 'message'),
|
||||
messageType: common.clearSessionValue(req.session, 'messageType'),
|
||||
helpers: req.handlebars.helpers,
|
||||
config: common.getConfig(),
|
||||
config: req.app.config,
|
||||
menu: common.sortMenu(await common.getMenu(db))
|
||||
});
|
||||
});
|
||||
|
@ -257,7 +251,7 @@ router.get('/admin/settings/pages/new', common.restrict, common.checkAccess, asy
|
|||
message: common.clearSessionValue(req.session, 'message'),
|
||||
messageType: common.clearSessionValue(req.session, 'messageType'),
|
||||
helpers: req.handlebars.helpers,
|
||||
config: common.getConfig(),
|
||||
config: req.app.config,
|
||||
menu: common.sortMenu(await common.getMenu(db))
|
||||
});
|
||||
});
|
||||
|
@ -281,14 +275,14 @@ router.get('/admin/settings/pages/edit/:page', common.restrict, common.checkAcce
|
|||
message: common.clearSessionValue(req.session, 'message'),
|
||||
messageType: common.clearSessionValue(req.session, 'messageType'),
|
||||
helpers: req.handlebars.helpers,
|
||||
config: common.getConfig(),
|
||||
config: req.app.config,
|
||||
menu
|
||||
});
|
||||
}else{
|
||||
// 404 it!
|
||||
res.status(404).render('error', {
|
||||
title: '404 Error - Page not found',
|
||||
config: common.getConfig(),
|
||||
config: req.app.config,
|
||||
message: '404 Error - Page not found',
|
||||
helpers: req.handlebars.helpers,
|
||||
showFooter: 'showFooter',
|
||||
|
@ -478,7 +472,7 @@ router.post('/admin/file/upload', common.restrict, common.checkAccess, upload.si
|
|||
|
||||
// delete a file via ajax request
|
||||
router.post('/admin/testEmail', common.restrict, (req, res) => {
|
||||
let config = common.getConfig();
|
||||
let config = req.app.config;
|
||||
// TODO: Should fix this to properly handle result
|
||||
common.sendEmail(config.emailAddress, 'expressCart test email', 'Your email settings are working');
|
||||
res.status(200).json({message: 'Test email sent'});
|
||||
|
|
|
@ -74,7 +74,7 @@ router.get('/admin/customer/view/:id?', common.restrict, (req, res) => {
|
|||
session: req.session,
|
||||
message: common.clearSessionValue(req.session, 'message'),
|
||||
messageType: common.clearSessionValue(req.session, 'messageType'),
|
||||
config: common.getConfig(),
|
||||
config: req.app.config,
|
||||
editor: true,
|
||||
helpers: req.handlebars.helpers
|
||||
});
|
||||
|
@ -94,7 +94,7 @@ router.get('/admin/customers', common.restrict, (req, res) => {
|
|||
helpers: req.handlebars.helpers,
|
||||
message: common.clearSessionValue(req.session, 'message'),
|
||||
messageType: common.clearSessionValue(req.session, 'messageType'),
|
||||
config: common.getConfig()
|
||||
config: req.app.config
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -119,7 +119,7 @@ router.get('/admin/customers/filter/:search', common.restrict, (req, res, next)
|
|||
title: 'Customer results',
|
||||
customers: customers,
|
||||
admin: true,
|
||||
config: common.getConfig(),
|
||||
config: req.app.config,
|
||||
session: req.session,
|
||||
searchTerm: searchTerm,
|
||||
message: common.clearSessionValue(req.session, 'message'),
|
||||
|
@ -130,7 +130,7 @@ router.get('/admin/customers/filter/:search', common.restrict, (req, res, next)
|
|||
});
|
||||
|
||||
// login the customer and check the password
|
||||
router.post('/customer/login_action', (req, res) => {
|
||||
router.post('/customer/login_action', async (req, res) => {
|
||||
let db = req.app.db;
|
||||
|
||||
db.customers.findOne({email: req.body.loginEmail}, (err, customer) => { // eslint-disable-line
|
||||
|
@ -178,7 +178,7 @@ router.get('/customer/forgotten', (req, res) => {
|
|||
title: 'Forgotten',
|
||||
route: 'customer',
|
||||
forgotType: 'customer',
|
||||
config: common.getConfig(),
|
||||
config: req.app.config,
|
||||
helpers: req.handlebars.helpers,
|
||||
message: common.clearSessionValue(req.session, 'message'),
|
||||
messageType: common.clearSessionValue(req.session, 'messageType'),
|
||||
|
@ -189,7 +189,7 @@ router.get('/customer/forgotten', (req, res) => {
|
|||
// forgotten password
|
||||
router.post('/customer/forgotten_action', (req, res) => {
|
||||
const db = req.app.db;
|
||||
const config = common.getConfig();
|
||||
const config = req.app.config;
|
||||
let passwordToken = randtoken.generate(30);
|
||||
|
||||
// find the user
|
||||
|
@ -240,7 +240,7 @@ router.get('/customer/reset/:token', (req, res) => {
|
|||
title: 'Reset password',
|
||||
token: req.params.token,
|
||||
route: 'customer',
|
||||
config: common.getConfig(),
|
||||
config: req.app.config,
|
||||
message: common.clearSessionValue(req.session, 'message'),
|
||||
message_type: common.clearSessionValue(req.session, 'message_type'),
|
||||
show_footer: 'show_footer',
|
||||
|
|
|
@ -6,10 +6,9 @@ const _ = require('lodash');
|
|||
const common = require('../lib/common');
|
||||
|
||||
// These is the customer facing routes
|
||||
|
||||
router.get('/payment/:orderId', async (req, res, next) => {
|
||||
let db = req.app.db;
|
||||
let config = common.getConfig();
|
||||
let config = req.app.config;
|
||||
|
||||
// render the payment complete message
|
||||
db.orders.findOne({_id: common.getId(req.params.orderId)}, async (err, result) => {
|
||||
|
@ -18,7 +17,7 @@ router.get('/payment/:orderId', async (req, res, next) => {
|
|||
}
|
||||
res.render(`${config.themeViews}payment_complete`, {
|
||||
title: 'Payment complete',
|
||||
config: common.getConfig(),
|
||||
config: req.app.config,
|
||||
session: req.session,
|
||||
pageCloseBtn: common.showCartCloseBtn('payment'),
|
||||
result: result,
|
||||
|
@ -32,7 +31,7 @@ router.get('/payment/:orderId', async (req, res, next) => {
|
|||
});
|
||||
|
||||
router.get('/checkout', async (req, res, next) => {
|
||||
let config = common.getConfig();
|
||||
let config = req.app.config;
|
||||
|
||||
// if there is no items in the cart then render a failure
|
||||
if(!req.session.cart){
|
||||
|
@ -45,7 +44,7 @@ router.get('/checkout', async (req, res, next) => {
|
|||
// render the checkout
|
||||
res.render(`${config.themeViews}checkout`, {
|
||||
title: 'Checkout',
|
||||
config: common.getConfig(),
|
||||
config: req.app.config,
|
||||
session: req.session,
|
||||
pageCloseBtn: common.showCartCloseBtn('checkout'),
|
||||
checkout: 'hidden',
|
||||
|
@ -58,7 +57,7 @@ router.get('/checkout', async (req, res, next) => {
|
|||
});
|
||||
|
||||
router.get('/pay', async (req, res, next) => {
|
||||
const config = common.getConfig();
|
||||
const config = req.app.config;
|
||||
|
||||
// if there is no items in the cart then render a failure
|
||||
if(!req.session.cart){
|
||||
|
@ -71,7 +70,7 @@ router.get('/pay', async (req, res, next) => {
|
|||
// render the payment page
|
||||
res.render(`${config.themeViews}pay`, {
|
||||
title: 'Pay',
|
||||
config: common.getConfig(),
|
||||
config: req.app.config,
|
||||
paymentConfig: common.getPaymentConfig(),
|
||||
pageCloseBtn: common.showCartCloseBtn('pay'),
|
||||
session: req.session,
|
||||
|
@ -85,14 +84,14 @@ router.get('/pay', async (req, res, next) => {
|
|||
});
|
||||
|
||||
router.get('/cartPartial', (req, res) => {
|
||||
const config = common.getConfig();
|
||||
const config = req.app.config;
|
||||
|
||||
res.render(`${config.themeViews}cart`, {
|
||||
pageCloseBtn: common.showCartCloseBtn(req.query.path),
|
||||
page: req.query.path,
|
||||
layout: false,
|
||||
helpers: req.handlebars.helpers,
|
||||
config: common.getConfig(),
|
||||
config: req.app.config,
|
||||
session: req.session
|
||||
});
|
||||
});
|
||||
|
@ -100,7 +99,7 @@ router.get('/cartPartial', (req, res) => {
|
|||
// show an individual product
|
||||
router.get('/product/:id', (req, res) => {
|
||||
let db = req.app.db;
|
||||
let config = common.getConfig();
|
||||
let config = req.app.config;
|
||||
|
||||
db.products.findOne({$or: [{_id: common.getId(req.params.id)}, {productPermalink: req.params.id}]}, (err, result) => {
|
||||
// render 404 if page is not published
|
||||
|
@ -115,6 +114,12 @@ router.get('/product/:id', (req, res) => {
|
|||
productOptions = JSON.parse(result.productOptions);
|
||||
}
|
||||
|
||||
// If JSON query param return json instead
|
||||
if(req.query.json === 'true'){
|
||||
res.status(200).json(result);
|
||||
return;
|
||||
}
|
||||
|
||||
// show the view
|
||||
common.getImages(result._id, req, res, async (images) => {
|
||||
res.render(`${config.themeViews}product`, {
|
||||
|
@ -223,10 +228,14 @@ router.post('/product/addtocart', (req, res, next) => {
|
|||
db.products.findOne({_id: common.getId(req.body.productId)}, (err, product) => {
|
||||
if(err){
|
||||
console.error(colors.red('Error adding to cart', err));
|
||||
return res.status(400).json({message: 'Error updating cart. Please try again.'});
|
||||
}
|
||||
|
||||
// No product found
|
||||
if(!product){
|
||||
return res.status(400).json({message: 'Error updating cart. Please try again.'});
|
||||
}
|
||||
|
||||
// We item is found, add it to the cart
|
||||
if(product){
|
||||
let productPrice = parseFloat(product.productPrice).toFixed(2);
|
||||
|
||||
// Doc used to test if existing in the cart with the options. If not found, we add new.
|
||||
|
@ -271,10 +280,7 @@ router.post('/product/addtocart', (req, res, next) => {
|
|||
|
||||
// update how many products in the shopping cart
|
||||
req.session.cartTotalItems = Object.keys(req.session.cart).length;
|
||||
res.status(200).json({message: 'Cart successfully updated', totalCartItems: Object.keys(req.session.cart).length});
|
||||
}else{
|
||||
res.status(400).json({message: 'Error updating cart. Please try again.'});
|
||||
}
|
||||
return res.status(200).json({message: 'Cart successfully updated', totalCartItems: Object.keys(req.session.cart).length});
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -283,7 +289,7 @@ router.get('/search/:searchTerm/:pageNum?', (req, res) => {
|
|||
let db = req.app.db;
|
||||
let searchTerm = req.params.searchTerm;
|
||||
let productsIndex = req.app.productsIndex;
|
||||
let config = common.getConfig();
|
||||
let config = req.app.config;
|
||||
let numberProducts = config.productsPerPage ? config.productsPerPage : 6;
|
||||
|
||||
let lunrIdArray = [];
|
||||
|
@ -301,12 +307,18 @@ router.get('/search/:searchTerm/:pageNum?', (req, res) => {
|
|||
common.getMenu(db)
|
||||
])
|
||||
.then(([results, menu]) => {
|
||||
// If JSON query param return json instead
|
||||
if(req.query.json === 'true'){
|
||||
res.status(200).json(results.data);
|
||||
return;
|
||||
}
|
||||
|
||||
res.render(`${config.themeViews}index`, {
|
||||
title: 'Results',
|
||||
results: results.data,
|
||||
filtered: true,
|
||||
session: req.session,
|
||||
metaDescription: common.getConfig().cartTitle + ' - Search term: ' + searchTerm,
|
||||
metaDescription: req.app.config.cartTitle + ' - Search term: ' + searchTerm,
|
||||
searchTerm: searchTerm,
|
||||
pageCloseBtn: common.showCartCloseBtn('search'),
|
||||
message: common.clearSessionValue(req.session, 'message'),
|
||||
|
@ -331,7 +343,7 @@ router.get('/category/:cat/:pageNum?', (req, res) => {
|
|||
let db = req.app.db;
|
||||
let searchTerm = req.params.cat;
|
||||
let productsIndex = req.app.productsIndex;
|
||||
let config = common.getConfig();
|
||||
let config = req.app.config;
|
||||
let numberProducts = config.productsPerPage ? config.productsPerPage : 6;
|
||||
|
||||
let lunrIdArray = [];
|
||||
|
@ -351,13 +363,19 @@ router.get('/category/:cat/:pageNum?', (req, res) => {
|
|||
.then(([results, menu]) => {
|
||||
const sortedMenu = common.sortMenu(menu);
|
||||
|
||||
// If JSON query param return json instead
|
||||
if(req.query.json === 'true'){
|
||||
res.status(200).json(results.data);
|
||||
return;
|
||||
}
|
||||
|
||||
res.render(`${config.themeViews}index`, {
|
||||
title: 'Category',
|
||||
results: results.data,
|
||||
filtered: true,
|
||||
session: req.session,
|
||||
searchTerm: searchTerm,
|
||||
metaDescription: common.getConfig().cartTitle + ' - Category: ' + searchTerm,
|
||||
metaDescription: req.app.config.cartTitle + ' - Category: ' + searchTerm,
|
||||
pageCloseBtn: common.showCartCloseBtn('category'),
|
||||
message: common.clearSessionValue(req.session, 'message'),
|
||||
messageType: common.clearSessionValue(req.session, 'messageType'),
|
||||
|
@ -380,7 +398,7 @@ router.get('/category/:cat/:pageNum?', (req, res) => {
|
|||
// return sitemap
|
||||
router.get('/sitemap.xml', (req, res, next) => {
|
||||
let sm = require('sitemap');
|
||||
let config = common.getConfig();
|
||||
let config = req.app.config;
|
||||
|
||||
common.addSitemapProducts(req, res, (err, products) => {
|
||||
if(err){
|
||||
|
@ -412,7 +430,7 @@ router.get('/sitemap.xml', (req, res, next) => {
|
|||
|
||||
router.get('/page/:pageNum', (req, res, next) => {
|
||||
let db = req.app.db;
|
||||
let config = common.getConfig();
|
||||
let config = req.app.config;
|
||||
let numberProducts = config.productsPerPage ? config.productsPerPage : 6;
|
||||
|
||||
Promise.all([
|
||||
|
@ -420,15 +438,21 @@ router.get('/page/:pageNum', (req, res, next) => {
|
|||
common.getMenu(db)
|
||||
])
|
||||
.then(([results, menu]) => {
|
||||
// If JSON query param return json instead
|
||||
if(req.query.json === 'true'){
|
||||
res.status(200).json(results.data);
|
||||
return;
|
||||
}
|
||||
|
||||
res.render(`${config.themeViews}index`, {
|
||||
title: 'Shop',
|
||||
results: results.data,
|
||||
session: req.session,
|
||||
message: common.clearSessionValue(req.session, 'message'),
|
||||
messageType: common.clearSessionValue(req.session, 'messageType'),
|
||||
metaDescription: common.getConfig().cartTitle + ' - Products page: ' + req.params.pageNum,
|
||||
metaDescription: req.app.config.cartTitle + ' - Products page: ' + req.params.pageNum,
|
||||
pageCloseBtn: common.showCartCloseBtn('page'),
|
||||
config: common.getConfig(),
|
||||
config: req.app.config,
|
||||
productsPerPage: numberProducts,
|
||||
totalProductCount: results.totalProducts,
|
||||
pageNum: req.params.pageNum,
|
||||
|
@ -446,7 +470,7 @@ router.get('/page/:pageNum', (req, res, next) => {
|
|||
// The main entry point of the shop
|
||||
router.get('/:page?', (req, res, next) => {
|
||||
let db = req.app.db;
|
||||
let config = common.getConfig();
|
||||
let config = req.app.config;
|
||||
let numberProducts = config.productsPerPage ? config.productsPerPage : 6;
|
||||
|
||||
// if no page is specified, just render page 1 of the cart
|
||||
|
@ -456,6 +480,12 @@ router.get('/:page?', (req, res, next) => {
|
|||
common.getMenu(db)
|
||||
])
|
||||
.then(([results, menu]) => {
|
||||
// If JSON query param return json instead
|
||||
if(req.query.json === 'true'){
|
||||
res.status(200).json(results.data);
|
||||
return;
|
||||
}
|
||||
|
||||
res.render(`${config.themeViews}index`, {
|
||||
title: `${config.cartTitle} - Shop`,
|
||||
theme: config.theme,
|
||||
|
@ -464,7 +494,7 @@ router.get('/:page?', (req, res, next) => {
|
|||
message: common.clearSessionValue(req.session, 'message'),
|
||||
messageType: common.clearSessionValue(req.session, 'messageType'),
|
||||
pageCloseBtn: common.showCartCloseBtn('page'),
|
||||
config: common.getConfig(),
|
||||
config: req.app.config,
|
||||
productsPerPage: numberProducts,
|
||||
totalProductCount: results.totalProducts,
|
||||
pageNum: 1,
|
||||
|
@ -497,8 +527,8 @@ router.get('/:page?', (req, res, next) => {
|
|||
message: common.clearSessionValue(req.session, 'message'),
|
||||
messageType: common.clearSessionValue(req.session, 'messageType'),
|
||||
pageCloseBtn: common.showCartCloseBtn('page'),
|
||||
config: common.getConfig(),
|
||||
metaDescription: common.getConfig().cartTitle + ' - ' + page,
|
||||
config: req.app.config,
|
||||
metaDescription: req.app.config.cartTitle + ' - ' + page,
|
||||
helpers: req.handlebars.helpers,
|
||||
showFooter: 'showFooter',
|
||||
menu: common.sortMenu(await common.getMenu(db))
|
||||
|
@ -506,7 +536,7 @@ router.get('/:page?', (req, res, next) => {
|
|||
}else{
|
||||
res.status(404).render('error', {
|
||||
title: '404 Error - Page not found',
|
||||
config: common.getConfig(),
|
||||
config: req.app.config,
|
||||
message: '404 Error - Page not found',
|
||||
helpers: req.handlebars.helpers,
|
||||
showFooter: 'showFooter',
|
||||
|
|
|
@ -15,7 +15,7 @@ router.get('/admin/orders', common.restrict, (req, res, next) => {
|
|||
title: 'Cart',
|
||||
orders: orders,
|
||||
admin: true,
|
||||
config: common.getConfig(),
|
||||
config: req.app.config,
|
||||
session: req.session,
|
||||
message: common.clearSessionValue(req.session, 'message'),
|
||||
messageType: common.clearSessionValue(req.session, 'messageType'),
|
||||
|
@ -45,7 +45,7 @@ router.get('/admin/orders/bystatus/:orderstatus', common.restrict, (req, res, ne
|
|||
admin: true,
|
||||
filteredOrders: true,
|
||||
filteredStatus: req.params.orderstatus,
|
||||
config: common.getConfig(),
|
||||
config: req.app.config,
|
||||
session: req.session,
|
||||
message: common.clearSessionValue(req.session, 'message'),
|
||||
messageType: common.clearSessionValue(req.session, 'messageType'),
|
||||
|
@ -69,7 +69,7 @@ router.get('/admin/order/view/:id', common.restrict, (req, res) => {
|
|||
title: 'View order',
|
||||
result: result,
|
||||
productOptions: productOptions,
|
||||
config: common.getConfig(),
|
||||
config: req.app.config,
|
||||
session: req.session,
|
||||
message: common.clearSessionValue(req.session, 'message'),
|
||||
messageType: common.clearSessionValue(req.session, 'messageType'),
|
||||
|
@ -100,7 +100,7 @@ router.get('/admin/orders/filter/:search', common.restrict, (req, res, next) =>
|
|||
title: 'Order results',
|
||||
orders: orders,
|
||||
admin: true,
|
||||
config: common.getConfig(),
|
||||
config: req.app.config,
|
||||
session: req.session,
|
||||
searchTerm: searchTerm,
|
||||
message: common.clearSessionValue(req.session, 'message'),
|
||||
|
|
|
@ -7,7 +7,7 @@ const router = express.Router();
|
|||
// The homepage of the site
|
||||
router.post('/checkout_action', (req, res, next) => {
|
||||
const db = req.app.db;
|
||||
const config = common.getConfig();
|
||||
const config = req.app.config;
|
||||
const authorizenetConfig = common.getPaymentConfig();
|
||||
|
||||
let authorizeUrl = 'https://api.authorize.net/xml/v1/request.api';
|
||||
|
|
|
@ -10,7 +10,7 @@ router.get('/checkout_cancel', (req, res, next) => {
|
|||
|
||||
router.get('/checkout_return', (req, res, next) => {
|
||||
let db = req.app.db;
|
||||
let config = common.getConfig();
|
||||
let config = req.app.config;
|
||||
let paymentId = req.session.paymentId;
|
||||
let payerId = req.query['PayerID'];
|
||||
|
||||
|
@ -107,7 +107,7 @@ router.get('/checkout_return', (req, res, next) => {
|
|||
// The homepage of the site
|
||||
router.post('/checkout_action', (req, res, next) => {
|
||||
let db = req.app.db;
|
||||
let config = common.getConfig();
|
||||
let config = req.app.config;
|
||||
let paypalConfig = common.getPaymentConfig();
|
||||
|
||||
// setup the payment object
|
||||
|
|
|
@ -7,7 +7,7 @@ let router = express.Router();
|
|||
// The homepage of the site
|
||||
router.post('/checkout_action', (req, res, next) => {
|
||||
let db = req.app.db;
|
||||
let config = common.getConfig();
|
||||
let config = req.app.config;
|
||||
let stripeConfig = common.getPaymentConfig();
|
||||
|
||||
// charge via stripe
|
||||
|
|
|
@ -18,7 +18,7 @@ router.get('/admin/products', common.restrict, (req, res, next) => {
|
|||
top_results: topResults,
|
||||
session: req.session,
|
||||
admin: true,
|
||||
config: common.getConfig(),
|
||||
config: req.app.config,
|
||||
message: common.clearSessionValue(req.session, 'message'),
|
||||
messageType: common.clearSessionValue(req.session, 'messageType'),
|
||||
helpers: req.handlebars.helpers
|
||||
|
@ -45,7 +45,7 @@ router.get('/admin/products/filter/:search', (req, res, next) => {
|
|||
title: 'Results',
|
||||
results: results,
|
||||
admin: true,
|
||||
config: common.getConfig(),
|
||||
config: req.app.config,
|
||||
session: req.session,
|
||||
searchTerm: searchTerm,
|
||||
message: common.clearSessionValue(req.session, 'message'),
|
||||
|
@ -69,7 +69,7 @@ router.get('/admin/product/new', common.restrict, common.checkAccess, (req, res)
|
|||
editor: true,
|
||||
admin: true,
|
||||
helpers: req.handlebars.helpers,
|
||||
config: common.getConfig()
|
||||
config: req.app.config
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -167,7 +167,7 @@ router.get('/admin/product/edit/:id', common.restrict, common.checkAccess, (req,
|
|||
session: req.session,
|
||||
message: common.clearSessionValue(req.session, 'message'),
|
||||
messageType: common.clearSessionValue(req.session, 'messageType'),
|
||||
config: common.getConfig(),
|
||||
config: req.app.config,
|
||||
editor: true,
|
||||
helpers: req.handlebars.helpers
|
||||
});
|
||||
|
|
|
@ -15,7 +15,7 @@ router.get('/admin/users', common.restrict, (req, res) => {
|
|||
title: 'Users',
|
||||
users: users,
|
||||
admin: true,
|
||||
config: common.getConfig(),
|
||||
config: req.app.config,
|
||||
isAdmin: req.session.isAdmin,
|
||||
helpers: req.handlebars.helpers,
|
||||
session: req.session,
|
||||
|
@ -49,7 +49,7 @@ router.get('/admin/user/edit/:id', common.restrict, (req, res) => {
|
|||
message: common.clearSessionValue(req.session, 'message'),
|
||||
messageType: common.clearSessionValue(req.session, 'messageType'),
|
||||
helpers: req.handlebars.helpers,
|
||||
config: common.getConfig()
|
||||
config: req.app.config
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -63,7 +63,7 @@ router.get('/admin/user/new', common.restrict, (req, res) => {
|
|||
helpers: req.handlebars.helpers,
|
||||
message: common.clearSessionValue(req.session, 'message'),
|
||||
messageType: common.clearSessionValue(req.session, 'messageType'),
|
||||
config: common.getConfig()
|
||||
config: req.app.config
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -0,0 +1,147 @@
|
|||
const test = require('ava');
|
||||
const axios = require('axios');
|
||||
const fs = require('fs');
|
||||
const app = require('../app');
|
||||
const common = require('../lib/common');
|
||||
|
||||
// Get test data to compare in tests
|
||||
const rawTestData = fs.readFileSync('./bin/testdata.json', 'utf-8');
|
||||
const testData = JSON.parse(rawTestData);
|
||||
|
||||
let config;
|
||||
let db;
|
||||
let baseUrl;
|
||||
let products;
|
||||
let customers;
|
||||
let users;
|
||||
|
||||
// Start up app and wait for it to be ready
|
||||
test.before.cb(t => {
|
||||
app.on('appStarted', async () => {
|
||||
// Set some stuff now we have the app started
|
||||
config = app.config;
|
||||
db = app.db;
|
||||
baseUrl = `http://localhost:${app.port}`;
|
||||
await common.testData(app);
|
||||
products = await db.products.find({}).toArray();
|
||||
customers = await db.customers.find({}).toArray();
|
||||
users = await db.users.find({}).toArray();
|
||||
t.end();
|
||||
});
|
||||
});
|
||||
|
||||
test('[Success] Get products JSON', t => {
|
||||
return new Promise((resolve, reject) => {
|
||||
axios.get(`${baseUrl}?json=true`)
|
||||
.then((response) => {
|
||||
if(response.data.length < config.productsPerPage){
|
||||
t.is(response.data.length, testData.products.length);
|
||||
}else{
|
||||
t.is(response.data.length, config.productsPerPage);
|
||||
}
|
||||
t.pass();
|
||||
resolve();
|
||||
})
|
||||
.catch((error) => {
|
||||
reject(new Error('Should not be allowed'));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('[Success] User Login', t => {
|
||||
return new Promise((resolve, reject) => {
|
||||
axios.post(`${baseUrl}/admin/login_action`, {
|
||||
email: users[0].userEmail,
|
||||
password: 'test'
|
||||
})
|
||||
.then((response) => {
|
||||
t.deepEqual(response.data.message, 'Login successful');
|
||||
resolve();
|
||||
})
|
||||
.catch((error) => {
|
||||
reject(new Error('Should not be allowed'));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('[Fail] Incorrect user password', t => {
|
||||
return new Promise((resolve, reject) => {
|
||||
axios.post(`${baseUrl}/admin/login_action`, {
|
||||
email: users[0].userEmail,
|
||||
password: 'test1'
|
||||
})
|
||||
.then((response) => {
|
||||
reject(new Error('Should not be allowed'));
|
||||
})
|
||||
.catch((error) => {
|
||||
t.deepEqual(error.response.data.message, 'Access denied. Check password and try again.');
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('[Fail] Customer login with incorrect email', t => {
|
||||
return new Promise((resolve, reject) => {
|
||||
axios.post(`${baseUrl}/customer/login_action`, {
|
||||
loginEmail: 'test1@test.com',
|
||||
loginPassword: 'test'
|
||||
})
|
||||
.then((response) => {
|
||||
reject(new Error('Should not be allowed'));
|
||||
})
|
||||
.catch((error) => {
|
||||
t.deepEqual(error.response.data.err, 'A customer with that email does not exist.');
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('[Success] Customer login with correct email', t => {
|
||||
return new Promise((resolve, reject) => {
|
||||
axios.post(`${baseUrl}/customer/login_action`, {
|
||||
loginEmail: 'test@test.com',
|
||||
loginPassword: 'test'
|
||||
})
|
||||
.then((response) => {
|
||||
t.deepEqual(response.data.message, 'Successfully logged in');
|
||||
resolve();
|
||||
})
|
||||
.catch((error) => {
|
||||
reject(new Error('Should not be allowed'));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('[Success] Add product to cart', t => {
|
||||
return new Promise((resolve, reject) => {
|
||||
axios.post(`${baseUrl}/product/addtocart`, {
|
||||
productId: products[0]._id,
|
||||
productQuantity: 1,
|
||||
productOptions: JSON.stringify(products[0].productOptions)
|
||||
})
|
||||
.then((response) => {
|
||||
t.deepEqual(response.data.message, 'Cart successfully updated');
|
||||
resolve();
|
||||
})
|
||||
.catch((error) => {
|
||||
reject(new Error('Should not be allowed'));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('[Fail] Add incorrect product to cart', t => {
|
||||
return new Promise((resolve, reject) => {
|
||||
axios.post(`${baseUrl}/product/addtocart`, {
|
||||
productId: 'someid'
|
||||
})
|
||||
.then((response) => {
|
||||
t.deepEqual(response.data.message, 'Successfully logged in');
|
||||
reject(new Error('Should not be allowed'));
|
||||
resolve();
|
||||
})
|
||||
.catch((error) => {
|
||||
t.deepEqual(error.response.data.message, 'Error updating cart. Please try again.');
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,13 +1,13 @@
|
|||
<div class="col-md-offset-4 col-md-4 col-lg-offset-4 col-lg-4" style="padding-top: 100px" >
|
||||
<form class="form-signin" action="login_action" method="post" role="form" data-toggle="validator">
|
||||
<form class="form-signin" method="post" role="form" data-toggle="validator">
|
||||
<input type="hidden" name="frm_referringUrl" value="{{referringUrl}}">
|
||||
<h2 class="form-signin-heading">Please sign in</h2>
|
||||
<div class="form-group">
|
||||
<input type="email" name="email" class="form-control" placeholder="email address" required autofocus>
|
||||
<input type="email" id="email" name="email" class="form-control" placeholder="email address" required autofocus>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="password" name="password" class="form-control" placeholder="Password" required>
|
||||
<input type="password" id="password" name="password" class="form-control" placeholder="Password" required>
|
||||
</div>
|
||||
<button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
|
||||
<button class="btn btn-lg btn-primary btn-block" id="loginForm" type="submit">Sign in</button>
|
||||
</form>
|
||||
</div>
|
||||
|
|
Loading…
Reference in New Issue