Skip to content
This repository has been archived by the owner on Mar 25, 2020. It is now read-only.

Commit

Permalink
Merge pull request #2 from Financial-Times/reports
Browse files Browse the repository at this point in the history
use reports
  • Loading branch information
lc512k authored Jul 21, 2016
2 parents 744c6c1 + c51e1a4 commit 5732328
Show file tree
Hide file tree
Showing 5 changed files with 251 additions and 159 deletions.
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
{
"name": "@financial-times/n-automation",
"main": "build/main.js",
"dependencies": {},
"dependencies": {
"fs": "0.0.2",
"xml2js": "^0.4.17"
},
"repository": {
"type": "git",
"url": "https://github.com/Financial-Times/n-automation.git"
Expand Down
23 changes: 23 additions & 0 deletions src/email.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
const REGRESSION_TRANSPORT = process.env.REGRESSION_TRANSPORT;
const RECIPIENTS = process.env.REGRESSION_RECIPIENTS;

const nodemailer = require('nodemailer');
const transporter = nodemailer.createTransport(REGRESSION_TRANSPORT);
const logger = require('@financial-times/n-logger').default.logger;

module.exports = function sendEmails (err, output) {

const options = {
from: '"Signup Regression" <no-reply@ft.com>',
to: RECIPIENTS,
subject: `❗Regression tests failed ${new Date()}`,
text: output.replace('[0;37m ','').replace('[41m ', '').replace('[42m ', '').replace('[44m ', '').replace('[45m ', '')
};

transporter.sendMail(options, function (emailError, data) {
if (emailError) {
return logger.info('Error sending emails', emailError);
}
logger.info('Regression test notification sent to: ', data);
});
};
240 changes: 82 additions & 158 deletions src/main.js
Original file line number Diff line number Diff line change
@@ -1,193 +1,117 @@
'use strict';

const REGRESSION_TRANSPORT = process.env.REGRESSION_TRANSPORT;
const SLACK_URL = process.env.SLACK_URL;
const RECIPIENTS = process.env.REGRESSION_RECIPIENTS;
const SLACK_MENTIONS = process.env.SLACK_MENTIONS;

// TODO exctract to config file
const SUPPORTED_BROWSERS = ['ie8', 'ie9', 'ie10', 'ie11', 'chrome', 'firefox', 'edge', 'safari', 'iPhone6Plus', 'Nexus7'];

const worker = require('@financial-times/n-worker');
const nodemailer = require('nodemailer');
const transporter = nodemailer.createTransport(REGRESSION_TRANSPORT);
const exec = require('child_process').exec;
const fetch = require('isomorphic-fetch');
const parseXML = require('xml2js').parseString;
const fs = require('fs');

let VERBOSE = true;
const util = require('./util');
const sendEmails = require('./email');
const sendSlackNotification = require('./slack');
const logger = require('@financial-times/n-logger').default.logger;

const sendEmails = function (err, output) {
function emptyReportsFolder (path) {
logger.info('Deleting old reports...')

const options = {
from: '"Signup Regression" <no-reply@ft.com>',
to: RECIPIENTS,
subject: `❗Regression tests failed ${new Date()}`,
text: output.replace('[0;37m ','').replace('[41m ', '').replace('[42m ', '').replace('[44m ', '').replace('[45m ', '')
};
const reportNames = fs.readdirSync(path);

transporter.sendMail(options, function (emailError, data) {
if (emailError) {
return console.log('Error sending emails', emailError);
}
console.log('Regression test notification sent to: ', data);
});
};

const sendSlackNotification = function (err, results) {
console.log('sendSlackNotification', err, results)
if (!results) {

// Don't show start message on slack when not in verbose mode
if (VERBOSE) {
const initOptions = {
method: 'POST',
body: JSON.stringify({
username: '(Beta) Signup Tests',
text: `Started ${new Date()}`
}),
headers: {
'Content-type': 'application/json'
}
};
fetch(SLACK_URL, initOptions);
}
return;
for (const name of reportNames) {
fs.unlinkSync(path + name);
}
}

function readReports (path) {

const fields = [];
logger.info('Reading new reports...')
const map = {};

for (const key in results) {
if (results.hasOwnProperty(key)) {
fields.push({
'title': key,
'value': results[key].join(', '),
'short': false
});
}
}
const reportNames = fs.readdirSync(path);

const options = {
method: 'POST',
body: JSON.stringify({
username: '(Beta) Signup Tests',
'attachments': [
{
'fallback': '',

'text': err ? `Some automated tests have failed\n${SLACK_MENTIONS}` :
`${fields.length} of ${fields.length} tests passing`,

'color': err ? 'warning' :
'good',

'fields': fields
}
]
}),
headers: {
'Content-type': 'application/json'
}
};

fetch(SLACK_URL, options);
};

// TODO don't read output, parse result files
const curate = function (stdout, stderr) {
let moreTestResults = true;
const marker = 'Test: ';
const failMarker = 'TEST FAILURE';
const EOL = '\n';
let result = {};
let showedFailure = stdout.indexOf(failMarker) !== -1 ? true : false;

console.log('CURATING:');
console.log('failure', showedFailure, stdout.indexOf(failMarker));
console.log('stderr', stderr);

// We can show failure but succeed on a retry
// only return empty if stderr is present
if (showedFailure && stderr) {
return {};
if (!reportNames) {
logger.info('No reports found!')
}

while (moreTestResults) {

let index = stdout.indexOf(marker);
for (const name of reportNames) {

if (index === -1) {
moreTestResults = false;
break;
}
const xmlContents = fs.readFileSync(`${path}/${name}`, 'utf8');

let testName = stdout.substring(index + marker.length, stdout.indexOf(EOL, index)).replace('[0m', '');
parseXML(xmlContents, function (xmlError, json) {

if (!result[testName]) {
result[testName] = [];
}
// logger.info('\n\n\n\n', JSON.stringify(json))

let browser = null;
let largestIndex = null;
for (const candidate of SUPPORTED_BROWSERS) {
let candidateIndex = stdout.lastIndexOf(candidate, index);
const env = util.getEnvironmentData(name)
const suite = json.testsuites.testsuite[0]; // TODO accomodate multisuite
const suiteInfo = {
name: suite.$.name,
failures: suite.$.failures,
skipped: suite.$.skipped,
time: suite.$.time,
timestamp: suite.$.timestamps,
tests: []
}

if (candidateIndex !== -1 && result[testName].indexOf(candidate) === -1) {
if (!largestIndex || candidateIndex > largestIndex) {
largestIndex = candidateIndex;
browser = candidate;
}
for (const test of suite.testcase) {
suiteInfo.tests.push({
name: test.$.name,
failure: test.failure
})
}
}
if (browser) {
result[testName].push(browser);
}
largestIndex = null;

stdout = stdout.substring(index + marker.length, stdout.length);
if (map[env]) {
map[env].push(suiteInfo)
}
else {
map[env] = [suiteInfo];
};
})
}
return result;
return map;
}

export class Automation {
module.exports = class Automation {

static run () {
console.log('Starting regression tests');
sendSlackNotification();
exec('make regression', {env: process.env}, function (error, stdout, stderr) {
console.log('error', error);
console.log('stdout', stdout);
console.log('stderr', stderr);
const output = curate(stdout, stderr);
console.log('output', output)
static run ({
nightwatchJson,
regressionCommand='make regression',
verbose=true,
packageJson = {},
appName,
appLogo
}={}) {

sendSlackNotification(error || stderr, output);
if (!nightwatchJson) {
throw new Error('must specify nightwtach config path')
}

if (error || stderr) {
console.log('SENDING EMAIL', error, stderr)
sendEmails(stderr, stdout);
}
else {
console.log('NOT SENDING EMAIL', error, stderr)
}
logger.info('Starting regression tests...');
const reportsPath = nightwatchJson.output_folder;
emptyReportsFolder(reportsPath)


sendSlackNotification({
init: true,
appName: appName,
verbose: verbose
});
}

static schedule ({time='0 8 * * 1-5'}={}) {

worker.setup().then(function () {
exec(regressionCommand, {env: process.env}, function (error, stdout, stderr) {
// logger.info('\n\nerror', error);
// logger.info('\n\nstdout', stdout);
// logger.info('\n\nstderr', stderr);

console.log('scheduling', time);
const reports = readReports(reportsPath);

new worker.CronJob({
cronTime: time,
timeZone: 'Europe/London',
onTick: this.run,
onComplete: function () {
console.log('cronjob done');
}
sendSlackNotification({
error: error || stderr, // TODO ONLY non retry errors
reports: reports,
appName: appName,
appLogo: appLogo,
packageJson: packageJson,
verbose: verbose
});

if (error || stderr) {
logger.info('Sending email...', error, stderr)
sendEmails(stderr, stdout);
}
});
}
}
Loading

0 comments on commit 5732328

Please sign in to comment.