Apply JSHint to test files.

closes #2666
- Add new jshint:test task
- Fix jshint errors
This commit is contained in:
Fabian Becker 2014-09-03 17:42:55 +02:00
parent 94db4624e7
commit bc558cf0d2
43 changed files with 496 additions and 492 deletions

View File

@ -151,6 +151,17 @@ var _ = require('lodash'),
'!core/client/tpl/**/*.js'
]
}
},
test: {
options: {
jshintrc: 'core/test/.jshintrc'
},
files: {
src: [
'core/test/**/*.js'
]
}
}
},

27
core/test/.jshintrc Normal file
View File

@ -0,0 +1,27 @@
{
"node": true,
"browser": true,
"nomen": false,
"strict": false,
"sub": true,
"eqeqeq": true,
"laxbreak": true,
"bitwise": true,
"curly": true,
"forin": true,
"immed": true,
"latedef": true,
"newcap": true,
"noarg": true,
"noempty": true,
"nonew": true,
"plusplus": true,
"regexp": true,
"undef": true,
"unused": true,
"trailing": true,
"indent": 4,
"onevar": true,
"white": true,
"quotmark": "single"
}

View File

@ -1,11 +1,11 @@
// Posts
/*jshint unused:false */
var blanket = require('blanket')({
'pattern': ['/core/server/', '/core/client/', '/core/shared/'],
'data-cover-only': ['/core/server/', '/core/client/', '/core/shared/']
}),
'pattern': ['/core/server/', '/core/client/', '/core/shared/'],
'data-cover-only': ['/core/server/', '/core/client/', '/core/shared/']
}),
requireDir = require('require-dir');
requireDir('./unit');
requireDir('./integration');
requireDir('./functional/routes');

View File

