Skip to content

Instantly share code, notes, and snippets.

@pyk
Last active July 31, 2018 16:06
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pyk/dd5b76e2c5fb53ebeae063841d9d6fbd to your computer and use it in GitHub Desktop.
Save pyk/dd5b76e2c5fb53ebeae063841d9d6fbd to your computer and use it in GitHub Desktop.
app.js
// Models is sequelize instance
app.use('/smartphones', smartphonesRouter(models));
const http = require('http');
const puppeteer = require('puppeteer');
const models = require('../models');
let server = null;
let browser = null;
beforeEach(async () => {
// eslint-disable-next-line
const app = require('../app')(models);
server = http.createServer(app);
await models.sequelize.sync();
// Create new brand first
// brandId = models.Brand.create({name: 'Xiaomi'}).id;
await server.listen(0, 'localhost');
browser = await puppeteer.launch();
});
afterEach(async () => {
// Close the server
await server.close();
// Close the browser
await browser.close();
});
test(
'User access smartphone list',
async () => {
// Initialize browser and url
const page = await browser.newPage();
const addr = server.address();
const rootUrl = `http://${addr.address}:${addr.port}`;
const url = `${rootUrl}/smartphones`;
// User access /smartphones
await page.goto(url);
// It should display empty list
const emptySmartphones = await page.$('#emptySmartphones');
expect(emptySmartphones).not.toBe(null);
const linkToNewSmartphone = await page.$('#linkToNewSmartphone');
expect(linkToNewSmartphone).not.toBe(null);
const linkToHome = await page.$('#linkToHome');
expect(linkToHome).not.toBe(null);
},
100000
);
test(
'User create unique smartphone',
async () => {
// Initialize browser and url
const page = await browser.newPage();
const addr = server.address();
const rootUrl = `http://${addr.address}:${addr.port}`;
const url = `${rootUrl}/smartphones/new`;
// Create new brand for this test
const brand = await models.Brand.create({
name: 'Brand #1'
});
// User access /smartphones/new
await page.goto(url);
// User filling the form
const inputSmartphoneName = await page.$('#inputSmartphoneName');
await inputSmartphoneName.type('Redmi 2');
await page.select('select#availableBrands', `${brand.id}`);
const buttonSave = await page.$('#buttonSave');
await buttonSave.click();
await page.waitForNavigation();
// Make sure success message is displayed
const successMessage = await page.$('#successMessage');
expect(successMessage).not.toBe(null);
// Make sure the brand list is displayed
const linkToSmartphoneIndex = await page.$('#linkToSmartphoneIndex');
linkToSmartphoneIndex.click();
await page.waitForNavigation();
const emptySmartphones = await page.$('#emptySmartphones');
const listOfSmartphones = await page.$('#listOfSmartphones');
expect(emptySmartphones).toBe(null);
expect(listOfSmartphones).not.toBe(null);
},
100000
);
test(
'User create duplicate smartphone',
async () => {
// Initialize browser and url
let page = await browser.newPage();
const addr = server.address();
const rootUrl = `http://${addr.address}:${addr.port}`;
const url = `${rootUrl}/smartphones/new`;
// Create new brand for this test
const brand = await models.Brand.create({
name: 'Brand #2'
});
// User access /smartphones/new
await page.goto(url);
// User filling the form
let inputSmartphoneName = await page.$('#inputSmartphoneName');
await inputSmartphoneName.type('Redmi 2');
// Available brands should be displayed
// and select the brand
await page.select('select#availableBrands', `${brand.id}`);
let buttonSave = await page.$('#buttonSave');
await buttonSave.click();
// User reload the page
page = await browser.newPage();
await page.goto(url);
// User fill the form again with the same data
inputSmartphoneName = await page.$('#inputSmartphoneName');
await inputSmartphoneName.type('Redmi 2');
// Available brands should be displayed
// and select the brand
await page.select('select#availableBrands', `${brand.id}`);
buttonSave = await page.$('#buttonSave');
await buttonSave.click();
await page.waitForNavigation();
await page.screenshot({ path: 'debug.png' });
// Make sure, error message are displayed
// await page.screenshot({path: 'debug.png'})
const notUniqueMessage = await page.$('#notUniqueMessage');
expect(notUniqueMessage).not.toBe(null);
},
100000
);
const express = require('express');
/**
* Initialize a Smartphone router
*
* @param {Object} models - Model object from //models/index.js
*/
module.exports = (models) => {
// Initialize new router
const router = express.Router();
// Handle GET /smarphones
// eslint-disable-next-line
router.get('/', async (req, res, next) => {
// Get all smartphones from the database
const title = 'List of smartphones';
const smartphones = await models.Smartphone.findAll();
// Render the view
res.render('smartphones/index', {
title,
smartphones
});
});
// Handle GET /smartphones/new
// eslint-disable-next-line
router.get('/new', async (req, res, next) => {
// Get available brands from database
const title = 'Create new smartphone';
const brands = await models.Brand.findAll();
// Render the view
res.render('smartphones/new', {
title,
brands
});
});
// Handle POST /smartphones/new
// eslint-disable-next-line
router.post('/new', async (req, res, next) => {
// Start new transaction
const transaction = await models.sequelize.transaction();
// Get all brands from the database
const brands = await models.Brand.findAll();
try {
// Initialize model based on reqquest body object
const smartphone = await models.Smartphone.create(req.body, {
transaction
});
await transaction.commit();
// Render success message if everythins is OK
const message = `Smarphone ${smartphone.name} is created`;
res.render('smartphones/new', {
message,
brands,
isSuccess: true
});
} catch (error) {
// Rollback transaction if shit happen
await transaction.rollback();
if (error instanceof models.sequelize.UniqueConstraintError) {
// Notify that brand name is already exists
const message = `Smartphone ${req.body.name} is already exists`;
res.status(409).render('smartphones/new', {
message,
brands,
isNotUnique: true
});
} else {
// Notify user that something bad happen on the server side
const message = '500 Internal server error';
res.status(500).render('smartphones/new', {
message,
brands,
isServerEror: true
});
}
}
});
return router;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment