mirror of
https://github.com/pa11y/pa11y-dashboard.git
synced 2025-09-25 14:51:28 +00:00
Compare commits
40 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
ce9219c01e | ||
![]() |
28a0a861f3 | ||
![]() |
acba762a66 | ||
![]() |
9b80bfa6ab | ||
![]() |
926cb5af3b | ||
![]() |
503ed16265 | ||
![]() |
6d0c6e821b | ||
![]() |
cc5b3f19e5 | ||
![]() |
11e64e27c4 | ||
![]() |
ff4a9fa7b0 | ||
![]() |
5bc32fc68e | ||
![]() |
c2fbcf4fa1 | ||
![]() |
f60d1ca0ce | ||
![]() |
227de3638a | ||
![]() |
79c849d42b | ||
![]() |
8195c5d2c5 | ||
![]() |
568e068613 | ||
![]() |
ee729d1d55 | ||
![]() |
509914d19a | ||
![]() |
9df456c7c1 | ||
![]() |
36dad55bb8 | ||
![]() |
39435f37e4 | ||
![]() |
c562bb07f3 | ||
![]() |
2976d5e391 | ||
![]() |
344efb9da3 | ||
![]() |
c2b1b1d1a1 | ||
![]() |
8c4517c830 | ||
![]() |
40b6e79f81 | ||
![]() |
02ce731e83 | ||
![]() |
4f46351d68 | ||
![]() |
ee7795a7a9 | ||
![]() |
3a3cca881a | ||
![]() |
fa0c523e3f | ||
![]() |
36a677948b | ||
![]() |
22aab6bee2 | ||
![]() |
a30e82d5be | ||
![]() |
71432a3063 | ||
![]() |
6cd7630049 | ||
![]() |
979f7f244b | ||
![]() |
e431fefbd8 |
30
.jscsrc
30
.jscsrc
@@ -2,6 +2,7 @@
|
||||
"disallowEmptyBlocks": true,
|
||||
"disallowImplicitTypeConversion": [
|
||||
"binary",
|
||||
"boolean",
|
||||
"numeric",
|
||||
"string"
|
||||
],
|
||||
@@ -13,8 +14,13 @@
|
||||
"disallowMultipleSpaces": true,
|
||||
"disallowMultipleVarDecl": true,
|
||||
"disallowNewlineBeforeBlockStatements": true,
|
||||
"disallowParenthesesAroundArrowParam": true,
|
||||
"disallowQuotedKeysInObjects": true,
|
||||
"disallowSpaceAfterObjectKeys": true,
|
||||
"disallowSpaceAfterObjectKeys": {
|
||||
"allExcept": [
|
||||
"method"
|
||||
]
|
||||
},
|
||||
"disallowSpaceAfterPrefixUnaryOperators": true,
|
||||
"disallowSpaceBeforeComma": true,
|
||||
"disallowSpaceBeforeSemicolon": true,
|
||||
@@ -26,24 +32,22 @@
|
||||
"disallowSpacesInsideBrackets": true,
|
||||
"disallowSpacesInsideObjectBrackets": true,
|
||||
"disallowSpacesInsideParentheses": true,
|
||||
"disallowSpacesInsideTemplateStringPlaceholders": true,
|
||||
"disallowTrailingComma": true,
|
||||
"disallowTrailingWhitespace": true,
|
||||
"disallowVar": true,
|
||||
"disallowYodaConditions": true,
|
||||
"maximumLineLength": 200,
|
||||
|
||||
"maximumLineLength": 100,
|
||||
|
||||
"requireArrowFunctions": true,
|
||||
"requireBlocksOnNewline": true,
|
||||
"requireCamelCaseOrUpperCaseIdentifiers": true,
|
||||
"requireCapitalizedConstructors": true,
|
||||
"requireCommaBeforeLineBreak": true,
|
||||
"requireCurlyBraces": [
|
||||
"if",
|
||||
"else",
|
||||
"for",
|
||||
"while",
|
||||
"do",
|
||||
"switch",
|
||||
"try",
|
||||
"catch"
|
||||
],
|
||||
"requireCurlyBraces": true,
|
||||
"requireDotNotation": true,
|
||||
"requireFunctionDeclarations": true,
|
||||
"requireLineBreakAfterVariableAssignment": true,
|
||||
"requireLineFeedAtFileEnd": true,
|
||||
"requireObjectKeysOnNewLine": true,
|
||||
@@ -74,6 +78,8 @@
|
||||
"requireSpacesInFunction": {
|
||||
"beforeOpeningCurlyBrace": true
|
||||
},
|
||||
"requireTemplateStrings": true,
|
||||
|
||||
"validateIndentation": "\t",
|
||||
"validateLineBreaks": "LF",
|
||||
"validateNewlineAfterArrayElements": true,
|
||||
|
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"browser": true,
|
||||
"curly": true,
|
||||
"eqeqeq": true,
|
||||
"esversion": 6,
|
||||
"forin": true,
|
||||
"globals": {
|
||||
"after": true,
|
||||
@@ -19,11 +19,8 @@
|
||||
"node": true,
|
||||
"nonew": true,
|
||||
"nonstandard": true,
|
||||
"regexp": true,
|
||||
"shadow": true,
|
||||
"shadow": false,
|
||||
"strict": true,
|
||||
"sub": true,
|
||||
"trailing": true,
|
||||
"undef": true,
|
||||
"unused": true
|
||||
}
|
||||
|
41
CHANGELOG.md
41
CHANGELOG.md
@@ -1,6 +1,47 @@
|
||||
|
||||
# Changelog
|
||||
|
||||
## 2.2.0 (2017-01-27)
|
||||
|
||||
* Add support for Pa11y actions
|
||||
* Update dependencies
|
||||
* pa11y-webservice: ~2.1.2 to ^2.3.0
|
||||
|
||||
## 2.1.2 (2016-12-12)
|
||||
|
||||
* Hide the "add" button in readonly mode
|
||||
* Add a contributing guide
|
||||
|
||||
## 2.1.1 (2016-11-20)
|
||||
|
||||
* Use arrows instead of plus and minus for collapsibles/expanders
|
||||
* Supply more detailed 500 messages
|
||||
|
||||
## 2.1.0 (2016-11-07)
|
||||
|
||||
* Allow for configuration files to be JavaScript rather than JSON
|
||||
* Allow setting of HTTP headers for task runs
|
||||
* Allow hiding/ignoring elements for task runs
|
||||
* Update dependencies and devDependencies
|
||||
* pa11y-webservice: ~2.0.1 to ^2.1.2
|
||||
* mocha: ^3 to ^2 (temporary – tests weren't running)
|
||||
|
||||
## 2.0.1 (2016-09-12)
|
||||
|
||||
* Update dependencies and devDependencies
|
||||
* express: ~4.13 to ~4.14
|
||||
* pa11y-webservice: ~2.0 to ^2.0.1
|
||||
* request: ^2 to ^2.74
|
||||
* mocha: ^2 to ^3
|
||||
* pa11y-webservice-client-node: ~1.2 to ^1.2.1
|
||||
This fixes the following vulnerabilities:
|
||||
* https://nodesecurity.io/advisories/45
|
||||
* https://nodesecurity.io/advisories/63
|
||||
* https://nodesecurity.io/advisories/65
|
||||
* https://nodesecurity.io/advisories/106
|
||||
* https://nodesecurity.io/advisories/121
|
||||
* https://nodesecurity.io/advisories/130
|
||||
|
||||
## 2.0.0 (2016-06-05)
|
||||
|
||||
* Drop Node.js 0.10–0.12 support
|
||||
|
21
CONTRIBUTING.md
Normal file
21
CONTRIBUTING.md
Normal file
@@ -0,0 +1,21 @@
|
||||
|
||||
Contributing Guide
|
||||
==================
|
||||
|
||||
Thanks for getting involved :tada:
|
||||
|
||||
The Pa11y team loves to see new contributors, and we strive to provide a welcoming and inclusive environment. We ask that all contributors read and follow [our code of conduct][code-of-conduct] before joining. If you represent an organisation, then you might find our [guide for companies][companies] helpful.
|
||||
|
||||
Our website outlines the many ways that you can contribute to Pa11y:
|
||||
|
||||
- [Help us to talk to our users][communications]
|
||||
- [Help us out with design][designers]
|
||||
- [Help us with our code][developers]
|
||||
|
||||
|
||||
|
||||
[code-of-conduct]: http://pa11y.org/contributing/code-of-conduct/
|
||||
[communications]: http://pa11y.org/contributing/communications/
|
||||
[companies]: http://pa11y.org/contributing/companies/
|
||||
[designers]: http://pa11y.org/contributing/designers/
|
||||
[developers]: http://pa11y.org/contributing/developers/
|
23
README.md
23
README.md
@@ -22,7 +22,7 @@ Pa11y Dashboard is a web interface to the [Pa11y][pa11y] accessibility reporter;
|
||||
Setup
|
||||
-----
|
||||
|
||||
Pa11y Dashboard requires [Node.js][node] 4+ and [PhantomJS][phantom]. See the [Pa11y][pa11y] documentation for detailed instructions on how to install these dependencies on your operating system.
|
||||
Pa11y Dashboard requires [Node.js][node] 4+. See the [Pa11y][pa11y] documentation for detailed instructions on how to install this on your operating system.
|
||||
|
||||
You'll also need to have [MongoDB][mongo] installed and running. See the [MongoDB install guide][mongo-install] for more information on this.
|
||||
|
||||
@@ -58,6 +58,8 @@ NODE_ENV=development node index.js
|
||||
|
||||
See [development instructions](#development) for more information about running locally (and restarting automatically when files change).
|
||||
|
||||
If you run into problems, check the [troubleshooting guide][troubleshooting].
|
||||
|
||||
|
||||
Configurations
|
||||
--------------
|
||||
@@ -80,10 +82,12 @@ The boot configurations for Pa11y Dashboard are as follows. Look at the sample J
|
||||
This can either be an object containing [Pa11y Webservice configurations][pa11y-webservice-config], or a string which is the base URL of a [Pa11y Webservice][pa11y-webservice] instance you are running separately. If using environment variables, prefix the webservice vars with `WEBSERVICE_`.
|
||||
|
||||
|
||||
Development
|
||||
-----------
|
||||
Contributing
|
||||
------------
|
||||
|
||||
To develop Pa11y Dashboard, you'll need to clone the repo and get set up as outlined in the [setup guide](#setup).
|
||||
There are many ways to contribute to Pa11y Dashboard, we cover these in the [contributing guide](CONTRIBUTING.md) for this repo.
|
||||
|
||||
If you're ready to contribute some code, you'll need to clone the repo and get set up as outlined in the [setup guide](#setup).
|
||||
|
||||
You'll need to start the application in test mode with:
|
||||
|
||||
@@ -111,7 +115,7 @@ make uglify # Compile and uglify the client-side JavaScript
|
||||
|
||||
Useful Resources
|
||||
-------
|
||||
* [Setting up An Accessibility Dashboard from Scratch with Pa11y on DigitialOcean][resource-una-k]
|
||||
* [Setting up An Accessibility Dashboard from Scratch with Pa11y on DigitalOcean][resource-una-k]
|
||||
|
||||
|
||||
Support and Migration
|
||||
@@ -124,7 +128,7 @@ We also maintain a [migration guide](MIGRATION.md) to help you migrate.
|
||||
| :grey_question: | Major Version | Last Minor Release | Node.js Versions | Support End Date |
|
||||
| :-------------- | :------------ | :----------------- | :--------------- | :--------------- |
|
||||
| :heart: | 2 | N/A | 4+ | N/A |
|
||||
| :hourglass: | 1 | 1.12 | 0.10–6 | 2016-12-05 |
|
||||
| :skull: | 1 | 1.12 | 0.10–6 | 2016-12-05 |
|
||||
|
||||
If you're opening issues related to these, please mention the version that the issue relates to.
|
||||
|
||||
@@ -132,8 +136,8 @@ If you're opening issues related to these, please mention the version that the i
|
||||
License
|
||||
-------
|
||||
|
||||
Pa11y Dashboard is licensed under the [GNU General Public License 3.0][info-license].
|
||||
Copyright © 2013–2016, Springer Nature
|
||||
Pa11y Dashboard is licensed under the [GNU General Public License 3.0][info-license].<br/>
|
||||
Copyright © 2013–2017, Team Pa11y
|
||||
|
||||
|
||||
|
||||
@@ -148,11 +152,12 @@ Copyright © 2013–2016, Springer Nature
|
||||
[sidekick-proposal]: https://github.com/pa11y/sidekick/blob/master/PROPOSAL.md
|
||||
[travis]: https://travis-ci.org/pa11y/dashboard
|
||||
[travis-img]: https://travis-ci.org/pa11y/dashboard.png?branch=master
|
||||
[troubleshooting]: https://github.com/pa11y/dashboard/blob/master/TROUBLESHOOTING.md
|
||||
|
||||
[info-license]: LICENSE
|
||||
[info-node]: package.json
|
||||
[info-build]: https://travis-ci.org/pa11y/dashboard
|
||||
[shield-license]: https://img.shields.io/badge/license-GPL%203.0-blue.svg
|
||||
[shield-node]: https://img.shields.io/badge/node.js%20support-4–6-brightgreen.svg
|
||||
[shield-version]: https://img.shields.io/badge/version-2.0.0-blue.svg
|
||||
[shield-version]: https://img.shields.io/badge/version-2.2.0-blue.svg
|
||||
[shield-build]: https://img.shields.io/travis/pa11y/dashboard/master.svg
|
||||
|
27
TROUBLESHOOTING.md
Normal file
27
TROUBLESHOOTING.md
Normal file
@@ -0,0 +1,27 @@
|
||||
Troubleshooting
|
||||
===============
|
||||
|
||||
|
||||
Common issues
|
||||
-----
|
||||
|
||||
* `500` errors or `Could not connect to pa11y-webservice` messages are often related to MongoDB. Ensure that you have the [latest version of MongoDB][mongo-install] installed, and that it's running - it doesn't always start automatically.
|
||||
* Error messages saying that pa11y-webservice isn't running may be due to dependency installation problems. Try deleting your `pa11y-dashboard/node_modules` directory and running `npm install` again.
|
||||
|
||||
|
||||
Check to see if the issue has been reported
|
||||
-----
|
||||
|
||||
* Check the [issue tracker][issues] for similar issues.
|
||||
|
||||
|
||||
Create an issue
|
||||
-----
|
||||
|
||||
If all else fails, [create an issue][create-issue] and we'll help you. Please include your node.js, Phantom, and MongoDB version numbers, and your operating system.
|
||||
|
||||
|
||||
[issues]: https://github.com/pa11y/dashboard/issues?utf8=%E2%9C%93&q=is%3Aissue
|
||||
[mongo-install]: https://docs.mongodb.org/manual/installation/
|
||||
[create-issue]: https://github.com/pa11y/dashboard/issues/new
|
||||
|
44
app.js
44
app.js
@@ -15,14 +15,14 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var bodyParser = require('body-parser');
|
||||
var compression = require('compression');
|
||||
var createClient = require('pa11y-webservice-client-node');
|
||||
var EventEmitter = require('events').EventEmitter;
|
||||
var express = require('express');
|
||||
var hbs = require('express-hbs');
|
||||
var http = require('http');
|
||||
var pkg = require('./package.json');
|
||||
const bodyParser = require('body-parser');
|
||||
const compression = require('compression');
|
||||
const createClient = require('pa11y-webservice-client-node');
|
||||
const EventEmitter = require('events').EventEmitter;
|
||||
const express = require('express');
|
||||
const hbs = require('express-hbs');
|
||||
const http = require('http');
|
||||
const pkg = require('./package.json');
|
||||
|
||||
module.exports = initApp;
|
||||
|
||||
@@ -30,12 +30,12 @@ module.exports = initApp;
|
||||
function initApp(config, callback) {
|
||||
config = defaultConfig(config);
|
||||
|
||||
var webserviceUrl = config.webservice;
|
||||
let webserviceUrl = config.webservice;
|
||||
if (typeof webserviceUrl === 'object') {
|
||||
webserviceUrl = 'http://' + webserviceUrl.host + ':' + webserviceUrl.port + '/';
|
||||
webserviceUrl = `http://${webserviceUrl.host}:${webserviceUrl.port}/`;
|
||||
}
|
||||
|
||||
var app = new EventEmitter();
|
||||
const app = new EventEmitter();
|
||||
app.address = null;
|
||||
app.express = express();
|
||||
app.server = http.createServer(app.express);
|
||||
@@ -45,7 +45,7 @@ function initApp(config, callback) {
|
||||
app.express.use(compression());
|
||||
|
||||
// Public files
|
||||
app.express.use(express.static(__dirname + '/public', {
|
||||
app.express.use(express.static(`${__dirname}/public`, {
|
||||
maxAge: (process.env.NODE_ENV === 'production' ? 604800000 : 0)
|
||||
}));
|
||||
|
||||
@@ -59,11 +59,11 @@ function initApp(config, callback) {
|
||||
app.express.engine('html', hbs.express4({
|
||||
extname: '.html',
|
||||
contentHelperName: 'content',
|
||||
layoutsDir: __dirname + '/view/layout',
|
||||
partialsDir: __dirname + '/view/partial',
|
||||
defaultLayout: __dirname + '/view/layout/default'
|
||||
layoutsDir: `${__dirname}/view/layout`,
|
||||
partialsDir: `${__dirname}/view/partial`,
|
||||
defaultLayout: `${__dirname}/view/layout/default`
|
||||
}));
|
||||
app.express.set('views', __dirname + '/view');
|
||||
app.express.set('views', `${__dirname}/view`);
|
||||
app.express.set('view engine', 'html');
|
||||
|
||||
// View helpers
|
||||
@@ -84,7 +84,7 @@ function initApp(config, callback) {
|
||||
settings: {}
|
||||
};
|
||||
|
||||
app.express.use(function(req, res, next) {
|
||||
app.express.use((req, res, next) => {
|
||||
res.locals.isHomePage = (req.path === '/');
|
||||
res.locals.host = req.hostname;
|
||||
next();
|
||||
@@ -105,11 +105,11 @@ function initApp(config, callback) {
|
||||
}
|
||||
|
||||
// Error handling
|
||||
app.express.get('*', function(req, res) {
|
||||
app.express.get('*', (req, res) => {
|
||||
res.status(404);
|
||||
res.render('404');
|
||||
});
|
||||
app.express.use(function(err, req, res, next) {
|
||||
app.express.use((err, req, res, next) => {
|
||||
/* jshint unused: false */
|
||||
if (err.code === 'ECONNREFUSED') {
|
||||
err = new Error('Could not connect to Pa11y Webservice');
|
||||
@@ -122,9 +122,9 @@ function initApp(config, callback) {
|
||||
res.render('500');
|
||||
});
|
||||
|
||||
app.server.listen(config.port, function(err) {
|
||||
var address = app.server.address();
|
||||
app.address = 'http://' + address.address + ':' + address.port;
|
||||
app.server.listen(config.port, err => {
|
||||
const address = app.server.address();
|
||||
app.address = `http://${address.address}:${address.port}`;
|
||||
callback(err, app);
|
||||
});
|
||||
|
||||
|
10
config.js
10
config.js
@@ -15,11 +15,15 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var fs = require('fs');
|
||||
var jsonPath = './config/' + (process.env.NODE_ENV || 'development') + '.json';
|
||||
const fs = require('fs');
|
||||
const environment = (process.env.NODE_ENV || 'development');
|
||||
const jsonPath = `./config/${environment}.json`;
|
||||
const jsPath = `./config/${environment}.js`;
|
||||
|
||||
if (fs.existsSync(jsonPath)) {
|
||||
module.exports = require(jsonPath);
|
||||
} else if (fs.existsSync(jsPath)) {
|
||||
module.exports = require(jsPath);
|
||||
} else {
|
||||
module.exports = {
|
||||
port: Number(env('PORT', '4000')),
|
||||
@@ -36,6 +40,6 @@ if (fs.existsSync(jsonPath)) {
|
||||
}
|
||||
|
||||
function env(name, defaultValue) {
|
||||
var value = process.env[name];
|
||||
const value = process.env[name];
|
||||
return typeof value === 'string' ? value : defaultValue;
|
||||
}
|
||||
|
16
index.js
16
index.js
@@ -15,24 +15,24 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var chalk = require('chalk');
|
||||
var config = require('./config');
|
||||
const chalk = require('chalk');
|
||||
const config = require('./config');
|
||||
|
||||
process.on('SIGINT', function() {
|
||||
process.on('SIGINT', () => {
|
||||
console.log('\nGracefully shutting down from SIGINT (Ctrl-C)');
|
||||
process.exit();
|
||||
});
|
||||
|
||||
require('./app')(config, function(err, app) {
|
||||
require('./app')(config, (err, app) => {
|
||||
|
||||
console.log('');
|
||||
console.log(chalk.underline.magenta('Pa11y Dashboard started'));
|
||||
console.log(chalk.grey('mode: %s'), process.env.NODE_ENV);
|
||||
console.log(chalk.grey('uri: %s'), app.address);
|
||||
|
||||
app.on('route-error', function(err) {
|
||||
var stack = (err.stack ? err.stack.split('\n') : [err.message]);
|
||||
var msg = chalk.red(stack.shift());
|
||||
app.on('route-error', err => {
|
||||
const stack = (err.stack ? err.stack.split('\n') : [err.message]);
|
||||
const msg = chalk.red(stack.shift());
|
||||
console.error('');
|
||||
console.error(msg);
|
||||
console.error(chalk.grey(stack.join('\n')));
|
||||
@@ -40,7 +40,7 @@ require('./app')(config, function(err, app) {
|
||||
|
||||
// Start the webservice if required
|
||||
if (typeof config.webservice === 'object') {
|
||||
require('pa11y-webservice')(config.webservice, function(err, webservice) {
|
||||
require('pa11y-webservice')(config.webservice, (err, webservice) => {
|
||||
console.log('');
|
||||
console.log(chalk.underline.cyan('Pa11y Webservice started'));
|
||||
console.log(chalk.grey('mode: %s'), process.env.NODE_ENV);
|
||||
|
23
package.json
23
package.json
@@ -1,22 +1,25 @@
|
||||
{
|
||||
"name": "pa11y-dashboard",
|
||||
"version": "2.0.0",
|
||||
"version": "2.2.0",
|
||||
"private": true,
|
||||
|
||||
"description": "Pa11y Dashboard is a visual web interface to the Pa11y accessibility reporter",
|
||||
"keywords": [ "accessibility", "analysis", "report" ],
|
||||
"keywords": [
|
||||
"accessibility",
|
||||
"analysis",
|
||||
"report"
|
||||
],
|
||||
"author": "Team Pa11y",
|
||||
"contributors": [
|
||||
"Perry Harlock (http://www.phwebs.co.uk/)",
|
||||
"Rowan Manning (http://rowanmanning.com/)"
|
||||
],
|
||||
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pa11y/dashboard.git"
|
||||
},
|
||||
"homepage": "https://github.com/pa11y/dashboard",
|
||||
"bugs": "https://github.com/pa11y/dashboard/issues",
|
||||
|
||||
"license": "GPL-3.0",
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
},
|
||||
@@ -24,11 +27,12 @@
|
||||
"body-parser": "~1.15",
|
||||
"chalk": "~1.1",
|
||||
"compression": "~1.6",
|
||||
"express": "~4.13",
|
||||
"express": "~4.14",
|
||||
"express-hbs": "~1.0",
|
||||
"http-headers": "^3.0.1",
|
||||
"moment": "~2.13",
|
||||
"pa11y-webservice": "~2.0",
|
||||
"pa11y-webservice-client-node": "~1.2",
|
||||
"pa11y-webservice": "^2.3.0",
|
||||
"pa11y-webservice-client-node": "^1.2.1",
|
||||
"underscore": "~1.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -39,10 +43,9 @@
|
||||
"less": "~2.7",
|
||||
"mocha": "^2",
|
||||
"proclaim": "^3",
|
||||
"request": "^2",
|
||||
"request": "^2.74",
|
||||
"uglify-js": "~2.6"
|
||||
},
|
||||
|
||||
"scripts": {
|
||||
"start": "node index.js",
|
||||
"test": "make ci"
|
||||
|
@@ -77,11 +77,11 @@ $(document).ready(function(){
|
||||
expandLink.click( function(){
|
||||
$(this).next().slideToggle('slow', function(){});
|
||||
if ($(this).hasClass('showing')) {
|
||||
$(this).find('span.expander').html('+');
|
||||
$(this).find('span.expander').html('↓');
|
||||
$(this).attr('aria-expanded', false);
|
||||
}
|
||||
else {
|
||||
$(this).find('span.expander').html('-');
|
||||
$(this).find('span.expander').html('↑');
|
||||
$(this).attr('aria-expanded', true);
|
||||
}
|
||||
$(this).toggleClass('showing');
|
||||
|
2
public/js/site.min.js
vendored
2
public/js/site.min.js
vendored
File diff suppressed because one or more lines are too long
@@ -15,14 +15,14 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var presentTask = require('../view/presenter/task');
|
||||
const presentTask = require('../view/presenter/task');
|
||||
|
||||
module.exports = route;
|
||||
|
||||
// Route definition
|
||||
function route(app) {
|
||||
app.express.get('/', function(req, res, next) {
|
||||
app.webservice.tasks.get({lastres: true}, function(err, tasks) {
|
||||
app.express.get('/', (req, res, next) => {
|
||||
app.webservice.tasks.get({lastres: true}, (err, tasks) => {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
|
52
route/new.js
52
route/new.js
@@ -13,17 +13,20 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Pa11y Dashboard. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/*jshint maxcomplexity:10*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var getStandards = require('../data/standards');
|
||||
const getStandards = require('../data/standards');
|
||||
const httpHeaders = require('http-headers');
|
||||
|
||||
module.exports = route;
|
||||
|
||||
// Route definition
|
||||
function route(app) {
|
||||
|
||||
app.express.get('/new', function(req, res) {
|
||||
var standards = getStandards().map(function(standard) {
|
||||
app.express.get('/new', (req, res) => {
|
||||
const standards = getStandards().map(standard => {
|
||||
if (standard.title === 'WCAG2AA') {
|
||||
standard.selected = true;
|
||||
}
|
||||
@@ -35,24 +38,45 @@ function route(app) {
|
||||
});
|
||||
});
|
||||
|
||||
app.express.post('/new', function(req, res) {
|
||||
var newTask = {
|
||||
app.express.post('/new', (req, res) => {
|
||||
|
||||
let parsedActions;
|
||||
if (req.body.actions) {
|
||||
parsedActions = req.body.actions.split(/[\r\n]+/)
|
||||
.map(action => {
|
||||
return action.trim();
|
||||
})
|
||||
.filter(action => {
|
||||
return Boolean(action);
|
||||
});
|
||||
}
|
||||
|
||||
let parsedHeaders;
|
||||
if (req.body.headers) {
|
||||
parsedHeaders = httpHeaders(req.body.headers, true);
|
||||
}
|
||||
|
||||
const newTask = {
|
||||
name: req.body.name,
|
||||
url: req.body.url,
|
||||
standard: req.body.standard,
|
||||
ignore: req.body.ignore || [],
|
||||
timeout: req.body.timeout,
|
||||
wait: req.body.wait,
|
||||
username: req.body.username,
|
||||
password: req.body.password
|
||||
timeout: req.body.timeout || undefined,
|
||||
wait: req.body.wait || undefined,
|
||||
actions: parsedActions,
|
||||
username: req.body.username || undefined,
|
||||
password: req.body.password || undefined,
|
||||
headers: parsedHeaders,
|
||||
hideElements: req.body.hideElements || undefined
|
||||
};
|
||||
app.webservice.tasks.create(newTask, function(err, task) {
|
||||
|
||||
app.webservice.tasks.create(newTask, (err, task) => {
|
||||
if (err) {
|
||||
var standards = getStandards().map(function(standard) {
|
||||
const standards = getStandards().map(standard => {
|
||||
if (standard.title === newTask.standard) {
|
||||
standard.selected = true;
|
||||
}
|
||||
standard.rules = standard.rules.map(function(rule) {
|
||||
standard.rules = standard.rules.map(rule => {
|
||||
if (newTask.ignore.indexOf(rule.name) !== -1) {
|
||||
rule.ignored = true;
|
||||
}
|
||||
@@ -60,13 +84,15 @@ function route(app) {
|
||||
});
|
||||
return standard;
|
||||
});
|
||||
newTask.actions = req.body.actions;
|
||||
newTask.headers = req.body.headers;
|
||||
return res.render('new', {
|
||||
error: err,
|
||||
standards: standards,
|
||||
task: newTask
|
||||
});
|
||||
}
|
||||
res.redirect('/' + task.id + '?added');
|
||||
res.redirect(`/${task.id}?added`);
|
||||
});
|
||||
});
|
||||
|
||||
|
@@ -15,7 +15,7 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var moment = require('moment');
|
||||
const moment = require('moment');
|
||||
|
||||
module.exports = route;
|
||||
|
||||
@@ -23,14 +23,14 @@ module.exports = route;
|
||||
function route(app) {
|
||||
|
||||
function getTaskAndResult(req, res, next) {
|
||||
app.webservice.task(req.params.id).get({}, function(err, task) {
|
||||
app.webservice.task(req.params.id).get({}, (err, task) => {
|
||||
if (err) {
|
||||
return next('route');
|
||||
}
|
||||
app.webservice
|
||||
.task(req.params.id)
|
||||
.result(req.params.rid)
|
||||
.get({full: true}, function(err, result) {
|
||||
.get({full: true}, (err, result) => {
|
||||
if (err) {
|
||||
return next('route');
|
||||
}
|
||||
@@ -58,11 +58,11 @@ function route(app) {
|
||||
].join('');
|
||||
}
|
||||
|
||||
app.express.get('/:id/:rid.csv', getTaskAndResult, function(req, res) {
|
||||
var task = res.locals.task;
|
||||
var result = res.locals.result;
|
||||
var rows = ['"code","message","type","context","selector"'];
|
||||
result.results.forEach(function(msg) {
|
||||
app.express.get('/:id/:rid.csv', getTaskAndResult, (req, res) => {
|
||||
const task = res.locals.task;
|
||||
const result = res.locals.result;
|
||||
const rows = ['"code","message","type","context","selector"'];
|
||||
result.results.forEach(msg => {
|
||||
rows.push([
|
||||
JSON.stringify(msg.code),
|
||||
JSON.stringify(msg.message),
|
||||
@@ -75,9 +75,9 @@ function route(app) {
|
||||
res.send(rows.join('\n'));
|
||||
});
|
||||
|
||||
app.express.get('/:id/:rid.json', getTaskAndResult, function(req, res) {
|
||||
var task = res.locals.task;
|
||||
var result = res.locals.result;
|
||||
app.express.get('/:id/:rid.json', getTaskAndResult, (req, res) => {
|
||||
const task = res.locals.task;
|
||||
const result = res.locals.result;
|
||||
res.attachment(getDownloadFileName(task, result, 'json'));
|
||||
delete task.id;
|
||||
delete result.id;
|
||||
|
@@ -15,23 +15,23 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var presentTask = require('../../view/presenter/task');
|
||||
var presentResult = require('../../view/presenter/result');
|
||||
const presentTask = require('../../view/presenter/task');
|
||||
const presentResult = require('../../view/presenter/result');
|
||||
|
||||
module.exports = route;
|
||||
|
||||
// Route definition
|
||||
function route(app) {
|
||||
|
||||
app.express.get('/:id/:rid', function(req, res, next) {
|
||||
app.webservice.task(req.params.id).get({}, function(err, task) {
|
||||
app.express.get('/:id/:rid', (req, res, next) => {
|
||||
app.webservice.task(req.params.id).get({}, (err, task) => {
|
||||
if (err) {
|
||||
return next();
|
||||
}
|
||||
app.webservice
|
||||
.task(req.params.id)
|
||||
.result(req.params.rid)
|
||||
.get({full: true}, function(err, result) {
|
||||
.get({full: true}, (err, result) => {
|
||||
if (err) {
|
||||
return next();
|
||||
}
|
||||
|
@@ -15,15 +15,15 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var presentTask = require('../../view/presenter/task');
|
||||
const presentTask = require('../../view/presenter/task');
|
||||
|
||||
module.exports = route;
|
||||
|
||||
// Route definition
|
||||
function route(app) {
|
||||
|
||||
app.express.get('/:id/delete', function(req, res, next) {
|
||||
app.webservice.task(req.params.id).get({}, function(err, task) {
|
||||
app.express.get('/:id/delete', (req, res, next) => {
|
||||
app.webservice.task(req.params.id).get({}, (err, task) => {
|
||||
if (err) {
|
||||
return next();
|
||||
}
|
||||
@@ -34,8 +34,8 @@ function route(app) {
|
||||
});
|
||||
});
|
||||
|
||||
app.express.post('/:id/delete', function(req, res, next) {
|
||||
app.webservice.task(req.params.id).remove(function(err) {
|
||||
app.express.post('/:id/delete', (req, res, next) => {
|
||||
app.webservice.task(req.params.id).remove(err => {
|
||||
if (err) {
|
||||
return next();
|
||||
}
|
||||
|
@@ -13,26 +13,29 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Pa11y Dashboard. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/*jshint maxcomplexity:10*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var presentTask = require('../../view/presenter/task');
|
||||
var getStandards = require('../../data/standards');
|
||||
const presentTask = require('../../view/presenter/task');
|
||||
const getStandards = require('../../data/standards');
|
||||
const httpHeaders = require('http-headers');
|
||||
|
||||
module.exports = route;
|
||||
|
||||
// Route definition
|
||||
function route(app) {
|
||||
|
||||
app.express.get('/:id/edit', function(req, res, next) {
|
||||
app.webservice.task(req.params.id).get({}, function(err, task) {
|
||||
app.express.get('/:id/edit', (req, res, next) => {
|
||||
app.webservice.task(req.params.id).get({}, (err, task) => {
|
||||
if (err) {
|
||||
return next();
|
||||
}
|
||||
var standards = getStandards().map(function(standard) {
|
||||
const standards = getStandards().map(standard => {
|
||||
if (standard.title === task.standard) {
|
||||
standard.selected = true;
|
||||
}
|
||||
standard.rules = standard.rules.map(function(rule) {
|
||||
standard.rules = standard.rules.map(rule => {
|
||||
if (task.ignore.indexOf(rule.name) !== -1) {
|
||||
rule.ignored = true;
|
||||
}
|
||||
@@ -40,6 +43,7 @@ function route(app) {
|
||||
});
|
||||
return standard;
|
||||
});
|
||||
task.actions = (task.actions ? task.actions.join('\n') : '');
|
||||
res.render('task/edit', {
|
||||
edited: (typeof req.query.edited !== 'undefined'),
|
||||
standards: standards,
|
||||
@@ -49,25 +53,45 @@ function route(app) {
|
||||
});
|
||||
});
|
||||
|
||||
app.express.post('/:id/edit', function(req, res, next) {
|
||||
app.webservice.task(req.params.id).get({}, function(err, task) {
|
||||
app.express.post('/:id/edit', (req, res, next) => {
|
||||
app.webservice.task(req.params.id).get({}, (err, task) => {
|
||||
if (err) {
|
||||
return next();
|
||||
}
|
||||
const originalActions = req.body.actions;
|
||||
const originalHeaders = req.body.headers;
|
||||
req.body.ignore = req.body.ignore || [];
|
||||
app.webservice.task(req.params.id).edit(req.body, function(err) {
|
||||
req.body.timeout = req.body.timeout || undefined;
|
||||
req.body.wait = req.body.wait || undefined;
|
||||
if (req.body.actions) {
|
||||
req.body.actions = req.body.actions.split(/[\r\n]+/)
|
||||
.map(action => {
|
||||
return action.trim();
|
||||
})
|
||||
.filter(action => {
|
||||
return Boolean(action);
|
||||
});
|
||||
}
|
||||
req.body.username = req.body.username || undefined;
|
||||
req.body.password = req.body.password || undefined;
|
||||
req.body.hideElements = req.body.hideElements || undefined;
|
||||
req.body.headers = httpHeaders(req.body.headers || '', true);
|
||||
app.webservice.task(req.params.id).edit(req.body, err => {
|
||||
if (err) {
|
||||
task.name = req.body.name;
|
||||
task.ignore = req.body.ignore;
|
||||
task.timeout = req.body.timeout;
|
||||
task.wait = req.body.wait;
|
||||
task.actions = originalActions;
|
||||
task.username = req.body.username;
|
||||
task.password = req.body.password;
|
||||
var standards = getStandards().map(function(standard) {
|
||||
task.headers = originalHeaders;
|
||||
task.hideElements = req.body.hideElements;
|
||||
const standards = getStandards().map(standard => {
|
||||
if (standard.title === task.standard) {
|
||||
standard.selected = true;
|
||||
}
|
||||
standard.rules = standard.rules.map(function(rule) {
|
||||
standard.rules = standard.rules.map(rule => {
|
||||
if (task.ignore.indexOf(rule.name) !== -1) {
|
||||
rule.ignored = true;
|
||||
}
|
||||
@@ -82,7 +106,7 @@ function route(app) {
|
||||
isTaskSubPage: true
|
||||
});
|
||||
}
|
||||
res.redirect('/' + req.params.id + '/edit?edited');
|
||||
res.redirect(`/${req.params.id}/edit?edited`);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@@ -5,20 +5,20 @@ module.exports = route;
|
||||
// Route definition
|
||||
function route(app) {
|
||||
|
||||
app.express.post('/:id/ignore', function(req, res, next) {
|
||||
app.webservice.task(req.params.id).get({}, function(err, task) {
|
||||
app.express.post('/:id/ignore', (req, res, next) => {
|
||||
app.webservice.task(req.params.id).get({}, (err, task) => {
|
||||
if (err) {
|
||||
return next();
|
||||
}
|
||||
var edit = {
|
||||
const edit = {
|
||||
name: task.name,
|
||||
ignore: task.ignore
|
||||
};
|
||||
if (typeof req.body.rule === 'string') {
|
||||
edit.ignore.push(req.body.rule);
|
||||
}
|
||||
app.webservice.task(req.params.id).edit(edit, function() {
|
||||
res.redirect('/' + req.params.id + '?rule-ignored');
|
||||
app.webservice.task(req.params.id).edit(edit, () => {
|
||||
res.redirect(`/${req.params.id}?rule-ignored`);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@@ -15,25 +15,25 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var presentTask = require('../../view/presenter/task');
|
||||
var presentResult = require('../../view/presenter/result');
|
||||
var presentResultList = require('../../view/presenter/result-list');
|
||||
const presentTask = require('../../view/presenter/task');
|
||||
const presentResult = require('../../view/presenter/result');
|
||||
const presentResultList = require('../../view/presenter/result-list');
|
||||
|
||||
module.exports = route;
|
||||
|
||||
// Route definition
|
||||
function route(app) {
|
||||
|
||||
app.express.get('/:id', function(req, res, next) {
|
||||
app.webservice.task(req.params.id).get({lastres: true}, function(err, task) {
|
||||
app.express.get('/:id', (req, res, next) => {
|
||||
app.webservice.task(req.params.id).get({lastres: true}, (err, task) => {
|
||||
if (err) {
|
||||
return next();
|
||||
}
|
||||
app.webservice.task(req.params.id).results({}, function(err, results) {
|
||||
app.webservice.task(req.params.id).results({}, (err, results) => {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
var presentedResults = presentResultList(results.map(presentResult));
|
||||
const presentedResults = presentResultList(results.map(presentResult));
|
||||
res.render('task', {
|
||||
task: presentTask(task),
|
||||
results: presentedResults,
|
||||
|
@@ -20,12 +20,12 @@ module.exports = route;
|
||||
// Route definition
|
||||
function route(app) {
|
||||
|
||||
app.express.get('/:id/run', function(req, res, next) {
|
||||
app.webservice.task(req.params.id).run(function(err) {
|
||||
app.express.get('/:id/run', (req, res, next) => {
|
||||
app.webservice.task(req.params.id).run(err => {
|
||||
if (err) {
|
||||
return next();
|
||||
}
|
||||
res.redirect('/' + req.params.id + '?running');
|
||||
res.redirect(`/${req.params.id}?running`);
|
||||
});
|
||||
});
|
||||
|
||||
|
@@ -5,21 +5,21 @@ module.exports = route;
|
||||
// Route definition
|
||||
function route(app) {
|
||||
|
||||
app.express.post('/:id/unignore', function(req, res, next) {
|
||||
app.webservice.task(req.params.id).get({}, function(err, task) {
|
||||
app.express.post('/:id/unignore', (req, res, next) => {
|
||||
app.webservice.task(req.params.id).get({}, (err, task) => {
|
||||
if (err) {
|
||||
return next();
|
||||
}
|
||||
var edit = {
|
||||
const edit = {
|
||||
name: task.name,
|
||||
ignore: task.ignore
|
||||
};
|
||||
var indexOfRule = edit.ignore.indexOf(req.body.rule);
|
||||
const indexOfRule = edit.ignore.indexOf(req.body.rule);
|
||||
if (typeof req.body.rule === 'string' && indexOfRule !== -1) {
|
||||
edit.ignore.splice(indexOfRule, 1);
|
||||
}
|
||||
app.webservice.task(req.params.id).edit(edit, function() {
|
||||
res.redirect('/' + req.params.id + '?rule-unignored');
|
||||
app.webservice.task(req.params.id).edit(edit, () => {
|
||||
res.redirect(`/${req.params.id}?rule-unignored`);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@@ -13,10 +13,11 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Pa11y Dashboard. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// jscs:disable requireArrowFunctions
|
||||
'use strict';
|
||||
|
||||
var cheerio = require('cheerio');
|
||||
var request = require('request');
|
||||
const cheerio = require('cheerio');
|
||||
const request = require('request');
|
||||
|
||||
module.exports = createNavigator;
|
||||
|
||||
|
@@ -13,17 +13,18 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Pa11y Dashboard. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// jscs:disable requireArrowFunctions
|
||||
'use strict';
|
||||
|
||||
var createClient = require('pa11y-webservice-client-node');
|
||||
const createClient = require('pa11y-webservice-client-node');
|
||||
|
||||
module.exports = createWebserviceClient;
|
||||
|
||||
// Create a webservice client
|
||||
function createWebserviceClient(config) {
|
||||
var webserviceUrl = config.webservice;
|
||||
let webserviceUrl = config.webservice;
|
||||
if (typeof webserviceUrl === 'object') {
|
||||
webserviceUrl = 'http://' + webserviceUrl.host + ':' + webserviceUrl.port + '/';
|
||||
webserviceUrl = `http://${webserviceUrl.host}:${webserviceUrl.port}/`;
|
||||
}
|
||||
return createClient(webserviceUrl);
|
||||
}
|
||||
|
@@ -13,14 +13,15 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Pa11y Dashboard. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// jscs:disable maximumLineLength, requireArrowFunctions
|
||||
'use strict';
|
||||
|
||||
var assert = require('proclaim');
|
||||
const assert = require('proclaim');
|
||||
|
||||
describe.only('GET /', function() {
|
||||
|
||||
beforeEach(function(done) {
|
||||
var req = {
|
||||
const req = {
|
||||
method: 'GET',
|
||||
endpoint: '/'
|
||||
};
|
||||
@@ -32,13 +33,13 @@ describe.only('GET /', function() {
|
||||
});
|
||||
|
||||
it('should display an "Add new URL" button', function() {
|
||||
var elem = this.last.dom('[data-test=add-task]');
|
||||
const elem = this.last.dom('[data-test=add-task]');
|
||||
assert.strictEqual(elem.length, 1);
|
||||
assert.strictEqual(elem.eq(0).attr('href'), '/new');
|
||||
});
|
||||
|
||||
it('should display all of the expected tasks', function() {
|
||||
var tasks = this.last.dom('[data-test=task]');
|
||||
const tasks = this.last.dom('[data-test=task]');
|
||||
assert.strictEqual(tasks.length, 3);
|
||||
assert.match(tasks.eq(0).text(), /npg home\s+\(wcag2aa\)/i);
|
||||
assert.match(tasks.eq(1).text(), /npg home\s+\(wcag2aaa\)/i);
|
||||
@@ -46,42 +47,42 @@ describe.only('GET /', function() {
|
||||
});
|
||||
|
||||
it('should have links to each task', function() {
|
||||
var tasks = this.last.dom('[data-test=task]');
|
||||
const tasks = this.last.dom('[data-test=task]');
|
||||
assert.strictEqual(tasks.eq(0).find('[href="/abc000000000000000000001"]').length, 1);
|
||||
assert.strictEqual(tasks.eq(1).find('[href="/abc000000000000000000002"]').length, 1);
|
||||
assert.strictEqual(tasks.eq(2).find('[href="/abc000000000000000000003"]').length, 1);
|
||||
});
|
||||
|
||||
it('should display an "Edit" button for each task', function() {
|
||||
var tasks = this.last.dom('[data-test=task]');
|
||||
const tasks = this.last.dom('[data-test=task]');
|
||||
assert.strictEqual(tasks.eq(0).find('[href="/abc000000000000000000001/edit"]').length, 1);
|
||||
assert.strictEqual(tasks.eq(1).find('[href="/abc000000000000000000002/edit"]').length, 1);
|
||||
assert.strictEqual(tasks.eq(2).find('[href="/abc000000000000000000003/edit"]').length, 1);
|
||||
});
|
||||
|
||||
it('should display a "Delete" button for each task', function() {
|
||||
var tasks = this.last.dom('[data-test=task]');
|
||||
const tasks = this.last.dom('[data-test=task]');
|
||||
assert.strictEqual(tasks.eq(0).find('[href="/abc000000000000000000001/delete"]').length, 1);
|
||||
assert.strictEqual(tasks.eq(1).find('[href="/abc000000000000000000002/delete"]').length, 1);
|
||||
assert.strictEqual(tasks.eq(2).find('[href="/abc000000000000000000003/delete"]').length, 1);
|
||||
});
|
||||
|
||||
it('should display a "Run" button for each task', function() {
|
||||
var tasks = this.last.dom('[data-test=task]');
|
||||
const tasks = this.last.dom('[data-test=task]');
|
||||
assert.strictEqual(tasks.eq(0).find('[href="/abc000000000000000000001/run"]').length, 1);
|
||||
assert.strictEqual(tasks.eq(1).find('[href="/abc000000000000000000002/run"]').length, 1);
|
||||
assert.strictEqual(tasks.eq(2).find('[href="/abc000000000000000000003/run"]').length, 1);
|
||||
});
|
||||
|
||||
it('should display the task result counts if the task has been run', function() {
|
||||
var tasks = this.last.dom('[data-test=task]');
|
||||
const tasks = this.last.dom('[data-test=task]');
|
||||
assert.match(tasks.eq(0).text(), /1\s*errors/i);
|
||||
assert.match(tasks.eq(0).text(), /2\s*warnings/i);
|
||||
assert.match(tasks.eq(0).text(), /3\s*notices/i);
|
||||
});
|
||||
|
||||
it('should display a message indicating that there are no results if the task has not been run', function() {
|
||||
var tasks = this.last.dom('[data-test=task]');
|
||||
const tasks = this.last.dom('[data-test=task]');
|
||||
assert.match(tasks.eq(2).text(), /no results/i);
|
||||
});
|
||||
|
||||
|
@@ -13,14 +13,15 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Pa11y Dashboard. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// jscs:disable maximumLineLength, requireArrowFunctions
|
||||
'use strict';
|
||||
|
||||
var assert = require('proclaim');
|
||||
const assert = require('proclaim');
|
||||
|
||||
describe('GET /new', function() {
|
||||
|
||||
beforeEach(function(done) {
|
||||
var req = {
|
||||
const req = {
|
||||
method: 'GET',
|
||||
endpoint: '/new'
|
||||
};
|
||||
@@ -36,7 +37,7 @@ describe('GET /new', function() {
|
||||
});
|
||||
|
||||
it('should have an "Add new URL" form', function() {
|
||||
var form = this.last.dom('[data-test=new-url-form]').eq(0);
|
||||
const form = this.last.dom('[data-test=new-url-form]').eq(0);
|
||||
assert.isDefined(form);
|
||||
assert.strictEqual(form.attr('action'), '/new');
|
||||
assert.strictEqual(form.attr('method'), 'post');
|
||||
@@ -49,52 +50,69 @@ describe('GET /new', function() {
|
||||
});
|
||||
|
||||
it('should have a "name" field', function() {
|
||||
var field = this.form.find('input[name=name]').eq(0);
|
||||
const field = this.form.find('input[name=name]').eq(0);
|
||||
assert.isDefined(field);
|
||||
assert.strictEqual(field.attr('type'), 'text');
|
||||
assert.strictEqual(field.attr('value'), '');
|
||||
});
|
||||
|
||||
it('should have a "url" field', function() {
|
||||
var field = this.form.find('input[name=url]').eq(0);
|
||||
const field = this.form.find('input[name=url]').eq(0);
|
||||
assert.isDefined(field);
|
||||
assert.strictEqual(field.attr('type'), 'url');
|
||||
assert.strictEqual(field.attr('value'), '');
|
||||
});
|
||||
|
||||
it('should have a "wait" field', function() {
|
||||
var field = this.form.find('input[name=wait]').eq(0);
|
||||
const field = this.form.find('input[name=wait]').eq(0);
|
||||
assert.isDefined(field);
|
||||
assert.strictEqual(field.attr('type'), 'text');
|
||||
assert.strictEqual(field.attr('value'), '');
|
||||
});
|
||||
|
||||
it('should have an "actions" field', function() {
|
||||
const field = this.form.find('textarea[name=actions]').eq(0);
|
||||
assert.isDefined(field);
|
||||
});
|
||||
|
||||
it('should have a "username" field', function() {
|
||||
var field = this.form.find('input[name=username]').eq(0);
|
||||
const field = this.form.find('input[name=username]').eq(0);
|
||||
assert.isDefined(field);
|
||||
assert.strictEqual(field.attr('type'), 'text');
|
||||
assert.strictEqual(field.attr('value'), '');
|
||||
});
|
||||
|
||||
it('should have a "password" field', function() {
|
||||
var field = this.form.find('input[name=password]').eq(0);
|
||||
const field = this.form.find('input[name=password]').eq(0);
|
||||
assert.isDefined(field);
|
||||
assert.strictEqual(field.attr('type'), 'text');
|
||||
assert.strictEqual(field.attr('value'), '');
|
||||
});
|
||||
|
||||
it('should have a "standard" field', function() {
|
||||
var field = this.form.find('select[name=standard]').eq(0);
|
||||
const field = this.form.find('select[name=standard]').eq(0);
|
||||
assert.isDefined(field);
|
||||
assert.strictEqual(field.find('option').length, 4);
|
||||
});
|
||||
|
||||
it('should have "ignore" fields', function() {
|
||||
var fields = this.form.find('input[name="ignore[]"]');
|
||||
const fields = this.form.find('input[name="ignore[]"]');
|
||||
assert.isDefined(fields);
|
||||
assert.notStrictEqual(fields.length, 0);
|
||||
});
|
||||
|
||||
it('should have a "hideElements" field', function() {
|
||||
const field = this.form.find('input[name=hideElements]').eq(0);
|
||||
assert.isDefined(field);
|
||||
assert.strictEqual(field.attr('type'), 'text');
|
||||
assert.strictEqual(field.attr('value'), '');
|
||||
});
|
||||
|
||||
it('should have a "headers" field', function() {
|
||||
const field = this.form.find('textarea[name=headers]').eq(0);
|
||||
assert.isDefined(field);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
@@ -104,7 +122,7 @@ describe('POST /new', function() {
|
||||
describe('with invalid query', function() {
|
||||
|
||||
beforeEach(function(done) {
|
||||
var req = {
|
||||
const req = {
|
||||
method: 'POST',
|
||||
endpoint: '/new',
|
||||
form: {
|
||||
@@ -128,7 +146,7 @@ describe('POST /new', function() {
|
||||
describe('with valid query', function() {
|
||||
|
||||
beforeEach(function(done) {
|
||||
var req = {
|
||||
const req = {
|
||||
method: 'POST',
|
||||
endpoint: '/new',
|
||||
form: {
|
||||
@@ -160,7 +178,7 @@ describe('POST /new', function() {
|
||||
});
|
||||
|
||||
it('should display a success message', function() {
|
||||
var alert = this.last.dom('[data-test=alert]').eq(0);
|
||||
const alert = this.last.dom('[data-test=alert]').eq(0);
|
||||
assert.isDefined(alert);
|
||||
assert.match(alert.textContent, /url has been added/i);
|
||||
});
|
||||
|
@@ -13,14 +13,15 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Pa11y Dashboard. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// jscs:disable maximumLineLength, requireArrowFunctions
|
||||
'use strict';
|
||||
|
||||
var assert = require('proclaim');
|
||||
const assert = require('proclaim');
|
||||
|
||||
describe('GET /<task-id>/<result-id>.csv', function() {
|
||||
|
||||
beforeEach(function(done) {
|
||||
var req = {
|
||||
const req = {
|
||||
method: 'GET',
|
||||
endpoint: '/abc000000000000000000001/def000000000000000000001.csv',
|
||||
nonDom: true
|
||||
@@ -41,7 +42,7 @@ describe('GET /<task-id>/<result-id>.csv', function() {
|
||||
describe('GET /<task-id>/<result-id>.json', function() {
|
||||
|
||||
beforeEach(function(done) {
|
||||
var req = {
|
||||
const req = {
|
||||
method: 'GET',
|
||||
endpoint: '/abc000000000000000000001/def000000000000000000001.json',
|
||||
nonDom: true,
|
||||
@@ -55,7 +56,7 @@ describe('GET /<task-id>/<result-id>.json', function() {
|
||||
});
|
||||
|
||||
it('should output JSON results', function() {
|
||||
var json = this.last.body;
|
||||
const json = this.last.body;
|
||||
assert.strictEqual(json.task.name, 'NPG Home');
|
||||
assert.strictEqual(json.task.url, 'nature.com');
|
||||
assert.strictEqual(json.count.error, 1);
|
||||
|
@@ -13,14 +13,15 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Pa11y Dashboard. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// jscs:disable maximumLineLength, requireArrowFunctions
|
||||
'use strict';
|
||||
|
||||
var assert = require('proclaim');
|
||||
const assert = require('proclaim');
|
||||
|
||||
describe('GET /<task-id>/<result-id>', function() {
|
||||
|
||||
beforeEach(function(done) {
|
||||
var req = {
|
||||
const req = {
|
||||
method: 'GET',
|
||||
endpoint: '/abc000000000000000000001/def000000000000000000001'
|
||||
};
|
||||
@@ -32,13 +33,13 @@ describe('GET /<task-id>/<result-id>', function() {
|
||||
});
|
||||
|
||||
it('should display a "Download CSV" button', function() {
|
||||
var elem = this.last.dom('[data-test=download-csv]');
|
||||
const elem = this.last.dom('[data-test=download-csv]');
|
||||
assert.strictEqual(elem.length, 1);
|
||||
assert.strictEqual(elem.eq(0).attr('href'), '/abc000000000000000000001/def000000000000000000001.csv');
|
||||
});
|
||||
|
||||
it('should display a "Download JSON" button', function() {
|
||||
var elem = this.last.dom('[data-test=download-json]');
|
||||
const elem = this.last.dom('[data-test=download-json]');
|
||||
assert.strictEqual(elem.length, 1);
|
||||
assert.strictEqual(elem.eq(0).attr('href'), '/abc000000000000000000001/def000000000000000000001.json');
|
||||
});
|
||||
@@ -48,19 +49,19 @@ describe('GET /<task-id>/<result-id>', function() {
|
||||
});
|
||||
|
||||
it('should display errors', function() {
|
||||
var elem = this.last.dom('[data-test=task-errors]').eq(0);
|
||||
const elem = this.last.dom('[data-test=task-errors]').eq(0);
|
||||
assert.isDefined(elem);
|
||||
assert.match(elem.text(), /errors \( 1 \)/i);
|
||||
});
|
||||
|
||||
it('should display warnings', function() {
|
||||
var elem = this.last.dom('[data-test=task-warnings]').eq(0);
|
||||
const elem = this.last.dom('[data-test=task-warnings]').eq(0);
|
||||
assert.isDefined(elem);
|
||||
assert.match(elem.text(), /warnings \( 2 \)/i);
|
||||
});
|
||||
|
||||
it('should display notices', function() {
|
||||
var elem = this.last.dom('[data-test=task-notices]').eq(0);
|
||||
const elem = this.last.dom('[data-test=task-notices]').eq(0);
|
||||
assert.isDefined(elem);
|
||||
assert.match(elem.text(), /notices \( 3 \)/i);
|
||||
});
|
||||
|
@@ -13,14 +13,15 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Pa11y Dashboard. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// jscs:disable maximumLineLength, requireArrowFunctions
|
||||
'use strict';
|
||||
|
||||
var assert = require('proclaim');
|
||||
const assert = require('proclaim');
|
||||
|
||||
describe('GET /<task-id>/delete', function() {
|
||||
|
||||
beforeEach(function(done) {
|
||||
var req = {
|
||||
const req = {
|
||||
method: 'GET',
|
||||
endpoint: '/abc000000000000000000001/delete'
|
||||
};
|
||||
@@ -32,7 +33,7 @@ describe('GET /<task-id>/delete', function() {
|
||||
});
|
||||
|
||||
it('should have a "Delete URL" form', function() {
|
||||
var form = this.last.dom('[data-test=delete-url-form]').eq(0);
|
||||
const form = this.last.dom('[data-test=delete-url-form]').eq(0);
|
||||
assert.isDefined(form);
|
||||
assert.strictEqual(form.attr('action'), '/abc000000000000000000001/delete');
|
||||
assert.strictEqual(form.attr('method'), 'post');
|
||||
@@ -47,7 +48,7 @@ describe('GET /<task-id>/delete', function() {
|
||||
describe('POST /<task-id>/delete', function() {
|
||||
|
||||
beforeEach(function(done) {
|
||||
var req = {
|
||||
const req = {
|
||||
method: 'POST',
|
||||
endpoint: '/abc000000000000000000001/delete'
|
||||
};
|
||||
@@ -70,7 +71,7 @@ describe('POST /<task-id>/delete', function() {
|
||||
});
|
||||
|
||||
it('should display a success message', function() {
|
||||
var alert = this.last.dom('[data-test=alert]').eq(0);
|
||||
const alert = this.last.dom('[data-test=alert]').eq(0);
|
||||
assert.isDefined(alert);
|
||||
assert.match(alert.text(), /been deleted/i);
|
||||
});
|
||||
|
@@ -13,14 +13,15 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Pa11y Dashboard. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// jscs:disable maximumLineLength, requireArrowFunctions
|
||||
'use strict';
|
||||
|
||||
var assert = require('proclaim');
|
||||
const assert = require('proclaim');
|
||||
|
||||
describe('GET /<task-id>/edit', function() {
|
||||
|
||||
beforeEach(function(done) {
|
||||
var req = {
|
||||
const req = {
|
||||
method: 'GET',
|
||||
endpoint: '/abc000000000000000000001/edit'
|
||||
};
|
||||
@@ -32,7 +33,7 @@ describe('GET /<task-id>/edit', function() {
|
||||
});
|
||||
|
||||
it('should have an "Edit URL" form', function() {
|
||||
var form = this.last.dom('[data-test=edit-url-form]').eq(0);
|
||||
const form = this.last.dom('[data-test=edit-url-form]').eq(0);
|
||||
assert.isDefined(form);
|
||||
assert.strictEqual(form.attr('action'), '/abc000000000000000000001/edit');
|
||||
assert.strictEqual(form.attr('method'), 'post');
|
||||
@@ -49,14 +50,14 @@ describe('GET /<task-id>/edit', function() {
|
||||
});
|
||||
|
||||
it('should have a "name" field', function() {
|
||||
var field = this.form.find('input[name=name]').eq(0);
|
||||
const field = this.form.find('input[name=name]').eq(0);
|
||||
assert.isDefined(field);
|
||||
assert.strictEqual(field.attr('type'), 'text');
|
||||
assert.strictEqual(field.attr('value'), 'NPG Home');
|
||||
});
|
||||
|
||||
it('should have a disabled "url" field', function() {
|
||||
var field = this.form.find('input[name=url]').eq(0);
|
||||
const field = this.form.find('input[name=url]').eq(0);
|
||||
assert.isDefined(field);
|
||||
assert.strictEqual(field.attr('type'), 'url');
|
||||
assert.strictEqual(field.attr('value'), 'nature.com');
|
||||
@@ -64,34 +65,51 @@ describe('GET /<task-id>/edit', function() {
|
||||
});
|
||||
|
||||
it('should have a "wait" field', function() {
|
||||
var field = this.form.find('input[name=wait]').eq(0);
|
||||
const field = this.form.find('input[name=wait]').eq(0);
|
||||
assert.isDefined(field);
|
||||
assert.strictEqual(field.attr('type'), 'text');
|
||||
assert.strictEqual(field.attr('value'), '0');
|
||||
});
|
||||
|
||||
it('should have an "actions" field', function() {
|
||||
const field = this.form.find('textarea[name=actions]').eq(0);
|
||||
assert.isDefined(field);
|
||||
});
|
||||
|
||||
it('should have a disabled "standard" field', function() {
|
||||
var field = this.form.find('select[name=standard]').eq(0);
|
||||
const field = this.form.find('select[name=standard]').eq(0);
|
||||
assert.isDefined(field);
|
||||
assert.isDefined(field.attr('disabled'));
|
||||
});
|
||||
|
||||
it('should have a "username" field', function() {
|
||||
var field = this.form.find('input[name=username]').eq(0);
|
||||
const field = this.form.find('input[name=username]').eq(0);
|
||||
assert.isDefined(field);
|
||||
assert.strictEqual(field.attr('type'), 'text');
|
||||
assert.strictEqual(field.attr('value'), 'user');
|
||||
});
|
||||
|
||||
it('should have a "password" field', function() {
|
||||
var field = this.form.find('input[name=password]').eq(0);
|
||||
const field = this.form.find('input[name=password]').eq(0);
|
||||
assert.isDefined(field);
|
||||
assert.strictEqual(field.attr('type'), 'text');
|
||||
assert.strictEqual(field.attr('value'), 'access');
|
||||
});
|
||||
|
||||
it('should have a "hideElements" field', function() {
|
||||
const field = this.form.find('input[name=hideElements]').eq(0);
|
||||
assert.isDefined(field);
|
||||
assert.strictEqual(field.attr('type'), 'text');
|
||||
assert.strictEqual(field.attr('value'), '');
|
||||
});
|
||||
|
||||
it('should have a "headers" field', function() {
|
||||
const field = this.form.find('textarea[name=headers]').eq(0);
|
||||
assert.isDefined(field);
|
||||
});
|
||||
|
||||
it('should have "ignore" fields', function() {
|
||||
var fields = this.form.find('input[name="ignore[]"]');
|
||||
const fields = this.form.find('input[name="ignore[]"]');
|
||||
assert.isDefined(fields);
|
||||
assert.notStrictEqual(fields.length, 0);
|
||||
});
|
||||
@@ -103,7 +121,7 @@ describe('GET /<task-id>/edit', function() {
|
||||
describe('POST /<task-id>/edit', function() {
|
||||
|
||||
beforeEach(function(done) {
|
||||
var req = {
|
||||
const req = {
|
||||
method: 'POST',
|
||||
endpoint: '/abc000000000000000000001/edit',
|
||||
form: {
|
||||
@@ -131,7 +149,7 @@ describe('POST /<task-id>/edit', function() {
|
||||
});
|
||||
|
||||
it('should display a success message', function() {
|
||||
var alert = this.last.dom('[data-test=alert]').eq(0);
|
||||
const alert = this.last.dom('[data-test=alert]').eq(0);
|
||||
assert.isDefined(alert);
|
||||
assert.match(alert.text(), /been saved/i);
|
||||
});
|
||||
|
@@ -13,16 +13,17 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Pa11y Dashboard. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// jscs:disable maximumLineLength, requireArrowFunctions
|
||||
'use strict';
|
||||
|
||||
var assert = require('proclaim');
|
||||
const assert = require('proclaim');
|
||||
|
||||
describe('GET /<task-id>', function() {
|
||||
|
||||
describe('when task has results', function() {
|
||||
|
||||
beforeEach(function(done) {
|
||||
var req = {
|
||||
const req = {
|
||||
method: 'GET',
|
||||
endpoint: '/abc000000000000000000001'
|
||||
};
|
||||
@@ -59,19 +60,19 @@ describe('GET /<task-id>', function() {
|
||||
});
|
||||
|
||||
it('should display errors', function() {
|
||||
var elem = this.last.dom('[data-test=task-errors]').eq(0);
|
||||
const elem = this.last.dom('[data-test=task-errors]').eq(0);
|
||||
assert.isDefined(elem);
|
||||
assert.match(elem.text(), /errors \( 1 \)/i);
|
||||
});
|
||||
|
||||
it('should display warnings', function() {
|
||||
var elem = this.last.dom('[data-test=task-warnings]').eq(0);
|
||||
const elem = this.last.dom('[data-test=task-warnings]').eq(0);
|
||||
assert.isDefined(elem);
|
||||
assert.match(elem.text(), /warnings \( 2 \)/i);
|
||||
});
|
||||
|
||||
it('should display notices', function() {
|
||||
var elem = this.last.dom('[data-test=task-notices]').eq(0);
|
||||
const elem = this.last.dom('[data-test=task-notices]').eq(0);
|
||||
assert.isDefined(elem);
|
||||
assert.match(elem.text(), /notices \( 3 \)/i);
|
||||
});
|
||||
@@ -81,7 +82,7 @@ describe('GET /<task-id>', function() {
|
||||
describe('when task has no results', function() {
|
||||
|
||||
beforeEach(function(done) {
|
||||
var req = {
|
||||
const req = {
|
||||
method: 'GET',
|
||||
endpoint: '/abc000000000000000000003'
|
||||
};
|
||||
@@ -93,13 +94,13 @@ describe('GET /<task-id>', function() {
|
||||
});
|
||||
|
||||
it('should display a "Run" button', function() {
|
||||
var elem = this.last.dom('[data-test=run-task]');
|
||||
const elem = this.last.dom('[data-test=run-task]');
|
||||
assert.strictEqual(elem.length, 1);
|
||||
assert.strictEqual(elem.eq(0).attr('href'), '/abc000000000000000000003/run');
|
||||
});
|
||||
|
||||
it('should display a message indicating that there are no results', function() {
|
||||
var alert = this.last.dom('[data-test=alert]').eq(0);
|
||||
const alert = this.last.dom('[data-test=alert]').eq(0);
|
||||
assert.isDefined(alert);
|
||||
assert.match(alert.text(), /there are no results to show/i);
|
||||
});
|
||||
|
@@ -13,14 +13,15 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Pa11y Dashboard. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// jscs:disable maximumLineLength, requireArrowFunctions
|
||||
'use strict';
|
||||
|
||||
var assert = require('proclaim');
|
||||
const assert = require('proclaim');
|
||||
|
||||
describe('GET /<task-id>/run', function() {
|
||||
|
||||
beforeEach(function(done) {
|
||||
var req = {
|
||||
const req = {
|
||||
method: 'GET',
|
||||
endpoint: '/abc000000000000000000001/run'
|
||||
};
|
||||
@@ -36,7 +37,7 @@ describe('GET /<task-id>/run', function() {
|
||||
});
|
||||
|
||||
it('should display a success message', function() {
|
||||
var alert = this.last.dom('[data-test=alert]').eq(0);
|
||||
const alert = this.last.dom('[data-test=alert]').eq(0);
|
||||
assert.isDefined(alert);
|
||||
assert.match(alert.text(), /new results are being generated/i);
|
||||
});
|
||||
|
@@ -13,21 +13,22 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Pa11y Dashboard. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// jscs:disable requireArrowFunctions
|
||||
'use strict';
|
||||
|
||||
var config = require('../../config/test.json');
|
||||
var createNavigator = require('./helper/navigate');
|
||||
var createWebserviceClient = require('./helper/webservice');
|
||||
var loadFixtures = require('pa11y-webservice/data/fixture/load');
|
||||
var request = require('request');
|
||||
const config = require('../../config/test.json');
|
||||
const createNavigator = require('./helper/navigate');
|
||||
const createWebserviceClient = require('./helper/webservice');
|
||||
const loadFixtures = require('pa11y-webservice/data/fixture/load');
|
||||
const request = require('request');
|
||||
|
||||
// Run before all tests
|
||||
before(function(done) {
|
||||
this.baseUrl = 'http://localhost:' + config.port;
|
||||
this.baseUrl = `http://localhost:${config.port}`;
|
||||
this.last = {};
|
||||
this.navigate = createNavigator(this.baseUrl, this.last);
|
||||
this.webservice = createWebserviceClient(config);
|
||||
assertTestAppIsRunning(this.baseUrl, function() {
|
||||
assertTestAppIsRunning(this.baseUrl, () => {
|
||||
loadFixtures('test', config.webservice, done);
|
||||
});
|
||||
});
|
||||
@@ -39,7 +40,7 @@ afterEach(function(done) {
|
||||
|
||||
// Check that the test application is running, and exit if not
|
||||
function assertTestAppIsRunning(url, done) {
|
||||
request(url, function(err) {
|
||||
request(url, err => {
|
||||
if (err) {
|
||||
console.error('Error: Test app not started; run with `NODE_ENV=test node index.js`');
|
||||
process.exit(1);
|
||||
|
@@ -15,9 +15,13 @@ You should have received a copy of the GNU General Public License
|
||||
along with Pa11y Dashboard. If not, see <http://www.gnu.org/licenses/>.
|
||||
}}
|
||||
<div class="col-md-8">
|
||||
<h1>Eeek! 500 error. This is serious.</h1>
|
||||
<p class="h2">There isn't much you can do about this.</h2>
|
||||
<p class="h4">Give it another go or try the <a href="/">home page</a>.</h4>
|
||||
<h1>Eeek! 500 error.</h1>
|
||||
<p class="h2">Let's see what we can do here:</h2>
|
||||
<ul>
|
||||
<li>Do you have <a href="https://www.mongodb.com/">MongoDB</a> installed and <code>mongod</code> running?</li>
|
||||
<li>Check out the <a href="https://github.com/pa11y/dashboard/blob/master/TROUBLESHOOTING.md">Troubleshooting doc</a> for more information.</li>
|
||||
<li>Search for a related <a href="https://github.com/pa11y/dashboard/issues">Github issue</a>, or open one yourself.</li>
|
||||
</ul>
|
||||
{{#if error}}
|
||||
<h2>Stack-Trace</h2>
|
||||
<pre>{{error.stack}}</pre>
|
||||
|
@@ -15,26 +15,21 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var moment = require('moment');
|
||||
const moment = require('moment');
|
||||
|
||||
module.exports = helper;
|
||||
|
||||
function helper(hbs) {
|
||||
|
||||
// Format a date with Moment
|
||||
hbs.registerHelper('date-format', function(context, block) {
|
||||
var format = block.hash.format || 'YYYY-MM-DD HH:mm:ss';
|
||||
hbs.registerHelper('date-format', (context, block) => {
|
||||
const format = block.hash.format || 'YYYY-MM-DD HH:mm:ss';
|
||||
return moment(context).format(format);
|
||||
});
|
||||
|
||||
// Get a relative date
|
||||
hbs.registerHelper('date-relative', function(context) {
|
||||
return moment(context).fromNow();
|
||||
});
|
||||
|
||||
hbs.registerHelper('date-timestamp', function(context) {
|
||||
return moment(context).valueOf();
|
||||
});
|
||||
hbs.registerHelper('date-relative', context => moment(context).fromNow());
|
||||
|
||||
hbs.registerHelper('date-timestamp', context => moment(context).valueOf());
|
||||
|
||||
}
|
||||
|
@@ -5,8 +5,6 @@ module.exports = helper;
|
||||
function helper(hbs) {
|
||||
|
||||
// Convert a string to lower-case
|
||||
hbs.registerHelper('lowercase', function(context) {
|
||||
return context.toLowerCase();
|
||||
});
|
||||
hbs.registerHelper('lowercase', context => context.toLowerCase());
|
||||
|
||||
}
|
||||
|
@@ -20,7 +20,7 @@ module.exports = helper;
|
||||
function helper(hbs) {
|
||||
|
||||
// Simplify url by removing (eg http://, https://, trailing slashes) from url
|
||||
hbs.registerHelper('simplify-url', function(context) {
|
||||
hbs.registerHelper('simplify-url', context => {
|
||||
return context.replace(/^https?:\/\//i, '').replace(/\/$/, '').toLowerCase();
|
||||
});
|
||||
|
||||
|
@@ -38,7 +38,7 @@ along with Pa11y Dashboard. If not, see <http://www.gnu.org/licenses/>.
|
||||
<div class="row">
|
||||
<div class="col-md-8 col-sm-8 col-xs-10">
|
||||
<label class="control-label" for="new-task-name">Name</label>
|
||||
<input class="form-control" id="new-task-name" type="text" placeholder="E.g. My Home Page" name="name" value="{{task.name}}"/>
|
||||
<input class="form-control" id="new-task-name" type="text" required placeholder="E.g. My Home Page" name="name" value="{{task.name}}"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -47,7 +47,7 @@ along with Pa11y Dashboard. If not, see <http://www.gnu.org/licenses/>.
|
||||
<div class="row">
|
||||
<div class="col-md-8 col-sm-8 col-xs-10">
|
||||
<label class="control-label" for="new-task-url">URL</label>
|
||||
<input class="form-control" id="new-task-url" type="url" placeholder="E.g. http://mysite.com/" name="url" value="{{task.url}}"/>
|
||||
<input class="form-control" id="new-task-url" type="url" required pattern="https?:\/\/.+" placeholder="E.g. http://mysite.com/" name="url" value="{{task.url}}"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -84,6 +84,19 @@ along with Pa11y Dashboard. If not, see <http://www.gnu.org/licenses/>.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group clearfix">
|
||||
<div class="row">
|
||||
<div class="col-md-4 col-sm-4 col-xs-6">
|
||||
<label class="control-label" for="new-task-actions">
|
||||
Task Actions
|
||||
(<a href="https://github.com/pa11y/pa11y#actions">see Pa11y documentation</a>)
|
||||
</label>
|
||||
<textarea class="form-control" id="new-task-actions" name="actions" aria-describedby="action-detail" placeholder="E.g. Click element #login-button">{{task.actions}}</textarea>
|
||||
<em id="action-detail">(one action per line)</em>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group clearfix">
|
||||
<div class="row">
|
||||
<div class="col-md-4 col-sm-4 col-xs-6">
|
||||
@@ -102,6 +115,25 @@ along with Pa11y Dashboard. If not, see <http://www.gnu.org/licenses/>.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group clearfix">
|
||||
<div class="row">
|
||||
<div class="col-md-4 col-sm-4 col-xs-6">
|
||||
<label class="control-label" for="new-task-headers">HTTP Headers</label>
|
||||
<textarea class="form-control" id="new-task-headers" name="headers" placeholder="Cookie: foo=bar">{{task.headers}}</textarea>
|
||||
<em>(As key/value pairs, separated by newlines/colons)</em>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group clearfix">
|
||||
<div class="row">
|
||||
<div class="col-md-4 col-sm-4 col-xs-6">
|
||||
<label class="control-label" for="new-task-hide-elements">Hide Elements</label>
|
||||
<input class="form-control" id="new-task-hide-elements" type="text" name="hideElements" value="{{task.hideElements}}" placeholder=".advert, #modal, div[aria-role=presentation]"/> <em>(CSS selector)</em>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p class="control-label"><b>Ignore these rules</b> <a target="_blank" href="https://github.com/pa11y/pa11y/wiki/HTML-CodeSniffer-Rules">(full list of rules here)</a></p>
|
||||
|
||||
<div class="standards-lists">
|
||||
|
@@ -18,7 +18,7 @@ along with Pa11y Dashboard. If not, see <http://www.gnu.org/licenses/>.
|
||||
<div class="footer" role="contentinfo">
|
||||
<div class="container">
|
||||
<div class="col-md-5">
|
||||
<small>© {{year}} Springer Nature.<br/>Pa11y Dashboard is licensed under the GNU General Public License 3.0.<br/>Version {{version}}</small>
|
||||
<small>© 2013–{{year}} Team Pa11y.<br/>Pa11y Dashboard is licensed under the GNU General Public License 3.0.<br/>Version {{version}}</small>
|
||||
</div>
|
||||
<div class="col-md-7 clearfix">
|
||||
<ul class="crunch-bottom floated-list nav">
|
||||
|
@@ -73,7 +73,7 @@ along with Pa11y Dashboard. If not, see <http://www.gnu.org/licenses/>.
|
||||
<div class="col-md-9" data-role="expandable-results" role="main">
|
||||
{{#if mainResult.count.error}}
|
||||
<div class="heading label-danger pointer showing first" id="errors" data-test="task-errors" data-role="expander" role="button" tabindex="0" aria-expanded="true" aria-controls="errors-list">
|
||||
<span class="pull-right expander"> - <span class="hide">(close panel)</span></span>
|
||||
<span class="pull-right expander"> ↑ <span class="hide">(close panel)</span></span>
|
||||
Errors ( {{mainResult.count.error}} )
|
||||
</div>
|
||||
<div class="task-danger tasks-list collapse clearfix in" id="errors-list">
|
||||
@@ -109,7 +109,7 @@ along with Pa11y Dashboard. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
{{#if mainResult.count.warning}}
|
||||
<div class="heading label-warning pointer" id="warnings" data-test="task-warnings" data-role="expander" role="button" tabindex="0" aria-expanded="false" aria-controls="warnings-list">
|
||||
<span class="pull-right expander"> + <span class="hide">(open panel)</span></span>
|
||||
<span class="pull-right expander"> ↓ <span class="hide">(open panel)</span></span>
|
||||
Warnings ( {{mainResult.count.warning}} )
|
||||
</div>
|
||||
<div class="task-warning tasks-list collapse clearfix" id="warnings-list">
|
||||
@@ -145,7 +145,7 @@ along with Pa11y Dashboard. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
{{#if mainResult.count.notice}}
|
||||
<div class="heading label-info pointer" id="notices" data-test="task-notices" data-role="expander" role="button" tabindex="0" aria-expanded="false" aria-controls="notices-list">
|
||||
<span class="pull-right expander"> + <span class="hide">(open panel)</span></span>
|
||||
<span class="pull-right expander"> ↓ <span class="hide">(open panel)</span></span>
|
||||
Notices ( {{mainResult.count.notice}} )
|
||||
</div>
|
||||
<div class="task-info tasks-list collapse clearfix" id="notices-list">
|
||||
@@ -180,7 +180,7 @@ along with Pa11y Dashboard. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
{{#if mainResult.ignore.length}}
|
||||
<div class="heading label-default pointer" id="ignore" data-role="expander" role="button" tabindex="0" aria-expanded="false" aria-controls="ignore-list">
|
||||
<span class="pull-right expander"> + <span class="hide">(open panel)</span></span>
|
||||
<span class="pull-right expander"> ↓ <span class="hide">(open panel)</span></span>
|
||||
Ignored Rules ( {{mainResult.ignore.length}} )
|
||||
</div>
|
||||
<div class="task-default tasks-list collapse clearfix" id="ignore-list">
|
||||
|
@@ -16,19 +16,15 @@ along with Pa11y Dashboard. If not, see <http://www.gnu.org/licenses/>.
|
||||
}}
|
||||
|
||||
<ul class="list-unstyled clearfix crunch-bottom">
|
||||
|
||||
{{#unless readonly}}
|
||||
<li class="col-md-4 col-sm-6 task-card add-task">
|
||||
{{#if readonly}}
|
||||
<span class="well task-card-link crunch-bottom">
|
||||
<p class="h3 crunch">Add new URL</p>
|
||||
<p class="supersize-me crunch">+</p>
|
||||
</span>
|
||||
{{else}}
|
||||
<a class="well task-card-link crunch-bottom" data-role="add-task" href="/new" data-test="add-task">
|
||||
<p class="h3 crunch">Add new URL</p>
|
||||
<p class="supersize-me crunch">+</p>
|
||||
</a>
|
||||
{{/if}}
|
||||
</li>
|
||||
{{/unless}}
|
||||
{{#each tasks}}
|
||||
<li class="col-md-4 col-sm-6 task-card" data-test="task" data-role="task" data-keywords="{{lowercase name}} {{lowercase standard}} {{simplify-url url}}">
|
||||
<a class="well task-card-link crunch-bottom" title="Details for URL {{simplify-url url}}" href="{{href}}">
|
||||
|
@@ -15,13 +15,13 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var standardsArray = require('../../data/standards')();
|
||||
var rules = createStandardDescriptionMap(standardsArray);
|
||||
const standardsArray = require('../../data/standards')();
|
||||
const rules = createStandardDescriptionMap(standardsArray);
|
||||
|
||||
module.exports = presentIgnoreRules;
|
||||
|
||||
function presentIgnoreRules(ignore) {
|
||||
return ignore.map(function(name) {
|
||||
return ignore.map(name => {
|
||||
return {
|
||||
name: name,
|
||||
description: rules[name]
|
||||
@@ -30,9 +30,9 @@ function presentIgnoreRules(ignore) {
|
||||
}
|
||||
|
||||
function createStandardDescriptionMap(standards) {
|
||||
var map = {};
|
||||
standards.forEach(function(standard) {
|
||||
standard.rules.forEach(function(rule) {
|
||||
const map = {};
|
||||
standards.forEach(standard => {
|
||||
standard.rules.forEach(rule => {
|
||||
map[rule.name] = rule.description;
|
||||
});
|
||||
});
|
||||
|
@@ -15,17 +15,17 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var _ = require('underscore');
|
||||
var moment = require('moment');
|
||||
const _ = require('underscore');
|
||||
const moment = require('moment');
|
||||
|
||||
module.exports = presentResultList;
|
||||
|
||||
function presentResultList(results) {
|
||||
var resultsByDay = _.groupBy(results, function(result) {
|
||||
const resultsByDay = _.groupBy(results, result => {
|
||||
return moment(result.date).format('YYYY-MM-DD');
|
||||
});
|
||||
var uniqueDayResults = [];
|
||||
_.keys(resultsByDay).forEach(function(day) {
|
||||
const uniqueDayResults = [];
|
||||
_.keys(resultsByDay).forEach(day => {
|
||||
uniqueDayResults.push(resultsByDay[day][0]);
|
||||
});
|
||||
return uniqueDayResults;
|
||||
|
@@ -15,17 +15,17 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var _ = require('underscore');
|
||||
var presentIgnoreRules = require('./ignore');
|
||||
const _ = require('underscore');
|
||||
const presentIgnoreRules = require('./ignore');
|
||||
|
||||
module.exports = presentResult;
|
||||
|
||||
function presentResult(result) {
|
||||
|
||||
// Add additional info
|
||||
result.href = '/' + result.task + '/' + result.id;
|
||||
result.hrefCsv = '/' + result.task + '/' + result.id + '.csv';
|
||||
result.hrefJson = '/' + result.task + '/' + result.id + '.json';
|
||||
result.href = `/${result.task}/${result.id}`;
|
||||
result.hrefCsv = `/${result.task}/${result.id}.csv`;
|
||||
result.hrefJson = `/${result.task}/${result.id}.json`;
|
||||
|
||||
// Parse date
|
||||
result.date = new Date(result.date);
|
||||
@@ -35,13 +35,13 @@ function presentResult(result) {
|
||||
|
||||
// Split out message types
|
||||
if (result.results) {
|
||||
var groupedByType = _.groupBy(result.results, 'type');
|
||||
['error', 'warning', 'notice'].forEach(function(type) {
|
||||
var pluralType = type + 's';
|
||||
var results = groupedByType[type] || [];
|
||||
var groupedByCode = _.groupBy(results, 'code');
|
||||
result[pluralType] = _.keys(groupedByCode).map(function(group) {
|
||||
var firstMessage = groupedByCode[group][0];
|
||||
const groupedByType = _.groupBy(result.results, 'type');
|
||||
['error', 'warning', 'notice'].forEach(type => {
|
||||
const pluralType = `${type}s`;
|
||||
const results = groupedByType[type] || [];
|
||||
const groupedByCode = _.groupBy(results, 'code');
|
||||
result[pluralType] = _.keys(groupedByCode).map(group => {
|
||||
const firstMessage = groupedByCode[group][0];
|
||||
firstMessage.count = groupedByCode[group].length;
|
||||
return firstMessage;
|
||||
});
|
||||
|
@@ -13,27 +13,35 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Pa11y Dashboard. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// jscs:disable requireCamelCaseOrUpperCaseIdentifiers
|
||||
'use strict';
|
||||
|
||||
var presentIgnoreRules = require('./ignore');
|
||||
var presentResult = require('./result');
|
||||
const presentIgnoreRules = require('./ignore');
|
||||
const presentResult = require('./result');
|
||||
|
||||
module.exports = presentTask;
|
||||
|
||||
function presentTask(task) {
|
||||
|
||||
// Add additional info
|
||||
task.href = '/' + task.id;
|
||||
task.hrefDelete = '/' + task.id + '/delete';
|
||||
task.hrefRun = '/' + task.id + '/run';
|
||||
task.hrefJson = '/' + task.id + '.json';
|
||||
task.hrefEdit = '/' + task.id + '/edit';
|
||||
task.hrefIgnore = '/' + task.id + '/ignore';
|
||||
task.hrefUnignore = '/' + task.id + '/unignore';
|
||||
task.href = `/${task.id}`;
|
||||
task.hrefDelete = `/${task.id}/delete`;
|
||||
task.hrefRun = `/${task.id}/run`;
|
||||
task.hrefJson = `/${task.id}.json`;
|
||||
task.hrefEdit = `/${task.id}/edit`;
|
||||
task.hrefIgnore = `/${task.id}/ignore`;
|
||||
task.hrefUnignore = `/${task.id}/unignore`;
|
||||
|
||||
// Enhance the ignored rules
|
||||
task.ignore = presentIgnoreRules(task.ignore);
|
||||
|
||||
// Change headers to a string format
|
||||
if (task.headers && typeof task.headers === 'object') {
|
||||
task.headers = Object.keys(task.headers).map(header => {
|
||||
return `${header}: ${task.headers[header]}`;
|
||||
}).join('\n');
|
||||
}
|
||||
|
||||
// Present the last result if present
|
||||
if (task.last_result) {
|
||||
task.lastResult = presentResult(task.last_result);
|
||||
|
@@ -50,7 +50,7 @@ along with Pa11y Dashboard. If not, see <http://www.gnu.org/licenses/>.
|
||||
<div class="row">
|
||||
<div class="col-md-8 col-sm-8 col-xs-10">
|
||||
<label class="control-label" for="new-task-name">Name</label>
|
||||
<input class="form-control" id="new-task-name" type="text" placeholder="E.g. My Home Page" name="name" value="{{task.name}}"/>
|
||||
<input class="form-control" id="new-task-name" type="text" required placeholder="E.g. My Home Page" name="name" value="{{task.name}}"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -59,7 +59,7 @@ along with Pa11y Dashboard. If not, see <http://www.gnu.org/licenses/>.
|
||||
<div class="row">
|
||||
<div class="col-md-8 col-sm-8 col-xs-10">
|
||||
<label class="control-label" for="new-task-url">URL</label>
|
||||
<input class="form-control" id="new-task-url" type="url" placeholder="E.g. http://mysite.com/" name="url" value="{{task.url}}" disabled/>
|
||||
<input class="form-control" id="new-task-url" type="url" required pattern="https?:\/\/.+" placeholder="E.g. http://mysite.com/" name="url" value="{{task.url}}" disabled/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -96,6 +96,19 @@ along with Pa11y Dashboard. If not, see <http://www.gnu.org/licenses/>.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group clearfix">
|
||||
<div class="row">
|
||||
<div class="col-md-4 col-sm-4 col-xs-6">
|
||||
<label class="control-label" for="new-task-actions">
|
||||
Task Actions
|
||||
(<a href="https://github.com/pa11y/pa11y#actions">see Pa11y documentation</a>)
|
||||
</label>
|
||||
<textarea class="form-control" id="new-task-actions" name="actions" aria-describedby="action-detail" placeholder="E.g. Click element #login-button">{{task.actions}}</textarea>
|
||||
<em id="action-detail">(one action per line)</em>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group clearfix">
|
||||
<div class="row">
|
||||
<div class="col-md-4 col-sm-4 col-xs-6">
|
||||
@@ -114,6 +127,25 @@ along with Pa11y Dashboard. If not, see <http://www.gnu.org/licenses/>.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group clearfix">
|
||||
<div class="row">
|
||||
<div class="col-md-4 col-sm-4 col-xs-6">
|
||||
<label class="control-label" for="new-task-headers">HTTP Headers</label>
|
||||
<textarea class="form-control" id="new-task-headers" name="headers" placeholder="Cookie: foo=bar">{{task.headers}}</textarea>
|
||||
<em>(As key/value pairs, separated by newlines/colons)</em>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group clearfix">
|
||||
<div class="row">
|
||||
<div class="col-md-4 col-sm-4 col-xs-6">
|
||||
<label class="control-label" for="new-task-hide-elements">Hide Elements</label>
|
||||
<input class="form-control" id="new-task-hide-elements" type="text" name="hideElements" value="{{task.hideElements}}" placeholder=".advert, #modal, div[aria-role=presentation]"/> <em>(CSS selector)</em>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p class="control-label"><b>Ignore these rules</b> <a target="_blank" href="https://github.com/pa11y/pa11y/wiki/HTML-CodeSniffer-Rules">(full list of rules here)</a></p>
|
||||
|
||||
<div class="standards-lists">
|
||||
|
Reference in New Issue
Block a user