@ -20,7 +20,7 @@
* Requirements:
* you must have phantomjs 1.9.1 and casperjs 1.1.0-DEV installed in order for these tests to work
*/
/*jshint unused:false */
var DEBUG = false, // TOGGLE THIS TO GET MORE SCREENSHOTS
host = casper.cli.options.host || 'localhost',
noPort = casper.cli.options.noPort || false,
@ -100,7 +100,7 @@ screens = {
},
'signout': {
url: 'ghost/signout/',
linkSelector: '.user-menu-signout',
linkSelector: '.user-menu-signout',
// When no user exists we get redirected to setup which has btn-green
selector: '.btn-blue, .btn-green'
},
@ -251,9 +251,9 @@ casper.on('page.error', function (msg, trace) {
pageErrors.push(msg);
});
casper.on('resource.received', function(resource) {
casper.on('resource.received', function (resource) {
var status = resource.status;
if(status >= 400) {
if (status >= 400) {
casper.echoConcise('RESOURCE ERROR: ' + resource.url + ' failed to load (' + status + ')', 'ERROR');
resourceErrors.push({
@ -284,7 +284,7 @@ casper.test.on('fail', function captureFailure() {
});
// on exit, output any errors
casper.test.on('exit', function() {
casper.test.on('exit', function () {
if (jsErrors.length > 0) {
casper.echo(jsErrors.length + ' Javascript errors found', 'WARNING');
} else {

View File

@ -1,7 +1,7 @@
// # App Test
// Tests that the general layout & functionality of global admin components is correct
/*globals CasperTest, casper */
/*globals CasperTest, casper, newUser */
CasperTest.begin('Admin navigation bar is correct', 28, function suite(test) {
casper.thenOpenAndWaitForPageLoad('root', function testTitleAndUrl() {

View File

@ -3,7 +3,7 @@
/*globals CasperTest, casper, testPost, $ */
CasperTest.begin('Ghost editor functions correctly', 21, function suite(test) {
test.assertHTMLEquals = function(equals, message) {
test.assertHTMLEquals = function (equals, message) {
test.assertEvalEquals(function () {
return document.querySelector('.entry-preview .rendered-markdown').innerHTML
.replace(/<script.*?><\/script>/g, '');
@ -19,7 +19,7 @@ CasperTest.begin('Ghost editor functions correctly', 21, function suite(test) {
// Part 1: Test saving with no data - title is required
casper.waitForSelector('#entry-title', function then() {
test.assertEvalEquals(function() {
test.assertEvalEquals(function () {
return document.getElementById('entry-title').value;
}, '', 'Title is empty');
});
@ -103,7 +103,7 @@ CasperTest.begin('Ghost editor functions correctly', 21, function suite(test) {
});
casper.then(function () {
casper.writeContentToCodeMirror('even **more** words'); // append another word, assumes newline
casper.writeContentToCodeMirror('even **more** words'); // append another word, assumes newline
});
casper.waitForSelectorTextChange('.entry-word-count', function onSuccess() {
@ -139,7 +139,7 @@ CasperTest.begin('Ghost editor functions correctly', 21, function suite(test) {
});
CasperTest.begin('Image Uploads', 20, function suite(test) {
test.assertHTMLEquals = function(equals, message) {
test.assertHTMLEquals = function (equals, message) {
test.assertEvalEquals(function () {
return document.querySelector('.entry-preview .rendered-markdown').innerHTML
.replace(/<script.*?><\/script>/g, '');
@ -201,7 +201,8 @@ CasperTest.begin('Image Uploads', 20, function suite(test) {
test.assertUrlMatch(/ghost\/editor\/$/, 'Landed on the correct URL');
});
var testFileLocation = '/test/file/location';
var testFileLocation = '/test/file/location',
imageURL = 'http://www.random.url';
casper.then(function () {
var markdownImageString = '![](' + testFileLocation + ')';
@ -232,7 +233,6 @@ CasperTest.begin('Image Uploads', 20, function suite(test) {
casper.thenClick('.entry-preview .image-uploader a.image-url');
});
var imageURL = 'http://www.random.url';
casper.waitForSelector('.image-uploader-url', function onSuccess() {
casper.sendKeys('.image-uploader-url input.url.js-upload-url', imageURL);
casper.thenClick('.js-button-accept.btn-blue');
@ -250,7 +250,8 @@ CasperTest.begin('Tag editor', 7, function suite(test) {
test.assertUrlMatch(/ghost\/editor\/$/, 'Landed on the correct URL');
});
var tagName = 'someTagName';
var tagName = 'someTagName',
createdTagSelector = '#entry-tags .tags .tag';
casper.then(function () {
test.assertExists('#entry-tags', 'should have tag label area');
@ -260,7 +261,6 @@ CasperTest.begin('Tag editor', 7, function suite(test) {
casper.sendKeys('#entry-tags input.tag-input', casper.page.event.key.Enter);
});
var createdTagSelector = '#entry-tags .tags .tag';
casper.waitForSelector(createdTagSelector, function onSuccess() {
test.assertSelectorHasText(createdTagSelector, tagName, 'typing enter after tag name should create tag');
});

View File

@ -1,7 +1,7 @@
// # Post Settings Menu Tests
// Test the post settings menu on the editor screen works as expected
/*globals CasperTest, casper */
/*globals CasperTest, casper, __utils__ */
CasperTest.begin('Post settings menu', 15, function suite(test) {
@ -36,7 +36,7 @@ CasperTest.begin('Post settings menu', 15, function suite(test) {
// Enter a title and save draft so converting to/from static post
// will result in notifications and 'Delete This Post' button appears
casper.then(function (){
casper.then(function () {
casper.sendKeys('#entry-title', 'aTitle');
casper.thenClick('.js-publish-button');
});

View File

@ -28,14 +28,14 @@ CasperTest.begin('Settings screen is correct', 15, function suite(test) {
casper.then(function testSwitchingTabs() {
casper.thenClick('.settings-menu-users a');
casper.waitForSelector(usersTabDetector, function then () {
casper.waitForSelector(usersTabDetector, function then() {
// assert that the right menu item is active
test.assertExists('.settings-menu-users.active a', 'Users link is active');
test.assertDoesntExist('.settings-menu-general.active a', 'General link is not active');
}, casper.failOnTimeout(test, 'waitForSelector `usersTabDetector` timed out'));
casper.thenClick('.settings-menu-general a');
casper.waitForSelector(generalTabDetector, function then () {
casper.waitForSelector(generalTabDetector, function then() {
// assert that the right menu item is active
test.assertExists('.settings-menu-general.active a', 'General link is active');
test.assertDoesntExist('.settings-menu-users.active a', 'User link is not active');
@ -156,7 +156,7 @@ CasperTest.begin('General settings validation is correct', 6, function suite(tes
CasperTest.begin('Users screen is correct', 9, function suite(test) {
casper.thenOpenAndWaitForPageLoad('settings.general');
casper.thenTransitionAndWaitForScreenLoad('settings.users', function canTransition () {
casper.thenTransitionAndWaitForScreenLoad('settings.users', function canTransition() {
test.assert(true, 'Can transition to users screen from settings.general');
test.assertUrlMatch(/ghost\/settings\/users\/$/, 'settings.users transitions to correct url');
});
@ -173,8 +173,8 @@ CasperTest.begin('Users screen is correct', 9, function suite(test) {
test.assertEval(function testOwnerRoleNotAnOption() {
var options = document.querySelectorAll('.invite-new-user select#new-user-role option'),
i = 0;
for (; i < options.length; i++) {
if (options[i].text === "Owner") {
for (; i < options.length; i = i + 1) {
if (options[i].text === 'Owner') {
return false;
}
}
@ -186,9 +186,9 @@ CasperTest.begin('Users screen is correct', 9, function suite(test) {
test.assertEval(function authorIsSelectedByDefault() {
var options = document.querySelectorAll('.invite-new-user select#new-user-role option'),
i = 0;
for (; i < options.length; i++) {
for (; i < options.length; i = i + 1) {
if (options[i].selected) {
return options[i].text === "Author"
return options[i].text === 'Author';
}
}
return false;
@ -248,24 +248,24 @@ CasperTest.begin('Can save settings', 7, function suite(test) {
});
casper.thenClick('.btn-blue').waitFor(function successNotification() {
return this.evaluate(function () {
return document.querySelectorAll('.js-bb-notification section').length > 0;
});
return this.evaluate(function () {
return document.querySelectorAll('.js-bb-notification section').length > 0;
});
}, function doneWaiting() {
test.pass('Waited for notification');
}, casper.failOnTimeout(test, 'Saving the general pane did not result in a notification'));
test.pass('Waited for notification');
}, casper.failOnTimeout(test, 'Saving the general pane did not result in a notification'));
casper.then(function checkSettingsWereSaved() {
casper.removeListener('resource.requested', handleSettingsRequest);
casper.removeListener('resource.requested', handleSettingsRequest);
});
casper.waitForSelector('.notification-success', function onSuccess() {
test.assert(true, 'Got success notification');
test.assert(true, 'Got success notification');
}, casper.failOnTimeout(test, 'No success notification :('));
CasperTest.beforeDone(function () {
casper.removeListener('resource.requested', handleUserRequest);
casper.removeListener('resource.requested', handleSettingsRequest);
casper.removeListener('resource.requested', handleUserRequest);
casper.removeListener('resource.requested', handleSettingsRequest);
});
});
@ -389,58 +389,58 @@ CasperTest.begin('User settings screen shows remaining characters for Bio proper
});
CasperTest.begin('Ensure user bio field length validation', 3, function suite(test) {
casper.thenOpenAndWaitForPageLoad('settings.users.user', function testTitleAndUrl() {
test.assertTitle('Ghost Admin', 'Ghost admin has no title');
test.assertUrlMatch(/ghost\/settings\/users\/test-user\/$/, 'Ghost doesn\'t require login this time');
});
casper.thenOpenAndWaitForPageLoad('settings.users.user', function testTitleAndUrl() {
test.assertTitle('Ghost Admin', 'Ghost admin has no title');
test.assertUrlMatch(/ghost\/settings\/users\/test-user\/$/, 'Ghost doesn\'t require login this time');
});
casper.then(function setBioToInvalid() {
this.fillSelectors('form.user-profile', {
'#user-bio': new Array(202).join('a')
});
});
casper.then(function setBioToInvalid() {
this.fillSelectors('form.user-profile', {
'#user-bio': new Array(202).join('a')
});
});
casper.thenClick('.page-actions .btn-blue');
casper.thenClick('.page-actions .btn-blue');
casper.waitForSelectorTextChange('.notification-error', function onSuccess() {
test.assertSelectorHasText('.notification-error', 'is too long');
}, casper.failOnTimeout(test, 'Bio field length error did not appear', 2000));
casper.waitForSelectorTextChange('.notification-error', function onSuccess() {
test.assertSelectorHasText('.notification-error', 'is too long');
}, casper.failOnTimeout(test, 'Bio field length error did not appear', 2000));
});
CasperTest.begin('Ensure user url field validation', 3, function suite(test) {
casper.thenOpenAndWaitForPageLoad('settings.users.user', function testTitleAndUrl() {
test.assertTitle('Ghost Admin', 'Ghost admin has no title');
test.assertUrlMatch(/ghost\/settings\/users\/test-user\/$/, 'Ghost doesn\'t require login this time');
});
casper.thenOpenAndWaitForPageLoad('settings.users.user', function testTitleAndUrl() {
test.assertTitle('Ghost Admin', 'Ghost admin has no title');
test.assertUrlMatch(/ghost\/settings\/users\/test-user\/$/, 'Ghost doesn\'t require login this time');
});
casper.then(function setWebsiteToInvalid() {
this.fillSelectors('form.user-profile', {
'#user-website': 'notaurl'
});
});
this.fillSelectors('form.user-profile', {
'#user-website': 'notaurl'
});
});
casper.thenClick('.page-actions .btn-blue');
casper.thenClick('.page-actions .btn-blue');
casper.waitForSelectorTextChange('.notification-error', function onSuccess() {
test.assertSelectorHasText('.notification-error', 'not a valid url');
}, casper.failOnTimeout(test, 'Url validation error did not appear', 2000));
casper.waitForSelectorTextChange('.notification-error', function onSuccess() {
test.assertSelectorHasText('.notification-error', 'not a valid url');
}, casper.failOnTimeout(test, 'Url validation error did not appear', 2000));
});
CasperTest.begin('Ensure user location field length validation', 3, function suite(test) {
casper.thenOpenAndWaitForPageLoad('settings.users.user', function testTitleAndUrl() {
test.assertTitle('Ghost Admin', 'Ghost admin has no title');
test.assertUrlMatch(/ghost\/settings\/users\/test-user\/$/, 'Ghost doesn\'t require login this time');
});
casper.thenOpenAndWaitForPageLoad('settings.users.user', function testTitleAndUrl() {
test.assertTitle('Ghost Admin', 'Ghost admin has no title');
test.assertUrlMatch(/ghost\/settings\/users\/test-user\/$/, 'Ghost doesn\'t require login this time');
});
casper.then(function setLocationToInvalid() {
this.fillSelectors('form.user-profile', {
'#user-location': new Array(1002).join('a')
});
});
casper.then(function setLocationToInvalid() {
this.fillSelectors('form.user-profile', {
'#user-location': new Array(1002).join('a')
});
});
casper.thenClick('.page-actions .btn-blue');
casper.thenClick('.page-actions .btn-blue');
casper.waitForSelectorTextChange('.notification-error', function onSuccess() {
test.assertSelectorHasText('.notification-error', 'is too long');
}, casper.failOnTimeout(test, 'Location field length error did not appear', 2000));
casper.waitForSelectorTextChange('.notification-error', function onSuccess() {
test.assertSelectorHasText('.notification-error', 'is too long');
}, casper.failOnTimeout(test, 'Location field length error did not appear', 2000));
});

View File

@ -1,7 +1,7 @@
// # Signin Test
// Test that signin works, including testing our spam prevention mechanisms
/*globals CasperTest, casper, url, newUser, user, falseUser */
/*globals CasperTest, casper, url, user, falseUser */
CasperTest.begin('Ghost admin will load login page', 3, function suite(test) {
CasperTest.Routines.signout.run(test);

View File

@ -1,10 +1,10 @@
// # Signup Test
// Test that signup works correctly
/*global CasperTest, casper, email */
/*globals CasperTest */
CasperTest.begin('Ghost signup fails properly', 0, function suite(test) {
/*jshint unused:false */
/*
casper.thenOpenAndWaitForPageLoad('signup', function then() {
test.assertUrlMatch(/ghost\/signup\/$/, 'Landed on the correct URL');

View File

@ -1,7 +1,7 @@
/**
* Tests if RSS exists and is working
*/
/*globals CasperTest, casper */
/*globals CasperTest, casper, url */
CasperTest.begin('Check post not found (404)', 2, function suite(test) {
casper.thenOpen(url + 'asdf/', function (response) {
test.assertEqual(response.status, 404, 'Response status should be 404.');
@ -19,6 +19,6 @@ CasperTest.begin('Check frontend route not found (404)', 2, function suite(test)
CasperTest.begin('Check frontend tag route not found (404)', 2, function suite(test) {
casper.thenOpen(url + 'tag/asdf/', function (response) {
test.assertEqual(response.status, 404, 'Response status should be 404.');
test.assertSelectorHasText('.error-code', '404');
test.assertSelectorHasText('.error-code', '404');
});
}, true);

View File

@ -47,8 +47,8 @@ CasperTest.begin('Ensures dated permalinks works with RSS', 2, function suite(te
casper.thenOpen(url + 'rss/', function (response) {
var content = this.getHTML(),
today = new Date(),
dd = ("0" + today.getDate()).slice(-2),
mm = ("0" + (today.getMonth() + 1)).slice(-2),
dd = ('0' + today.getDate()).slice(-2),
mm = ('0' + (today.getMonth() + 1)).slice(-2),
yyyy = today.getFullYear(),
postLink = '/' + yyyy + '/' + mm + '/' + dd + '/welcome-to-ghost/';

View File

@ -2,9 +2,9 @@
* Tests the homepage
*/
/*globals CasperTest, casper, __utils__, url, testPost, falseUser, email */
/*globals CasperTest, casper, url */
CasperTest.begin('Home page loads', 3, function suite(test) {
casper.start(url, function then(response) {
casper.start(url, function then() {
test.assertTitle('Test Blog', 'The homepage should have a title and it should be "Test Blog"');
test.assertExists('.content .post', 'There is at least one post on this page');
test.assertSelectorHasText('.poweredby', 'Proudly published with Ghost');
@ -12,7 +12,7 @@ CasperTest.begin('Home page loads', 3, function suite(test) {
}, true);
CasperTest.begin('Test helpers on homepage', 3, function suite(test) {
casper.start(url, function then(response) {
casper.start(url, function then() {
// body class
test.assertExists('body.home-template', 'body_class outputs correct home-template class');
// post class
@ -22,7 +22,7 @@ CasperTest.begin('Test helpers on homepage', 3, function suite(test) {
}, true);
CasperTest.begin('Test navigating to Post', 4, function suite(test) {
casper.thenOpen(url, function then(response) {
casper.thenOpen(url, function then() {
var lastPost = '.content article:last-of-type',
lastPostLink = lastPost + ' .post-title a';
@ -47,12 +47,12 @@ CasperTest.begin('Test navigating to Post', 4, function suite(test) {
CasperTest.begin('Test navigating to Post with date permalink', 4, function suite(test) {
CasperTest.Routines.togglePermalinks.run('on');
casper.thenOpen(url, function then(response) {
casper.thenOpen(url, function then() {
var lastPost = '.content article:last-of-type',
lastPostLink = lastPost + ' .post-title a',
today = new Date(),
dd = ("0" + today.getDate()).slice(-2),
mm = ("0" + (today.getMonth() + 1)).slice(-2),
dd = ('0' + today.getDate()).slice(-2),
mm = ('0' + (today.getMonth() + 1)).slice(-2),
yyyy = today.getFullYear(),
postLink = '/' + yyyy + '/' + mm + '/' + dd + '/welcome-to-ghost/';

View File

@ -2,12 +2,12 @@
* Tests the default post page
*/
/*globals CasperTest, casper, __utils__, url, testPost, falseUser, email */
/*globals CasperTest, casper, url */
// Tests when permalinks is set to date
CasperTest.begin('Post page does not load as slug', 2, function suite(test) {
CasperTest.Routines.togglePermalinks.run('on');
casper.thenOpen(url + 'welcome-to-ghost', function then(response) {
casper.thenOpen(url + 'welcome-to-ghost', function then() {
test.assertTitle('404 — Page Not Found', 'The post should return 404 page');
test.assertElementCount('.content .post', 0, 'There is no post on this page');
});
@ -15,7 +15,7 @@ CasperTest.begin('Post page does not load as slug', 2, function suite(test) {
}, false);
CasperTest.begin('Post page loads', 3, function suite(test) {
casper.thenOpen(url + 'welcome-to-ghost', function then(response) {
casper.thenOpen(url + 'welcome-to-ghost', function then() {
test.assertTitle('Welcome to Ghost', 'The post should have a title and it should be "Welcome to Ghost"');
test.assertElementCount('.content .post', 1, 'There is exactly one post on this page');
test.assertSelectorHasText('.poweredby', 'Proudly published with Ghost');
@ -23,7 +23,7 @@ CasperTest.begin('Post page loads', 3, function suite(test) {
}, true);
CasperTest.begin('Test helpers on welcome post', 4, function suite(test) {
casper.start(url + 'welcome-to-ghost', function then(response) {
casper.start(url + 'welcome-to-ghost', function then() {
// body class
test.assertExists('body.post-template', 'body_class outputs correct post-template class');
test.assertExists('body.tag-getting-started', 'body_class outputs correct tag class');

View File

@ -2,9 +2,9 @@
* Tests archive page routing
*/
/*globals CasperTest, casper, __utils__, url, testPost, falseUser, email */
/*globals CasperTest, casper, url */
CasperTest.begin('Redirects page 1 request', 1, function suite(test) {
casper.thenOpen(url + 'page/1/', function then(response) {
casper.thenOpen(url + 'page/1/', function then() {
test.assertEqual(casper.getCurrentUrl().indexOf('page/'), -1, 'Should be redirected to "/".');
});
}, true);

View File

@ -8,11 +8,9 @@
var request = require('supertest'),
express = require('express'),
should = require('should'),
moment = require('moment'),
testUtils = require('../../utils'),
ghost = require('../../../../core'),
agent = request.agent,
cacheRules = {
'public': 'public, max-age=0',
@ -120,7 +118,7 @@ describe('Admin Routing', function () {
});
// we'll use X-Forwarded-Proto: https to simulate an 'https://' request behind a proxy
describe('Require HTTPS - no redirect', function() {
describe('Require HTTPS - no redirect', function () {
var forkedGhost, request;
before(function (done) {
var configTestHttps = testUtils.fork.config();
@ -128,7 +126,7 @@ describe('Admin Routing', function () {
configTestHttps.urlSSL = 'https://localhost/';
testUtils.fork.ghost(configTestHttps, 'testhttps')
.then(function(child) {
.then(function (child) {
forkedGhost = child;
request = require('supertest');
request = request(configTestHttps.url.replace(/\/$/, ''));
@ -142,13 +140,13 @@ describe('Admin Routing', function () {
}
});
it('should block admin access over non-HTTPS', function(done) {
it('should block admin access over non-HTTPS', function (done) {
request.get('/ghost/')
.expect(403)
.end(done);
});
it('should allow admin access over HTTPS', function(done) {
it('should allow admin access over HTTPS', function (done) {
request.get('/ghost/setup/')
.set('X-Forwarded-Proto', 'https')
.expect(200)
@ -156,7 +154,7 @@ describe('Admin Routing', function () {
});
});
describe('Require HTTPS - redirect', function() {
describe('Require HTTPS - redirect', function () {
var forkedGhost, request;
before(function (done) {
var configTestHttps = testUtils.fork.config();
@ -164,7 +162,7 @@ describe('Admin Routing', function () {
configTestHttps.urlSSL = 'https://localhost/';
testUtils.fork.ghost(configTestHttps, 'testhttps')
.then(function(child) {
.then(function (child) {
forkedGhost = child;
request = require('supertest');
request = request(configTestHttps.url.replace(/\/$/, ''));
@ -178,14 +176,14 @@ describe('Admin Routing', function () {
}
});
it('should redirect admin access over non-HTTPS', function(done) {
it('should redirect admin access over non-HTTPS', function (done) {
request.get('/ghost/')
.expect('Location', /^https:\/\/localhost\/ghost\//)
.expect(301)
.end(done);
});
it('should allow admin access over HTTPS', function(done) {
it('should allow admin access over HTTPS', function (done) {
request.get('/ghost/setup/')
.set('X-Forwarded-Proto', 'https')
.expect(200)
@ -195,11 +193,11 @@ describe('Admin Routing', function () {
describe('Ghost Admin Setup', function () {
it('should redirect from /ghost/ to /ghost/setup/ when no user/not installed yet', function (done) {
request.get('/ghost/')
.expect('Location', /ghost\/setup/)
.expect('Cache-Control', cacheRules['private'])
.expect(302)
.end(doEnd(done));
request.get('/ghost/')
.expect('Location', /ghost\/setup/)
.expect('Cache-Control', cacheRules['private'])
.expect(302)
.end(doEnd(done));
});
it('should redirect from /ghost/signin/ to /ghost/setup/ when no user', function (done) {
@ -309,7 +307,7 @@ describe('Admin Routing', function () {
// }
// process.nextTick(function() {
// process.nextTick(function () {
// request.post('/ghost/signin/')
// .send({email: user.email, password: user.password})
// .expect(200)

View File

@ -1,5 +1,5 @@
/*global describe, it, before, after */
/*jshint expr:true*/
// # Api Route tests
// As it stands, these tests depend on the database, and as such are integration tests.
// Mocking out the models to not touch the DB would turn these into unit tests, and should probably be done in future,
@ -8,12 +8,10 @@
var supertest = require('supertest'),
express = require('express'),
should = require('should'),
_ = require('lodash'),
testUtils = require('../../../utils'),
ghost = require('../../../../../core'),
request,
agent;
request;
describe('Unauthorized', function () {

View File

@ -3,7 +3,6 @@
var testUtils = require('../../../utils'),
supertest = require('supertest'),
express = require('express'),
should = require('should'),
ghost = require('../../../../../core'),
@ -88,9 +87,8 @@ describe('Notifications API', function () {
return done(err);
}
var location = res.headers['location'];
var jsonResponse = res.body;
var location = res.headers['location'],
jsonResponse = res.body;
jsonResponse.notifications.should.exist;
testUtils.API.checkResponse(jsonResponse.notifications[0], 'notification');

View File

@ -452,7 +452,6 @@ describe('Post API', function () {
it('can edit a new draft and update post', function (done) {
var newTitle = 'My Post',
newTagName = 'My Tag',
publishedState = 'published',
newTag = {id: null, name: newTagName},
newPost = {posts: [{status: 'draft', title: newTitle, markdown: 'my post', tags: [newTag]}]};
@ -529,8 +528,6 @@ describe('Post API', function () {
return done(err);
}
var unpublishedPost = res.body;
// Unpublishing a post should send x-cache-invalidate headers
_.has(res.headers, 'x-cache-invalidate').should.equal(true);
done();
@ -635,7 +632,6 @@ describe('Post API', function () {
return done(err);
}
var putBody = res.body;
_.has(res.headers, 'x-cache-invalidate').should.equal(false);
jsonResponse = res.body;
jsonResponse.errors.should.exist;
@ -650,6 +646,7 @@ describe('Post API', function () {
.set('Authorization', 'Bearer ' + accesstoken)
.expect('Content-Type', /json/)
.end(function (err, res) {
/*jshint unused:false*/
if (err) {
return done(err);
}
@ -661,6 +658,7 @@ describe('Post API', function () {
.expect('Content-Type', /json/)
.expect(401)
.end(function (err, res) {
/*jshint unused:false*/
if (err) {
return done(err);
}
@ -799,7 +797,7 @@ describe('Post API', function () {
.send(newPost)
.expect('Content-Type', /json/)
.expect(201)
.end(function (err ,res) {
.end(function (err, res) {
if (err) {
return done(err);
}
@ -820,7 +818,7 @@ describe('Post API', function () {
return done(err);
}
var jsonResponse = res.body
var jsonResponse = res.body;
jsonResponse.should.exist;
jsonResponse.posts.should.exist;
testUtils.API.checkResponse(jsonResponse.posts[0], 'post');
@ -849,6 +847,7 @@ describe('Post API', function () {
.send(jsonResponse)
.expect('Content-Type', /json/)
.end(function (err, res) {
/*jshint unused:false*/
if (err) {
return done(err);
}
@ -874,6 +873,7 @@ describe('Post API', function () {
.expect('Content-Type', /json/)
.send(jsonResponse)
.end(function (err, res) {
/*jshint unused:false*/
if (err) {
return done(err);
}
@ -931,11 +931,6 @@ describe('Post API', function () {
return done(err);
}
var putBody = res.body;
var today = new Date(),
dd = ("0" + today.getDate()).slice(-2),
mm = ("0" + (today.getMonth() + 1)).slice(-2),
yyyy = today.getFullYear(),
postLink = '/' + yyyy + '/' + mm + '/' + dd + '/' + putBody.posts[0].slug + '/';
_.has(res.headers, 'x-cache-invalidate').should.equal(true);
putBody.should.exist;

View File

@ -72,7 +72,7 @@ describe('Settings API', function () {
jsonResponse.should.exist;
jsonResponse.settings.should.exist;
testUtils.API.checkResponseValue(jsonResponse.settings[0], ['id','uuid','key','value','type','created_at','created_by','updated_at','updated_by']);
testUtils.API.checkResponseValue(jsonResponse.settings[0], ['id', 'uuid', 'key', 'value', 'type', 'created_at', 'created_by', 'updated_at', 'updated_by']);
jsonResponse.settings[0].key.should.eql('title');
testUtils.API.isISO8601(jsonResponse.settings[0].created_at).should.be.true;
done();
@ -157,6 +157,7 @@ describe('Settings API', function () {
.send(jsonResponse)
.expect(401)
.end(function (err, res) {
/*jshint unused:false*/
if (err) {
return done(err);
}

View File

@ -339,6 +339,7 @@ describe('User API', function () {
.send(jsonResponse)
.expect(401)
.end(function (err, res) {
/*jshint unused:false*/
if (err) {
return done(err);
}

View File

@ -9,7 +9,6 @@ var request = require('supertest'),
express = require('express'),
should = require('should'),
moment = require('moment'),
path = require('path'),
testUtils = require('../../utils'),
ghost = require('../../../../core'),
@ -52,7 +51,7 @@ describe('Frontend Routing', function () {
});
after(function (done) {
testUtils.clearData().then(function () {
testUtils.clearData().then(function () {
done();
}).catch(done);
});
@ -101,7 +100,7 @@ describe('Frontend Routing', function () {
it('should not work with date permalinks', function (done) {
// get today's date
var date = moment().format("YYYY/MM/DD");
var date = moment().format('YYYY/MM/DD');
request.get('/' + date + '/welcome-to-ghost/')
//.expect('Cache-Control', cacheRules['private'])
@ -146,7 +145,7 @@ describe('Frontend Routing', function () {
});
// we'll use X-Forwarded-Proto: https to simulate an 'https://' request behind a proxy
describe('HTTPS', function() {
describe('HTTPS', function () {
var forkedGhost, request;
before(function (done) {
var configTestHttps = testUtils.fork.config();
@ -154,7 +153,7 @@ describe('Frontend Routing', function () {
configTestHttps.urlSSL = 'https://localhost/';
testUtils.fork.ghost(configTestHttps, 'testhttps')
.then(function(child) {
.then(function (child) {
forkedGhost = child;
request = require('supertest');
request = request(configTestHttps.url.replace(/\/$/, ''));
@ -167,20 +166,20 @@ describe('Frontend Routing', function () {
}
});
it('should set links to url over non-HTTPS', function(done) {
it('should set links to url over non-HTTPS', function (done) {
request.get('/')
.expect(200)
.expect(/\<link rel="canonical" href="http:\/\/127.0.0.1:2370\/" \/\>/)
.expect(/\<a href="http:\/\/127.0.0.1:2370">Ghost\<\/a\>/)
.expect(/<link rel="canonical" href="http:\/\/127.0.0.1:2370\/" \/\>/)
.expect(/<a href="http:\/\/127.0.0.1:2370">Ghost<\/a\>/)
.end(doEnd(done));
});
it('should set links to urlSSL over HTTPS', function(done) {
it('should set links to urlSSL over HTTPS', function (done) {
request.get('/')
.set('X-Forwarded-Proto', 'https')
.expect(200)
.expect(/\<link rel="canonical" href="https:\/\/localhost\/" \/\>/)
.expect(/\<a href="https:\/\/localhost">Ghost\<\/a\>/)
.expect(/<link rel="canonical" href="https:\/\/localhost\/" \/\>/)
.expect(/<a href="https:\/\/localhost">Ghost<\/a\>/)
.end(doEnd(done));
});
});
@ -610,7 +609,7 @@ describe('Frontend Routing', function () {
// it('should load a post with date permalink', function (done) {
//
// // get today's date
// var date = moment().format("YYYY/MM/DD");
// var date = moment().format('YYYY/MM/DD');
//
//
// request.get('/' + date + '/welcome-to-ghost/')

View File

@ -1,7 +1,7 @@
// # Setup Test
// Test that setup works correctly
/*global CasperTest, casper, email */
/*global CasperTest, casper, email, user, password */
CasperTest.begin('Ghost setup fails properly', 6, function suite(test) {
casper.thenOpenAndWaitForPageLoad('setup', function then() {
@ -42,7 +42,7 @@ CasperTest.begin('Authenticated user is redirected', 8, function suite(test) {
test.assertUrlMatch(/ghost\/signin\/$/, 'Landed on the correct URL');
});
casper.waitForOpaque('.login-box', function then() {
casper.waitForOpaque('.login-box', function then() {
this.fillAndSave('#login', user);
});

View File

@ -1,9 +1,7 @@
/*globals describe, before, beforeEach, afterEach, it */
/*globals describe, before, afterEach, it */
/*jshint expr:true*/
var testUtils = require('../../utils'),
should = require('should'),
sinon = require('sinon'),
rewire = require('rewire'),
_ = require('lodash'),
@ -34,8 +32,7 @@ describe('Configuration API', function () {
should.exist(ConfigurationAPI);
it('can browse config', function (done) {
var existingConfig = ConfigurationAPI.__get__('config'),
updatedConfig = _.extend(config, newConfig);
var updatedConfig = _.extend(config, newConfig);
config.set(updatedConfig);
ConfigurationAPI.__set__('config', updatedConfig);
@ -52,8 +49,7 @@ describe('Configuration API', function () {
});
it('can read config', function (done) {
var existingConfig = ConfigurationAPI.__get__('config'),
updatedConfig = _.extend(config, newConfig);
var updatedConfig = _.extend(config, newConfig);
config.set(updatedConfig);
ConfigurationAPI.__set__('config', updatedConfig);

View File

@ -25,7 +25,7 @@ describe('DB API', function () {
result.db.should.be.empty;
}).then(function () {
return ModelTag.Tag.findAll(testUtils.context.owner).then(function (results) {
should.exist(results);
should.exist(results);
results.length.should.equal(0);
});
}).then(function () {
@ -57,17 +57,17 @@ describe('DB API', function () {
});
it('delete all content is denied (editor & author)', function (done) {
return dbAPI.deleteAllContent(testUtils.context.editor).then(function (){
return dbAPI.deleteAllContent(testUtils.context.editor).then(function () {
done(new Error('Delete all content is not denied for editor.'));
}, function (error) {
error.type.should.eql('NoPermissionError');
return dbAPI.deleteAllContent(testUtils.context.author);
}).then(function (){
}).then(function () {
done(new Error('Delete all content is not denied for author.'));
}, function (error) {
error.type.should.eql('NoPermissionError');
return dbAPI.deleteAllContent();
}).then(function (){
}).then(function () {
done(new Error('Delete all content is not denied without authentication.'));
}).catch(function (error) {
error.type.should.eql('NoPermissionError');
@ -76,17 +76,17 @@ describe('DB API', function () {
});
it('export content is denied (editor & author)', function (done) {
return dbAPI.exportContent(testUtils.context.editor).then(function (){
return dbAPI.exportContent(testUtils.context.editor).then(function () {
done(new Error('Export content is not denied for editor.'));
}, function (error) {
error.type.should.eql('NoPermissionError');
return dbAPI.exportContent(testUtils.context.author);
}).then(function (){
}).then(function () {
done(new Error('Export content is not denied for author.'));
}, function (error) {
error.type.should.eql('NoPermissionError');
return dbAPI.exportContent();
}).then(function (){
}).then(function () {
done(new Error('Export content is not denied without authentication.'));
}).catch(function (error) {
error.type.should.eql('NoPermissionError');

View File

@ -40,11 +40,11 @@ describe('Upload API', function () {
path: '/tmp/TMPFILEID'
};
UploadAPI.add({uploadimage: uploadimage}).then(function () {
done(new Error('Upload suceeded with invalid file.'));
}, function (result) {
result.code.should.equal(415);
result.type.should.equal('UnsupportedMediaTypeError');
done();
done(new Error('Upload suceeded with invalid file.'));
}, function (result) {
result.code.should.equal(415);
result.type.should.equal('UnsupportedMediaTypeError');
done();
});
});
});
@ -57,11 +57,11 @@ describe('Upload API', function () {
path: '/tmp/TMPFILEID'
};
UploadAPI.add({uploadimage: uploadimage}).then(function () {
done(new Error('Upload suceeded with invalid file.'));
}, function (result) {
result.code.should.equal(415);
result.type.should.equal('UnsupportedMediaTypeError');
done();
done(new Error('Upload suceeded with invalid file.'));
}, function (result) {
result.code.should.equal(415);
result.type.should.equal('UnsupportedMediaTypeError');
done();
});
});
});
@ -87,11 +87,11 @@ describe('Upload API', function () {
path: '/tmp/TMPFILEID'
};
UploadAPI.add({uploadimage: uploadimage}).then(function () {
done(new Error('Upload suceeded with invalid file.'));
}, function (result) {
result.code.should.equal(415);
result.type.should.equal('UnsupportedMediaTypeError');
done();
done(new Error('Upload suceeded with invalid file.'));
}, function (result) {
result.code.should.equal(415);
result.type.should.equal('UnsupportedMediaTypeError');
done();
});
});

View File

@ -39,50 +39,50 @@ describe('Users API', function () {
describe('Browse', function () {
function checkBrowseResponse(response, count) {
should.exist(response);
testUtils.API.checkResponse(response, 'users');
should.exist(response.users);
response.users.should.have.length(count);
testUtils.API.checkResponse(response.users[0], 'user', ['roles']);
testUtils.API.checkResponse(response.users[1], 'user', ['roles']);
testUtils.API.checkResponse(response.users[2], 'user', ['roles']);
testUtils.API.checkResponse(response.users[3], 'user', ['roles']);
should.exist(response);
testUtils.API.checkResponse(response, 'users');
should.exist(response.users);
response.users.should.have.length(count);
testUtils.API.checkResponse(response.users[0], 'user', ['roles']);
testUtils.API.checkResponse(response.users[1], 'user', ['roles']);
testUtils.API.checkResponse(response.users[2], 'user', ['roles']);
testUtils.API.checkResponse(response.users[3], 'user', ['roles']);
}
it('Owner can browse', function (done) {
UserAPI.browse(context.owner).then(function (response) {
checkBrowseResponse(response, 7);
done();
}).catch(done);
UserAPI.browse(context.owner).then(function (response) {
checkBrowseResponse(response, 7);
done();
}).catch(done);
});
it('Admin can browse', function (done) {
UserAPI.browse(context.admin).then(function (response) {
checkBrowseResponse(response, 7);
done();
}).catch(done);
UserAPI.browse(context.admin).then(function (response) {
checkBrowseResponse(response, 7);
done();
}).catch(done);
});
it('Editor can browse', function (done) {
UserAPI.browse(context.editor).then(function (response) {
checkBrowseResponse(response, 7);
done();
}).catch(done);
UserAPI.browse(context.editor).then(function (response) {
checkBrowseResponse(response, 7);
done();
}).catch(done);
});
it('Author can browse active', function (done) {
UserAPI.browse(context.author).then(function (response) {
checkBrowseResponse(response, 7);
done();
}).catch(done);
UserAPI.browse(context.author).then(function (response) {
checkBrowseResponse(response, 7);
done();
}).catch(done);
});
it('No-auth CANNOT browse', function (done) {
UserAPI.browse().then(function () {
done(new Error('Browse users is not denied without authentication.'));
}, function () {
done();
}).catch(done);
UserAPI.browse().then(function () {
done(new Error('Browse users is not denied without authentication.'));
}, function () {
done();
}).catch(done);
});
it('Can browse invited/invited-pending (admin)', function (done) {
@ -116,10 +116,10 @@ describe('Users API', function () {
});
it('Can browse all', function (done) {
UserAPI.browse(_.extend(testUtils.context.admin, { status: 'all'})).then(function (response) {
checkBrowseResponse(response, 7);
done();
}).catch(done);
UserAPI.browse(_.extend(testUtils.context.admin, { status: 'all'})).then(function (response) {
checkBrowseResponse(response, 7);
done();
}).catch(done);
});
});
@ -859,11 +859,9 @@ describe('Users API', function () {
response.users[0].roles[0].name.should.equal('Owner');
return UserAPI.edit(
{users: [
{name: newName, roles: [roleIdFor.author]}
]},
{ users: [{name: newName, roles: [roleIdFor.author]}]},
options
).then(function (response) {
).then(function () {
done(new Error('Author should not be able to downgrade owner'));
}).catch(function (error) {
error.type.should.eql('NoPermissionError');
@ -876,9 +874,8 @@ describe('Users API', function () {
describe('Editor', function () {
it('Can assign author role to author', function (done) {
UserAPI.edit(
{users: [
{name: newName, roles: [roleIdFor.author]}
]}, _.extend({}, context.editor, {id: userIdFor.author2}, {include: 'roles'})
{ users: [{name: newName, roles: [roleIdFor.author]}]},
_.extend({}, context.editor, {id: userIdFor.author2}, {include: 'roles'})
).then(function (response) {
checkEditResponse(response);
response.users[0].id.should.equal(userIdFor.author2);
@ -890,23 +887,21 @@ describe('Users API', function () {
it('CANNOT assign author role to self', function (done) {
UserAPI.edit(
{users: [
{name: newName, roles: [roleIdFor.author]}
]}, _.extend({}, context.editor, {id: userIdFor.editor}, {include: 'roles'})
).then(function (response) {
done(new Error('Editor should not be able to upgrade their role'));
}, function (error) {
error.type.should.eql('NoPermissionError');
done();
}).catch(done);
{ users: [{name: newName, roles: [roleIdFor.author]}]},
_.extend({}, context.editor, {id: userIdFor.editor}, {include: 'roles'})
).then(function () {
done(new Error('Editor should not be able to upgrade their role'));
}, function (error) {
error.type.should.eql('NoPermissionError');
done();
}).catch(done);
});
it('CANNOT assign author role to other Editor', function (done) {
UserAPI.edit(
{users: [
{name: newName, roles: [roleIdFor.author]}
]}, _.extend({}, context.editor, {id: userIdFor.editor2}, {include: 'roles'})
).then(function (response) {
{ users: [{name: newName, roles: [roleIdFor.author]}]},
_.extend({}, context.editor, {id: userIdFor.editor2}, {include: 'roles'})
).then(function () {
done(new Error('Editor should not be able to change the roles of other editors'));
}, function (error) {
error.type.should.eql('NoPermissionError');
@ -916,22 +911,20 @@ describe('Users API', function () {
it('CANNOT assign author role to admin', function (done) {
UserAPI.edit(
{users: [
{name: newName, roles: [roleIdFor.author]}
]}, _.extend({}, context.editor, {id: userIdFor.admin}, {include: 'roles'})
).then(function (response) {
done(new Error('Editor should not be able to change the roles of admins'));
}, function (error) {
error.type.should.eql('NoPermissionError');
done();
}).catch(done);
{ users: [{name: newName, roles: [roleIdFor.author]}]},
_.extend({}, context.editor, {id: userIdFor.admin}, {include: 'roles'})
).then(function () {
done(new Error('Editor should not be able to change the roles of admins'));
}, function (error) {
error.type.should.eql('NoPermissionError');
done();
}).catch(done);
});
it('CANNOT assign admin role to author', function (done) {
UserAPI.edit(
{users: [
{name: newName, roles: [roleIdFor.admin]}
]}, _.extend({}, context.editor, {id: userIdFor.author}, {include: 'roles'})
).then(function (response) {
{ users: [{name: newName, roles: [roleIdFor.admin]}]},
_.extend({}, context.editor, {id: userIdFor.author}, {include: 'roles'})
).then(function () {
done(new Error('Editor should not be able to upgrade the role of authors'));
}).catch(function (error) {
error.type.should.eql('NoPermissionError');
@ -941,29 +934,27 @@ describe('Users API', function () {
});
describe('Author', function () {
it('CANNOT assign higher role to self', function (done) {
UserAPI.edit(
{users: [
{name: newName, roles: [roleIdFor.editor]}
]}, _.extend({}, context.author, {id: userIdFor.author}, {include: 'roles'})
).then(function (response) {
done(new Error('Author should not be able to upgrade their role'));
}, function (error) {
error.type.should.eql('NoPermissionError');
done();
}).catch(done);
});
it('CANNOT assign higher role to self', function (done) {
UserAPI.edit(
{ users: [{name: newName, roles: [roleIdFor.editor]}]},
_.extend({}, context.author, {id: userIdFor.author}, {include: 'roles'})
).then(function () {
done(new Error('Author should not be able to upgrade their role'));
}, function (error) {
error.type.should.eql('NoPermissionError');
done();
}).catch(done);
});
});
});
describe('Transfer ownership', function () {
it('Owner can transfer ownership', function (done) {
// transfer ownership to admin user id:2
UserAPI.transferOwnership(
{owner: [
{id: userIdFor.admin}
]}, context.owner
).then(function (response) {
it('Owner can transfer ownership', function (done) {
// transfer ownership to admin user id:2
UserAPI.transferOwnership(
{ owner: [{id: userIdFor.admin}]},
context.owner
).then(function (response) {
should.exist(response);
response.users.should.have.length(2);
testUtils.API.checkResponse(response.users[0], 'user', ['roles']);
@ -971,43 +962,40 @@ describe('Users API', function () {
response.users[0].roles[0].id.should.equal(1);
response.users[1].roles[0].id.should.equal(4);
done();
}).catch(done);
});
}).catch(done);
});
it('Owner CANNOT downgrade own role', function (done) {
// Cannot change own role to admin
UserAPI.transferOwnership(
{owner: [
{id: userIdFor.owner}
]}, context.owner
).then(function (response) {
{ owner: [{id: userIdFor.owner}]},
context.owner
).then(function () {
done(new Error('Owner should not be able to downgrade their role'));
}).catch(function (error) {
error.type.should.eql('ValidationError');
done();
});
}).catch(function (error) {
error.type.should.eql('ValidationError');
done();
});
});
it('Admin CANNOT transfer ownership', function (done) {
// transfer ownership to user id: 2
UserAPI.transferOwnership(
{owner: [
{id: userIdFor.editor}
]}, context.admin
{ owner: [{id: userIdFor.editor}]},
context.admin
).then(function () {
done(new Error('Admin is not denied transferring ownership.'));
}).catch(function (error) {
error.type.should.eql('NoPermissionError');
done();
});
done(new Error('Admin is not denied transferring ownership.'));
}).catch(function (error) {
error.type.should.eql('NoPermissionError');
done();
});
});
it('Editor CANNOT transfer ownership', function (done) {
// transfer ownership to user id: 2
UserAPI.transferOwnership(
{owner: [
{id: userIdFor.admin}
]}, context.editor
{ owner: [{id: userIdFor.admin}]},
context.editor
).then(function () {
done(new Error('Admin is not denied transferring ownership.'));
}).catch(function (error) {
@ -1019,15 +1007,14 @@ describe('Users API', function () {
it('Author CANNOT transfer ownership', function (done) {
// transfer ownership to user id: 2
UserAPI.transferOwnership(
{owner: [
{id: userIdFor.admin}
]}, context.author
{ owner: [{id: userIdFor.admin}]},
context.author
).then(function () {
done(new Error('Admin is not denied transferring ownership.'));
}).catch(function (error) {
error.type.should.eql('NoPermissionError');
done();
});
done(new Error('Admin is not denied transferring ownership.'));
}).catch(function (error) {
error.type.should.eql('NoPermissionError');
done();
});
});
});
});

View File

@ -2,7 +2,6 @@
/*jshint expr:true*/
var testUtils = require('../../utils'),
should = require('should'),
Promise = require('bluebird'),
sequence = require('../../../server/utils/sequence'),
_ = require('lodash'),

View File

@ -2,7 +2,6 @@
/*jshint expr:true*/
var testUtils = require('../../utils'),
should = require('should'),
Promise = require('bluebird'),
sequence = require('../../../server/utils/sequence'),
_ = require('lodash'),
@ -55,13 +54,11 @@ describe('Post Model', function () {
});
it('can findAll, returning all related data', function (done) {
var firstPost;
PostModel.findAll({include: ['author_id', 'fields', 'tags', 'created_by', 'updated_by', 'published_by']})
.then(function (results) {
should.exist(results);
results.length.should.be.above(0);
posts = results.models.map(function (model) {
var posts = results.models.map(function (model) {
return model.toJSON();
});
@ -88,8 +85,6 @@ describe('Post Model', function () {
});
it('can findPage, returning all related data', function (done) {
var firstPost;
PostModel.findPage({include: ['author_id', 'fields', 'tags', 'created_by', 'updated_by', 'published_by']})
.then(function (results) {
should.exist(results);
@ -255,7 +250,7 @@ describe('Post Model', function () {
return function () {
return PostModel.add({
title: 'Test Title',
markdown: 'Test Content ' + (i+1)
markdown: 'Test Content ' + (i + 1)
}, context);
};
})).then(function (createdPosts) {
@ -294,7 +289,7 @@ describe('Post Model', function () {
}).catch(done);
});
it('can generate a safe slug when a reserved keyword is used', function(done) {
it('can generate a safe slug when a reserved keyword is used', function (done) {
var newPost = {
title: 'rss',
markdown: 'Test Content 1'

View File

@ -100,18 +100,19 @@ describe('Tag Model', function () {
function seedTags(tagNames) {
var createOperations = [
PostModel.add(testUtils.DataGenerator.forModel.posts[0], context)
];
PostModel.add(testUtils.DataGenerator.forModel.posts[0], context)
],
tagModels = tagNames.map(function (tagName) { return TagModel.add({name: tagName}, context); });
var tagModels = tagNames.map(function (tagName) { return TagModel.add({name: tagName}, context); });
createOperations = createOperations.concat(tagModels);
return Promise.all(createOperations).then(function (models) {
var postModel = models[0],
attachOperations;
attachOperations,
i;
attachOperations = [];
for (var i = 1; i < models.length; i += 1) {
for (i = 1; i < models.length; i += 1) {
attachOperations.push(postModel.tags().attach(models[i]));
}

View File

@ -3,12 +3,9 @@
var testUtils = require('../utils'),
should = require('should'),
rewire = require('rewire'),
_ = require('lodash'),
// Stuff we are testing
packageInfo = require('../../../package'),
ghost = require('../../../core'),
config = rewire('../../../core/server/config'),
updateCheck = rewire('../../server/update-check');
describe('Update Check', function () {

View File

@ -118,22 +118,19 @@ describe('Apps', function () {
});
it('allows filter registration with permission', function (done) {
var registerSpy = sandbox.spy(filters, 'registerFilter');
var appProxy = new AppProxy({
name: 'TestApp',
permissions: {
filters: ['testFilter'],
helpers: ['myTestHelper'],
posts: ['browse', 'read', 'edit', 'add', 'delete']
}
});
var fakePosts = [{ id: 0 }, { id: 1 }];
var filterStub = sandbox.spy(function (val) {
return val;
});
var registerSpy = sandbox.spy(filters, 'registerFilter'),
appProxy = new AppProxy({
name: 'TestApp',
permissions: {
filters: ['testFilter'],
helpers: ['myTestHelper'],
posts: ['browse', 'read', 'edit', 'add', 'delete']
}
}),
fakePosts = [{ id: 0 }, { id: 1 }],
filterStub = sandbox.spy(function (val) {
return val;
});
appProxy.filters.register('testFilter', 5, filterStub);
@ -151,18 +148,16 @@ describe('Apps', function () {
});
it('does not allow filter registration without permission', function () {
var registerSpy = sandbox.spy(filters, 'registerFilter');
var appProxy = new AppProxy({
name: 'TestApp',
permissions: {
filters: ['prePostRender'],
helpers: ['myTestHelper'],
posts: ['browse', 'read', 'edit', 'add', 'delete']
}
});
var filterStub = sandbox.stub().returns('test result');
var registerSpy = sandbox.spy(filters, 'registerFilter'),
appProxy = new AppProxy({
name: 'TestApp',
permissions: {
filters: ['prePostRender'],
helpers: ['myTestHelper'],
posts: ['browse', 'read', 'edit', 'add', 'delete']
}
}),
filterStub = sandbox.stub().returns('test result');
function registerFilterWithoutPermission() {
appProxy.filters.register('superSecretFilter', 5, filterStub);
@ -175,20 +170,17 @@ describe('Apps', function () {
});
it('allows filter deregistration with permission', function (done) {
var registerSpy = sandbox.spy(filters, 'deregisterFilter');
var appProxy = new AppProxy({
name: 'TestApp',
permissions: {
filters: ['prePostsRender'],
helpers: ['myTestHelper'],
posts: ['browse', 'read', 'edit', 'add', 'delete']
}
});
var fakePosts = [{ id: 0 }, { id: 1 }];
var filterStub = sandbox.stub().returns(fakePosts);
var registerSpy = sandbox.spy(filters, 'deregisterFilter'),
appProxy = new AppProxy({
name: 'TestApp',
permissions: {
filters: ['prePostsRender'],
helpers: ['myTestHelper'],
posts: ['browse', 'read', 'edit', 'add', 'delete']
}
}),
fakePosts = [{ id: 0 }, { id: 1 }],
filterStub = sandbox.stub().returns(fakePosts);
appProxy.filters.deregister('prePostsRender', 5, filterStub);
@ -205,18 +197,16 @@ describe('Apps', function () {
});
it('does not allow filter deregistration without permission', function () {
var registerSpy = sandbox.spy(filters, 'deregisterFilter');
var appProxy = new AppProxy({
name: 'TestApp',
permissions: {
filters: ['prePostRender'],
helpers: ['myTestHelper'],
posts: ['browse', 'read', 'edit', 'add', 'delete']
}
});
var filterStub = sandbox.stub().returns('test result');
var registerSpy = sandbox.spy(filters, 'deregisterFilter'),
appProxy = new AppProxy({
name: 'TestApp',
permissions: {
filters: ['prePostRender'],
helpers: ['myTestHelper'],
posts: ['browse', 'read', 'edit', 'add', 'delete']
}
}),
filterStub = sandbox.stub().returns('test result');
function deregisterFilterWithoutPermission() {
appProxy.filters.deregister('superSecretFilter', 5, filterStub);
@ -229,16 +219,15 @@ describe('Apps', function () {
});
it('allows helper registration with permission', function () {
var registerSpy = sandbox.spy(helpers, 'registerThemeHelper');
var appProxy = new AppProxy({
name: 'TestApp',
permissions: {
filters: ['prePostRender'],
helpers: ['myTestHelper'],
posts: ['browse', 'read', 'edit', 'add', 'delete']
}
});
var registerSpy = sandbox.spy(helpers, 'registerThemeHelper'),
appProxy = new AppProxy({
name: 'TestApp',
permissions: {
filters: ['prePostRender'],
helpers: ['myTestHelper'],
posts: ['browse', 'read', 'edit', 'add', 'delete']
}
});
appProxy.helpers.register('myTestHelper', sandbox.stub().returns('test result'));
@ -246,16 +235,15 @@ describe('Apps', function () {
});
it('does not allow helper registration without permission', function () {
var registerSpy = sandbox.spy(helpers, 'registerThemeHelper');
var appProxy = new AppProxy({
name: 'TestApp',
permissions: {
filters: ['prePostRender'],
helpers: ['myTestHelper'],
posts: ['browse', 'read', 'edit', 'add', 'delete']
}
});
var registerSpy = sandbox.spy(helpers, 'registerThemeHelper'),
appProxy = new AppProxy({
name: 'TestApp',
permissions: {
filters: ['prePostRender'],
helpers: ['myTestHelper'],
posts: ['browse', 'read', 'edit', 'add', 'delete']
}
});
function registerWithoutPermissions() {
appProxy.helpers.register('otherHelper', sandbox.stub().returns('test result'));

View File

@ -1,4 +1,4 @@
/*globals describe, after, before, beforeEach, afterEach, it*/
/*globals describe, before, beforeEach, afterEach, it*/
/*jshint expr:true*/
var should = require('should'),
Promise = require('bluebird'),
@ -120,7 +120,7 @@ describe('Error handling', function () {
logStub.calledOnce.should.be.true;
logStub.calledWith(
'\nERROR:'.red, 'An unknown error occurred.'.red, '\n', message.white, '\n', message.green , '\n'
'\nERROR:'.red, 'An unknown error occurred.'.red, '\n', message.white, '\n', message.green, '\n'
).should.be.true;
});
@ -364,18 +364,18 @@ describe('Error handling', function () {
errors.error500(err, req, res, null);
});
it('Renders custom error template if one exists', function(done){
it('Renders custom error template if one exists', function (done) {
var code = 404,
error = {message:'Custom view test'},
error = {message: 'Custom view test'},
req = {
session: null
},
res = {
status: function(code) {
status: function (code) {
/*jshint unused:false*/
return this;
},
render: function(view, model, fn){
render: function (view, model, fn) {
/*jshint unused:false*/
view.should.eql('error');
errors.updateActiveTheme('casper');

View File

@ -266,7 +266,7 @@ describe('Frontend Controller', function () {
});
});
describe('tag', function() {
describe('tag', function () {
var mockPosts = [{
'status': 'published',
'id': 1,
@ -298,7 +298,7 @@ describe('Frontend Controller', function () {
'name': 'video',
'slug': 'video',
'id': 1
},{
}, {
'name': 'audio',
'slug': 'audio',
'id': 2
@ -372,7 +372,7 @@ describe('Frontend Controller', function () {
render: function (view, context) {
assert.equal(view, 'tag');
assert.equal(context.tag, mockTags[0]);
assert.equal(context.posts[0].author.email, undefined)
assert.equal(context.posts[0].author.email, undefined);
done();
}
};
@ -542,7 +542,7 @@ describe('Frontend Controller', function () {
beforeEach(function () {
sandbox.stub(api.posts, 'read', function (args) {
return Promise.resolve(_.find(mockPosts, function(mock) {
return Promise.resolve(_.find(mockPosts, function (mock) {
return mock.posts[0].slug === args.slug;
}));
});
@ -645,7 +645,7 @@ describe('Frontend Controller', function () {
},
res = {
render: sinon.spy(),
redirect: function(arg) {
redirect: function (arg) {
res.render.called.should.be.false;
arg.should.eql(adminEditPagePath + mockPosts[0].posts[0].id + '/');
done();
@ -792,7 +792,7 @@ describe('Frontend Controller', function () {
},
res = {
render: sinon.spy(),
redirect: function(arg) {
redirect: function (arg) {
res.render.called.should.be.false;
arg.should.eql(adminEditPagePath + mockPosts[1].posts[0].id + '/');
done();

View File

@ -168,21 +168,21 @@ describe('Mail', function () {
});
it('should use from address as configured in config.js', function () {
overrideConfig({mail:{fromaddress: 'static@example.com'}});
overrideConfig({mail: {fromaddress: 'static@example.com'}});
mailer.fromAddress().should.equal('static@example.com');
});
it('should fall back to ghost@[blog.url] as from address', function () {
// Standard domain
overrideConfig({url: 'http://default.com', mail:{fromaddress: null}});
overrideConfig({url: 'http://default.com', mail: {fromaddress: null}});
mailer.fromAddress().should.equal('ghost@default.com');
// Trailing slash
overrideConfig({url: 'http://default.com/', mail:{}});
overrideConfig({url: 'http://default.com/', mail: {}});
mailer.fromAddress().should.equal('ghost@default.com');
// Strip Port
overrideConfig({url: 'http://default.com:2368/', mail:{}});
overrideConfig({url: 'http://default.com:2368/', mail: {}});
mailer.fromAddress().should.equal('ghost@default.com');
});
});

View File

@ -3,8 +3,6 @@
var assert = require('assert'),
should = require('should'),
sinon = require('sinon'),
_ = require('lodash'),
api = require('../../server/api'),
middleware = require('../../server/middleware').middleware;
describe('Middleware', function () {

View File

@ -1,4 +1,4 @@
/*globals describe, before, beforeEach, afterEach, after, it*/
/*globals describe, before, beforeEach, afterEach, it*/
/*jshint expr:true*/
var testUtils = require('../utils'),
should = require('should'),
@ -9,8 +9,8 @@ var testUtils = require('../utils'),
// Stuff we are testing
Models = require('../../server/models'),
permissions = require('../../server/permissions'),
effectivePerms = require('../../server/permissions/effective'),
context = testUtils.context.owner,
// effectivePerms = require('../../server/permissions/effective'),
// context = testUtils.context.owner,
sandbox = sinon.sandbox.create();

View File

@ -326,53 +326,52 @@ describe('Core Helpers', function () {
describe('Plural Helper', function () {
it('has loaded plural helper', function () {
should.exist(handlebars.helpers.plural);
});
it('has loaded plural helper', function () {
should.exist(handlebars.helpers.plural);
});
it('will show no-value string', function () {
var expected = 'No Posts',
rendered = helpers.plural.call({}, 0, {
'hash': {
'empty': 'No Posts',
'singular': '% Post',
'plural': '% Posts'
}
});
it('will show no-value string', function () {
var expected = 'No Posts',
rendered = helpers.plural.call({}, 0, {
'hash': {
'empty': 'No Posts',
'singular': '% Post',
'plural': '% Posts'
}
});
should.exist(rendered);
rendered.string.should.equal(expected);
});
should.exist(rendered);
rendered.string.should.equal(expected);
});
it('will show singular string', function () {
var expected = '1 Post',
rendered = helpers.plural.call({}, 1, {
'hash': {
'empty': 'No Posts',
'singular': '% Post',
'plural': '% Posts'
}
});
it('will show singular string', function () {
var expected = '1 Post',
rendered = helpers.plural.call({}, 1, {
'hash': {
'empty': 'No Posts',
'singular': '% Post',
'plural': '% Posts'
}
});
should.exist(rendered);
rendered.string.should.equal(expected);
});
should.exist(rendered);
rendered.string.should.equal(expected);
});
it('will show plural string', function () {
var expected = '2 Posts',
rendered = helpers.plural.call({}, 2, {
'hash': {
'empty': 'No Posts',
'singular': '% Post',
'plural': '% Posts'
}
});
it('will show plural string', function () {
var expected = '2 Posts',
rendered = helpers.plural.call({}, 2, {
'hash': {
'empty': 'No Posts',
'singular': '% Post',
'plural': '% Posts'
}
});
should.exist(rendered);
rendered.string.should.equal(expected);
});
});
should.exist(rendered);
rendered.string.should.equal(expected);
});
});
describe('Excerpt Helper', function () {
@ -845,7 +844,11 @@ describe('Core Helpers', function () {
it('should return the slug with a prefix slash if the context is a post', function (done) {
helpers.url.call({
html: 'content', markdown: 'ff', title: 'title', slug: 'slug', created_at: new Date(0)
html: 'content',
markdown: 'ff',
title: 'title',
slug: 'slug',
created_at: new Date(0)
}).then(function (rendered) {
should.exist(rendered);
rendered.should.equal('/slug/');
@ -868,7 +871,10 @@ describe('Core Helpers', function () {
it('should return the slug with a prefixed /tag/ if the context is a tag', function (done) {
helpers.url.call({
name: 'the tag', slug: 'the-tag', description: null, parent: null
name: 'the tag',
slug: 'the-tag',
description: null,
parent: null
}).then(function (rendered) {
should.exist(rendered);
rendered.should.equal('/tag/the-tag/');
@ -1025,7 +1031,8 @@ describe('Core Helpers', function () {
it('can render single page with no pagination necessary', function () {
var rendered = helpers.pagination.call({
pagination: {page: 1, prev: null, next: null, limit: 15, total: 8, pages: 1}, tag: {slug: 'slug'}
pagination: {page: 1, prev: null, next: null, limit: 15, total: 8, pages: 1},
tag: {slug: 'slug'}
});
should.exist(rendered);
// strip out carriage returns and compare.
@ -1373,11 +1380,11 @@ describe('Core Helpers', function () {
var rendered,
configOriginal;
before(function() {
before(function () {
configOriginal = helpers.__get__('config');
});
after(function() {
after(function () {
helpers.__set__('config', configOriginal);
});
@ -1708,11 +1715,11 @@ describe('Core Helpers', function () {
var rendered,
configOriginal;
before(function() {
before(function () {
configOriginal = helpers.__get__('config');
});
after(function() {
after(function () {
helpers.__set__('config', configOriginal);
});

View File

@ -131,8 +131,8 @@ describe('Local File System Storage', function () {
});
describe('when a custom content path is used', function () {
var origContentPath = config.paths.contentPath;
var origImagesPath = config.paths.imagesPath;
var origContentPath = config.paths.contentPath,
origImagesPath = config.paths.imagesPath;
beforeEach(function () {
config.paths.contentPath = config.paths.appRoot + '/var/ghostcms';

View File

@ -1,4 +1,4 @@
/*jshint unused:false*/
var lib = require('../goodlib.js');
module.exports = {

View File

@ -2,7 +2,7 @@ var _ = require('lodash'),
uuid = require('node-uuid'),
globalUtils = require('../../../server/utils'),
DataGenerator = {};
/*jshint quotmark:false*/
DataGenerator.Content = {
posts: [
{
@ -333,7 +333,7 @@ DataGenerator.forKnex = (function () {
return _.defaults(overrides, {
token: uuid.v4(),
client_id: 1,
expires:Date.now() + globalUtils.ONE_DAY_MS
expires: Date.now() + globalUtils.ONE_DAY_MS
});
}

View File

@ -21,7 +21,7 @@ function findFreePort(port) {
var server = net.createServer();
server.on('error', function(e) {
server.on('error', function (e) {
if (e.code === 'EADDRINUSE') {
resolve(findFreePort(port));
} else {
@ -29,9 +29,9 @@ function findFreePort(port) {
}
});
server.listen(port, function() {
server.listen(port, function () {
var listenPort = server.address().port;
server.close(function() {
server.close(function () {
resolve(listenPort);
});
});
@ -52,7 +52,7 @@ function forkGhost(newConfig, envName) {
envName = envName || 'forked';
return findFreePort(newConfig.server ? newConfig.server.port : undefined)
.then(function(port) {
.then(function (port) {
newConfig.server = newConfig.server || {};
newConfig.server.port = port;
newConfig.url = url.format(_.extend(url.parse(newConfig.url), {port: port, host: null}));
@ -60,63 +60,68 @@ function forkGhost(newConfig, envName) {
var newConfigFile = path.join(config.paths.appRoot, 'config.test' + port + '.js');
return new Promise(function (resolve, reject) {
fs.writeFile(newConfigFile, 'module.exports = {' + envName + ': ' + JSON.stringify(newConfig) + '}', function(err) {
fs.writeFile(newConfigFile, 'module.exports = {' + envName + ': ' + JSON.stringify(newConfig) + '}', function (err) {
if (err) {
return reject(err);
}
// setup process environment for the forked Ghost to use the new config file
var env = _.clone(process.env);
var env = _.clone(process.env),
baseKill,
child,
pingTries = 0,
pingCheck,
pingStop = function () {
if (pingCheck) {
clearInterval(pingCheck);
pingCheck = undefined;
return true;
}
return false;
};
env['GHOST_CONFIG'] = newConfigFile;
env['NODE_ENV'] = envName;
var child = cp.fork(path.join(config.paths.appRoot, 'index.js'), {env: env});
var pingTries = 0;
var pingCheck;
var pingStop = function() {
if (pingCheck) {
clearInterval(pingCheck);
pingCheck = undefined;
return true;
}
return false;
};
child = cp.fork(path.join(config.paths.appRoot, 'index.js'), {env: env});
// periodic check until forked Ghost is running and is listening on the port
pingCheck = setInterval(function() {
pingCheck = setInterval(function () {
var socket = net.connect(port);
socket.on('connect', function() {
socket.on('connect', function () {
socket.end();
if (pingStop()) {
resolve(child);
}
});
socket.on('error', function(err) {
socket.on('error', function (err) {
/*jshint unused:false*/
pingTries = pingTries + 1;
// continue checking
if (++pingTries >= 20 && pingStop()) {
reject(new Error("Timed out waiting for child process"));
if (pingTries >= 20 && pingStop()) {
reject(new Error('Timed out waiting for child process'));
}
});
}, 200);
child.on('exit', function(code, signal) {
child.on('exit', function (code, signal) {
/*jshint unused:false*/
child.exited = true;
if (pingStop()) {
reject(new Error("Child process exit code: " + code));
reject(new Error('Child process exit code: ' + code));
}
// cleanup the temporary config file
fs.unlink(newConfigFile);
});
// override kill() to have an async callback
var baseKill = child.kill;
child.kill = function(signal, cb) {
baseKill = child.kill;
child.kill = function (signal, cb) {
if (typeof signal === 'function') {
cb = signal;
signal = undefined;
}
if (cb) {
child.on('exit', function() {
child.on('exit', function () {
cb();
});
}

View File

@ -39,8 +39,8 @@ fixtures = {
},
insertMultiAuthorPosts: function insertMultiAuthorPosts(max) {
/*jshint unused:false*/
var knex = config.database.knex,
tags,
author,
authors,
i, j, k = postsInserted,
@ -48,10 +48,10 @@ fixtures = {
max = max || 50;
// insert users of different roles
return Promise.resolve(fixtures.createUsersWithRoles()).then(function (results) {
return Promise.resolve(fixtures.createUsersWithRoles()).then(function () {
// create the tags
return knex('tags').insert(DataGenerator.forKnex.tags);
}).then(function (results) {
}).then(function () {
return knex('users').select('id');
}).then(function (results) {
authors = _.pluck(results, 'id');
@ -59,7 +59,8 @@ fixtures = {
// Let's insert posts with random authors
for (i = 0; i < max; i += 1) {
author = authors[i % authors.length];
posts.push(DataGenerator.forKnex.createGenericPost(k++, null, null, author));
posts.push(DataGenerator.forKnex.createGenericPost(k, null, null, author));
k = k + 1;
}
// Keep track so we can run this function again safely
@ -109,11 +110,13 @@ fixtures = {
for (i = 0; i < 2; i += 1) {
lang = i % 2 ? 'en' : 'fr';
posts.push(DataGenerator.forKnex.createGenericPost(k++, null, lang));
posts.push(DataGenerator.forKnex.createGenericPost(k, null, lang));
k = k + 1;
for (j = 0; j < max; j += 1) {
status = j % 2 ? 'draft' : 'published';
posts.push(DataGenerator.forKnex.createGenericPost(k++, status, lang));
posts.push(DataGenerator.forKnex.createGenericPost(k, status, lang));
k = k + 1;
}
}
@ -224,9 +227,9 @@ fixtures = {
return knex('users').insert(extraUsers).then(function () {
return knex('roles_users').insert([
{ user_id: 5, role_id: 1},
{ user_id: 6, role_id: 2},
{ user_id: 7, role_id: 3}
{ user_id: 5, role_id: 1},
{ user_id: 6, role_id: 2},
{ user_id: 7, role_id: 3}
]);
});
},
@ -256,9 +259,9 @@ fixtures = {
return knex('users').insert(extraUsers).then(function () {
return knex('roles_users').insert([
{ user_id: 8, role_id: 1},
{ user_id: 9, role_id: 2},
{ user_id: 10, role_id: 3}
{ user_id: 8, role_id: 1},
{ user_id: 9, role_id: 2},
{ user_id: 10, role_id: 3}
]);
});
},