0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-01-13 22:41:32 -05:00

Merge pull request #2978 from ErisDS/ember-test

[WIP] Functional tests for Ember
This commit is contained in:
Hannah Wolfe 2014-06-20 16:06:56 +01:00
commit d2d47b14e4
18 changed files with 1254 additions and 42 deletions

View file

@ -494,6 +494,7 @@ var path = require('path'),
'core/built/scripts/vendor-ember.js': [
'bower_components/loader.js/loader.js',
'bower_components/jquery/dist/jquery.js',
'bower_components/lodash/dist/lodash.js',
'bower_components/handlebars/handlebars.js',
'bower_components/ember/ember.js',
'bower_components/ember-data/ember-data.js',
@ -604,11 +605,14 @@ var path = require('path'),
// ### Spawn Casper.js
// Custom test runner for our Casper.js functional tests
// This really ought to be refactored into a separate grunt task module
grunt.registerTask('spawnCasperJS', function () {
grunt.registerTask('spawnCasperJS', function (target) {
target = _.contains(['client', 'clientold', 'frontend'], target) ? target + '/' : undefined;
var done = this.async(),
options = ['host', 'noPort', 'port', 'email', 'password'],
args = ['test']
.concat(grunt.option('target') || ['admin/', 'frontend/'])
.concat(grunt.option('target') || target || ['client/', 'frontend/'])
.concat(['--includes=base.js', '--log-level=debug', '--port=2369']);
// Forward parameters from grunt to casperjs
@ -725,8 +729,8 @@ var path = require('path'),
//
// `NODE_ENV=testing grunt mochacli:section`
//
// If you need to run an individual unit test file, you can do so, providing you have mocha installed globally by
// using a command in the form:
// If you need to run an individual unit test file, you can do so, providing you have mocha installed globally
// by using a command in the form:
//
// `NODE_ENV=testing mocha --timeout=15000 --ui=bdd --reporter=spec core/test/unit/config_spec.js`
//

View file

@ -28,6 +28,7 @@
"DS": true,
"$": true,
"validator": true,
"ic": true
"ic": true,
"_": true
}
}

View file

@ -1,12 +1,13 @@
/* global CodeMirror*/
/*global CodeMirror */
import MarkerManager from 'ghost/mixins/marker-manager';
import setScrollClassName from 'ghost/utils/set-scroll-classname';
var onChangeHandler = function (cm, changeObj) {
var line,
component = cm.component,
checkLine = component.checkLine.bind(component),
checkMarkers = component.checkMarkers.bind(component);
checkLine = _.bind(component.checkLine, component),
checkMarkers = _.bind(component.checkMarkers, component);
// fill array with a range of numbers
for (line = changeObj.from.line; line < changeObj.from.line + changeObj.text.length; line += 1) {
@ -37,7 +38,7 @@ var Codemirror = Ember.TextArea.extend(MarkerManager, {
},
afterRenderEvent: function () {
var initMarkers = this.initMarkers.bind(this);
var initMarkers = _.bind(this.initMarkers, this);
this.initCodemirror();
this.codemirror.eachLine(initMarkers);

View file

@ -25,10 +25,10 @@ var Markdown = Ember.Component.extend({
filestorage: false
});
dropzones.on('uploadstart', this.sendAction.bind(this, 'uploadStarted'));
dropzones.on('uploadfailure', this.sendAction.bind(this, 'uploadFinished'));
dropzones.on('uploadsuccess', this.sendAction.bind(this, 'uploadFinished'));
dropzones.on('uploadsuccess', this.sendAction.bind(this, 'uploadSuccess'));
dropzones.on('uploadstart', _.bind(this.sendAction, this, 'uploadStarted'));
dropzones.on('uploadfailure', _.bind(this.sendAction, this, 'uploadFinished'));
dropzones.on('uploadsuccess', _.bind(this.sendAction, this, 'uploadFinished'));
dropzones.on('uploadsuccess', _.bind(this.sendAction, this, 'uploadSuccess'));
});
}.observes('markdown')
});

View file

@ -113,7 +113,7 @@ var PostSettingsMenuController = Ember.ObjectController.extend({
// if the candidate slug is the same as the existing slug except
// for the incrementor then the existing slug should be used
if (Number.isInteger(check) && check > 0) {
if (_.isNumber(check) && check > 0) {
if (slug === slugTokens.join('-') && serverSlug !== newSlug) {
return;
}

View file

@ -27,9 +27,9 @@ var DEBUG = false, // TOGGLE THIS TO GET MORE SCREENSHOTS
port = casper.cli.options.port || '2368',
email = casper.cli.options.email || 'jbloggs@example.com',
password = casper.cli.options.password || 'Sl1m3rson',
url = "http://" + host + (noPort ? '/' : ":" + port + "/"),
url = 'http://' + host + (noPort ? '/' : ':' + port + '/'),
newUser = {
name: "Test User",
name: 'Test User',
email: email,
password: password
},
@ -42,12 +42,12 @@ var DEBUG = false, // TOGGLE THIS TO GET MORE SCREENSHOTS
password: 'letmethrough'
},
testPost = {
title: "Bacon ipsum dolor sit amet",
html: "I am a test post.\n#I have some small content"
title: 'Bacon ipsum dolor sit amet',
html: 'I am a test post.\n#I have some small content'
};
casper.writeContentToCodeMirror = function (content) {
var lines = content.split("\n");
var lines = content.split('\n');
casper.waitForSelector('.CodeMirror-wrap textarea', function onSuccess() {
casper.each(lines, function (self, line) {
@ -62,13 +62,15 @@ casper.writeContentToCodeMirror = function (content) {
};
casper.waitForOpaque = function (classname, then, timeout) {
timeout = timeout || casper.failOnTimeout(casper.test, 'waitForOpaque failed on ' + classname);
casper.waitFor(function checkOpaque() {
var value = this.evaluate(function (element) {
var target = document.querySelector(element);
if (target === null) {
return null;
}
return window.getComputedStyle(target).getPropertyValue('opacity') === "1";
return window.getComputedStyle(target).getPropertyValue('opacity') === '1';
}, classname);
if (value !== true && value !== false) {
casper.test.fail('Unable to find element: ' + classname);
@ -77,17 +79,77 @@ casper.waitForOpaque = function (classname, then, timeout) {
}, then, timeout);
};
// ### Then Open And Wait For Page Load
// Always wait for the `#main` element as some indication that the ember app has loaded.
casper.thenOpenAndWaitForPageLoad = function (screen, then, timeout) {
then = then || function () {};
timeout = timeout || casper.failOnTimeout(casper.test, 'Unable to load ' + screen);
var screens = {
'root': {
url: 'ghost/ember/',
selector: '#main-menu .content.active'
},
'content': {
url: 'ghost/ember/content/',
selector: '#main-menu .content.active'
},
'editor': {
url: 'ghost/ember/editor/',
selector: '#main-menu .editor.active'
},
'settings': {
url: 'ghost/ember/settings/',
selector: '.settings-content'
},
'settings.general': {
url: 'ghost/ember/settings/general',
selector: '.settings-content form#settings-general'
},
'settings.user': {
url: 'ghost/ember/settings/user',
selector: '.settings-content form.user-profile'
},
'signin': {
url: 'ghost/ember/signin/',
selector: '.button-save'
},
'signout': {
url: 'ghost/ember/signout/',
selector: '.button-save'
},
'signup': {
url: 'ghost/ember/signup/',
selector: '.button-save'
}
};
return casper.thenOpen(url + screens[screen].url).then(function () {
return casper.waitForSelector(screens[screen].selector, then, timeout, 15000);
});
};
casper.failOnTimeout = function (test, message) {
return function onTimeout() {
test.fail(message);
};
};
// ### Fill And Save
// With Ember in place, we don't want to submit forms, rather press the green button which always has a class of
// 'button-save'. This method handles that smoothly.
casper.fillAndSave = function (selector, data) {
casper.fill(selector, data, false);
casper.thenClick(selector + ' .button-save');
};
// ## Echo Concise
// Does casper.echo but checks for the presence of the --concise flag
casper.echoConcise = function (message, style) {
if (!casper.cli.options.concise) {
casper.echo(message, style);
}
}
};
// ## Debugging
// output all errors to the console
@ -99,24 +161,30 @@ casper.on('error', function (msg) {
casper.echoConcise('GOT ERROR, ' + msg);
});
casper.on("page.error", function (msg) {
casper.echoConcise("GOT PAGE ERROR: " + msg, "ERROR");
casper.on('page.error', function (msg) {
casper.echoConcise('GOT PAGE ERROR: ' + msg, 'ERROR');
});
casper.captureScreenshot = function (filename, debugOnly) {
debugOnly = debugOnly !== false;
// If we are in debug mode, OR debugOnly is false
if (DEBUG || debugOnly === false) {
filename = filename || "casper_test_fail.png";
filename = filename || 'casper_test_fail.png';
casper.then(function () {
casper.capture(new Date().getTime() + '_' + filename);
});
}
};
// on failure, grab a screenshot
casper.test.on("fail", function captureFailure(test) {
casper.captureScreenshot(casper.test.filename || "casper_test_fail.png", false);
casper.test.on('fail', function captureFailure(test) {
casper.captureScreenshot(casper.test.filename || 'casper_test_fail.png', false);
casper.then(function () {
console.log(casper.getHTML());
casper.exit(1);
});
});
var CasperTest = (function () {
@ -129,11 +197,7 @@ var CasperTest = (function () {
casper.test.tearDown(function (done) {
casper.then(_beforeDoneHandler);
casper.thenOpen(url + 'ghost\/signout/');
casper.waitForResource(/ghost\/sign/);
casper.captureScreenshot('teardown.png');
CasperTest.Routines.emberSignout.run();
casper.run(done);
});
@ -179,6 +243,48 @@ var CasperTest = (function () {
}
}
function emberBegin(testName, expect, suite, doNotAutoLogin) {
_beforeDoneHandler = _noop;
var runTest = function (test) {
test.filename = testName.toLowerCase().replace(/ /g, '-').concat('.png');
casper.start('about:blank').viewport(1280, 1024);
if (!doNotAutoLogin) {
// Only call register once for the lifetime of CasperTest
if (!_isUserRegistered) {
CasperTest.Routines.emberSignout.run();
CasperTest.Routines.emberSignup.run();
_isUserRegistered = true;
}
/* Ensure we're logged out at the start of every test or we may get
unexpected failures. */
CasperTest.Routines.emberSignout.run();
CasperTest.Routines.emberSignin.run();
}
suite.call(casper, test);
casper.run(function () {
test.done();
});
};
if (typeof expect === 'function') {
doNotAutoLogin = suite;
suite = expect;
casper.test.begin(testName, runTest);
} else {
casper.test.begin(testName, expect, runTest);
}
}
// Sets a handler to be invoked right before `test.done` is invoked
function beforeDone(fn) {
if (fn) {
@ -190,6 +296,7 @@ var CasperTest = (function () {
return {
begin: begin,
emberBegin: emberBegin,
beforeDone: beforeDone
};
@ -198,7 +305,7 @@ var CasperTest = (function () {
CasperTest.Routines = (function () {
function register(test) {
casper.thenOpen(url + 'ghost/signup/').viewport(1280, 1024);
casper.thenOpen(url + 'ghost/signup/');
casper.waitForOpaque('.signup-box', function then() {
this.fill('#signup', newUser, true);
@ -214,15 +321,43 @@ CasperTest.Routines = (function () {
}, 2000);
}
function emberSignup() {
casper.thenOpenAndWaitForPageLoad('signup', function then() {
casper.captureScreenshot('ember_signing_up1.png');
casper.waitForOpaque('.signup-box', function then() {
this.fillAndSave('#signup', newUser);
});
casper.captureScreenshot('ember_signing_up2.png');
casper.waitForSelectorTextChange('.notification-error', function onSuccess() {
var errorText = casper.evaluate(function () {
return document.querySelector('.notification-error').innerText;
});
casper.echoConcise('It appears as though a user is already registered. Error text: ' + errorText);
}, function onTimeout() {
casper.echoConcise('It appears as though a user was not already registered.');
}, 2000);
casper.captureScreenshot('ember_signing_up3.png');
});
}
function login(test) {
casper.thenOpen(url + 'ghost/signin/');
casper.waitForResource(/ghost\/signin/);
casper.waitForSelector('.login-box', function () {}, function () {
console.log(casper.getHTML());
});
casper.waitForOpaque('.login-box', function then() {
casper.captureScreenshot("got_sign_in.png");
this.fill("#login", user, true);
casper.captureScreenshot("filled_sign_in.png");
casper.captureScreenshot('got_sign_in.png');
this.fill('#login', user, true);
casper.captureScreenshot('filled_sign_in.png');
});
casper.waitForResource(/ghost\/$/).then(function () {
@ -230,17 +365,41 @@ CasperTest.Routines = (function () {
});
}
function logout(test) {
casper.thenOpen(url + 'ghost\/signout/');
function emberSignin() {
casper.thenOpenAndWaitForPageLoad('signin', function then() {
casper.captureScreenshot("logging_out.png");
casper.waitForOpaque('.login-box', function then() {
casper.captureScreenshot('ember_signing_in.png');
this.fillAndSave('#login', user);
casper.captureScreenshot('ember_signing_in2.png');
});
casper.waitForResource(/posts\/\?status=all&staticPages=all/, function then() {
casper.captureScreenshot('ember_signing_in3.png');
}, function timeout() {
casper.test.fail('Unable to signin and load admin panel');
});
});
}
function logout(test) {
casper.thenOpen(url + 'ghost/signout/');
casper.captureScreenshot('logging_out.png');
// Wait for signin or signup
casper.waitForResource(/ghost\/sign/);
}
function emberSignout() {
casper.thenOpenAndWaitForPageLoad('signout', function then() {
casper.captureScreenshot('ember_signing_out.png');
});
}
// This will need switching over to ember once settings general is working properly.
function togglePermalinks(state) {
casper.thenOpen(url + "ghost/settings/general");
casper.thenOpen(url + 'ghost/settings/general');
casper.waitForResource(/ghost\/settings\/general/);
@ -253,15 +412,47 @@ CasperTest.Routines = (function () {
casper.thenClick('#permalinks');
casper.thenClick('.button-save');
casper.captureScreenshot("saving.png");
casper.captureScreenshot('saving.png');
casper.waitForSelector('.notification-success', function () {
casper.captureScreenshot("saved.png");
casper.captureScreenshot('saved.png');
});
}
});
}
function createTestPost(publish) {
casper.thenOpenAndWaitForPageLoad('editor', function createTestPost() {
casper.sendKeys('#entry-title', testPost.title);
casper.writeContentToCodeMirror(testPost.html);
casper.sendKeys('#entry-tags input.tag-input', 'TestTag');
casper.sendKeys('#entry-tags input.tag-input', casper.page.event.key.Enter);
});
casper.waitForSelectorTextChange('.entry-preview .rendered-markdown');
if (publish) {
// Open the publish options menu;
casper.thenClick('.js-publish-splitbutton .options.up');
casper.waitForOpaque('.js-publish-splitbutton .open');
// Select the publish post button
casper.thenClick('.js-publish-splitbutton li:first-child a');
casper.waitForSelectorTextChange('.js-publish-button', function onSuccess() {
casper.thenClick('.js-publish-button');
});
} else {
casper.thenClick('.js-publish-button');
}
// **Note:** This should include tags on all post requests! Uncomment and replace lines below with this when fixed.
// casper.waitForResource(/posts\/\?include=tags$/);
casper.waitForResource(/posts\/$/);
}
function _createRunner(fn) {
fn.run = function run(test) {
var routine = this;
@ -278,7 +469,11 @@ CasperTest.Routines = (function () {
register: _createRunner(register),
login: _createRunner(login),
logout: _createRunner(logout),
togglePermalinks: _createRunner(togglePermalinks)
togglePermalinks: _createRunner(togglePermalinks),
emberSignup: _createRunner(emberSignup),
emberSignin: _createRunner(emberSignin),
emberSignout: _createRunner(emberSignout),
createTestPost: _createRunner(createTestPost)
};
}());

View file

@ -0,0 +1,67 @@
// # App Test
// Tests that the general layout & functionality of global admin components is correct
/*globals casper, __utils__, url, testPost, newUser */
CasperTest.emberBegin('Admin navigation bar is correct', 28, function suite(test) {
casper.thenOpenAndWaitForPageLoad('root', function testTitleAndUrl() {
test.assertTitle('Ghost Admin', 'Ghost admin has no title');
test.assertUrlMatch(/ghost\/ember\/\d+\/$/, 'Landed on the correct URL');
});
casper.then(function testNavItems() {
var logoHref = this.getElementAttribute('a.ghost-logo', 'href'),
contentHref = this.getElementAttribute('#main-menu li.content a', 'href'),
editorHref = this.getElementAttribute('#main-menu li.editor a', 'href'),
settingsHref = this.getElementAttribute('#main-menu li.settings a', 'href');
// Logo
test.assertExists('a.ghost-logo', 'Ghost logo home page link exists');
test.assertEquals(logoHref, '/', 'Ghost logo href is correct');
// Content
test.assertExists('#main-menu li.content a', 'Content nav item exists');
test.assertSelectorHasText('#main-menu li.content a', 'Content', 'Content nav item has correct text');
test.assertEquals(contentHref, '/ghost/ember/', 'Content href is correct');
test.assertExists('#main-menu li.content.active', 'Content nav item is not marked active');
// Editor
test.assertExists('#main-menu li.editor a', 'Editor nav item exists');
test.assertSelectorHasText('#main-menu li.editor a', 'New Post', 'Editor nav item has correct text');
test.assertEquals(editorHref, '/ghost/ember/editor/', 'Editor href is correct');
test.assertDoesntExist('#main-menu li.editor.active', 'Editor nav item is not marked active');
// Settings
test.assertExists('#main-menu li.settings a', 'Settings nav item exists');
test.assertSelectorHasText('#main-menu li.settings a', 'Settings', 'Settings nav item has correct text');
test.assertEquals(settingsHref, '/ghost/ember/settings/', 'Settings href is correct');
test.assertDoesntExist('#main-menu li.settings.active', 'Settings nav item is marked active');
});
casper.then(function testUserMenuNotVisible() {
test.assertExists('#usermenu', 'User menu nav item exists');
test.assertNotVisible('#usermenu ul.overlay', 'User menu should not be visible');
});
casper.thenClick('#usermenu a');
casper.waitForSelector('#usermenu ul.overlay', function then() {
var profileHref = this.getElementAttribute('#usermenu li.usermenu-profile a', 'href'),
helpHref = this.getElementAttribute('#usermenu li.usermenu-help a', 'href'),
signoutHref = this.getElementAttribute('#usermenu li.usermenu-signout a', 'href');
test.assertVisible('#usermenu ul.overlay', 'User menu should be visible');
test.assertExists('#usermenu li.usermenu-profile a', 'Profile menu item exists');
test.assertSelectorHasText('#usermenu li.usermenu-profile a', 'Your Profile',
'Profile menu item has correct text');
test.assertEquals(profileHref, '/ghost/ember/settings/user/', 'Profile href is correct');
test.assertExists('#usermenu li.usermenu-help a', 'Help menu item exists');
test.assertSelectorHasText('#usermenu li.usermenu-help a', 'Help / Support', 'Help menu item has correct text');
test.assertEquals(helpHref, 'http://support.ghost.org/', 'Help href is correct');
test.assertExists('#usermenu li.usermenu-signout a', 'Sign Out menu item exists');
test.assertSelectorHasText('#usermenu li.usermenu-signout a', 'Sign Out', 'Signout menu item has correct text');
test.assertEquals(signoutHref, '/ghost/ember/signout/', 'Sign Out href is correct');
}, casper.failOnTimeout(test, 'WaitForSelector #usermenu ul.overlay failed'));
});

View file

@ -0,0 +1,321 @@
// # Content Test
// Test the content screen, uses the editor to create dummy content
/*globals casper, __utils__, url, testPost, newUser */
CasperTest.emberBegin("Content screen is correct", 17, function suite(test) {
// First, create a sample post for testing (this should probably be a routine)
CasperTest.Routines.createTestPost.run(false);
// Begin test
casper.thenOpenAndWaitForPageLoad('content', function testTitleAndUrl() {
test.assertTitle("Ghost Admin", "Ghost admin has no title");
test.assertUrlMatch(/ghost\/ember\/\d+\/$/, "Landed on the correct URL");
});
casper.then(function testViews() {
test.assertExists(".content-view-container", "Content main view is present");
test.assertExists(".content-list-content", "Content list view is present");
test.assertExists('.content-list .floatingheader a.button.button-add', 'add new post button exists');
test.assertEquals(this.getElementAttribute('.content-list .floatingheader a.button.button-add', 'href'), '/ghost/ember/editor/', 'add new post href is correct');
test.assertExists(".content-list-content li .entry-title", "Content list view has at least one item");
test.assertSelectorHasText(".content-list-content li:first-of-type h3", testPost.title, "title is present and has content");
test.assertSelectorHasText(".content-list-content li:first-of-type .entry-meta .status .draft", 'Draft', "status is present has content");
test.assertExists(".content-preview", "Content preview is present");
test.assertSelectorHasText('.content-preview header .status', 'Written', 'preview header contains "Written" when post is a draft');
test.assertSelectorHasText('.content-preview header .author', newUser.name, 'preview header contains author name');
});
casper.then(function testEditPostButton() {
test.assertExists('.content-preview a.post-edit', 'edit post button exists');
});
casper.then(function testPostSettingsMenu() {
test.assertExists('.content-preview a.post-settings', 'post settings button exists');
this.click('.content-preview a.post-settings');
});
casper.waitUntilVisible('.post-settings-menu', function onSuccess() {
test.assert(true, 'post settings menu should be visible after clicking post-settings icon');
});
casper.then(function postSettingsMenuItems() {
test.assertExists('.post-settings-menu #static-page', 'post settings static page exists');
test.assertExists('.post-settings-menu a.delete', 'post settings delete this post exists');
});
// A bug is causing this to not always be activated. Uncomment when fixed
// casper.then(function testActiveItem() {
// test.assertExists('.content-list-content li:first-of-type .active', 'first item is active');
// test.assertDoesntExist('.content-list-content li:nth-of-type(2) .active', 'second item is not active');
//
// // Ember adds script tags into the list so we need to use nth-of-type
// }).thenClick(".content-list-content li:nth-of-type(2) a", function then() {
// test.assertDoesntExist('.content-list-content li:first-of-type .active', 'first item is not active');
// test.assertExists('.content-list-content li:nth-of-type(2) .active', 'second item is active');
// });
});
CasperTest.emberBegin('Content list shows correct post status', 7, function testStaticPageStatus(test) {
CasperTest.Routines.createTestPost.run(true);
// Begin test
casper.thenOpenAndWaitForPageLoad('content', function testTitleAndUrl() {
test.assertTitle('Ghost Admin', 'Ghost admin has no title');
test.assertUrlMatch(/ghost\/ember\/\d+\/$/, "Landed on the correct URL");
});
// Select first non-draft, non-static post. Should be second in the list at this stage of testing.
casper.thenClick('.content-list-content li:nth-of-type(2) a');
// Test for status of 'Published'
casper.then(function checkStatus() {
test.assertSelectorHasText('.content-list-content li.active .entry-meta .status time', 'Published',
'status is present and labeled as published');
});
// Test for 'Published' in header
casper.then(function testHeader() {
test.assertSelectorHasText('.content-preview header .status', 'Published', 'preview header contains "Published" when post is published');
test.assertSelectorHasText('.content-preview header .author', newUser.name, 'preview header contains author name');
});
// Change post to static page
casper.thenClick('a.post-settings');
casper.waitUntilVisible('.post-settings-menu', function onSuccess() {
test.assert(true, 'post settings menu should be visible after clicking post-settings icon');
});
casper.thenClick('.post-settings-menu #static-page');
casper.waitForSelector('.content-list-content li .entry-meta .status .page', function waitForSuccess() {
test.assertSelectorHasText('.content-list-content li .entry-meta .status .page', 'Page', 'status is Page');
}, function onTimeout() {
test.assert(false, 'status did not change');
});
});
CasperTest.emberBegin('Delete post modal', 7, function testDeleteModal(test) {
// Create a post that can be deleted
CasperTest.Routines.createTestPost.run(false);
// Begin test
casper.thenOpenAndWaitForPageLoad('content', function testTitleAndUrl() {
test.assertTitle('Ghost Admin', 'Ghost admin has no title');
test.assertUrlMatch(/ghost\/ember\/\d+\/$/, "Landed on the correct URL");
});
// Open post settings menu
casper.thenClick('.content-preview a.post-settings');
casper.waitForOpaque('.content-preview .post-settings-menu.open');
casper.thenClick('.post-settings-menu a.delete');
casper.waitUntilVisible('#modal-container', function onSuccess() {
test.assertSelectorHasText(
'.modal-content .modal-header',
'Are you sure you want to delete this post?',
'delete modal has correct text');
});
casper.thenClick('.js-button-reject');
casper.waitWhileVisible("#modal-container", function onSuccess() {
test.assert(true, "clicking cancel should close the delete post modal");
});
// Test delete
casper.thenClick('.content-preview a.post-settings');
casper.thenClick('.post-settings-menu a.delete');
casper.waitForSelector('#modal-container .modal-content', function onSuccess() {
test.assertExists('.modal-content .js-button-accept', 'delete button exists');
// Delete the post
this.click('.modal-content .js-button-accept');
casper.waitForSelector('.notification-success', function onSuccess() {
test.assert(true, 'Got success notification from delete post');
test.assertSelectorHasText('.notification-success', 'Your post has been deleted.');
}, function onTimeout() {
test.fail('No success notification from delete post');
});
});
});
// Uncomment when test is implemented... much needed!
//CasperTest.emberBegin('Infinite scrolling', 2, function suite(test) {
// // Placeholder for infinite scrolling/pagination tests (will need to setup 16+ posts).
//
// casper.thenOpenAndWaitForPageLoad('content', function testTitleAndUrl() {
// test.assertTitle('Ghost Admin', 'Ghost admin has no title');
// test.assertUrlMatch(/ghost\/ember\/\d+\/$/, "Landed on the correct URL");
// });
//});
CasperTest.emberBegin("Posts can be marked as featured", 10, function suite(test) {
// Create a sample post
CasperTest.Routines.createTestPost.run(false);
// Begin test
casper.thenOpenAndWaitForPageLoad('content', function testTitleAndUrl() {
test.assertTitle("Ghost Admin", "Ghost admin has no title");
test.assertUrlMatch(/ghost\/ember\/\d+\/$/, "Landed on the correct URL");
});
// Mark as featured
casper.waitForSelector('.content-preview .unfeatured', function () {
this.click('.content-preview .unfeatured');
}, function onTimeOut() {
test.assert(false, 'The first post can\'t be marked as featured');
});
casper.waitForSelector('.notification-success', function waitForSuccess() {
test.assert(true, 'got success notification');
test.assertSelectorHasText('.notification-success', 'Post successfully marked as featured.');
}, function onTimeout() {
test.assert(false, 'No success notification :(');
});
casper.waitForSelector('.content-list-content li.featured:first-of-type', function () {
test.assertExists('.content-preview .featured', 'preview pane gets featured class');
test.assertExists('.content-list-content li.featured:first-of-type', 'content list got a featured star');
this.click('.notification-success .close');
}, function onTimeout() {
test.assert(false, 'No featured star appeared in the left pane');
});
// Mark as not featured
casper.waitWhileSelector('.notification-success', function waitForNoSuccess() {
this.click('.content-preview .featured');
}, function onTimeout() {
test.assert(false, 'Success notification wont go away:(');
});
casper.waitForSelector('.notification-success', function waitForSuccess() {
test.assert(true, 'got success notification');
test.assertSelectorHasText('.notification-success', 'Post successfully marked as not featured.');
test.assertDoesntExist('.content-preview .featured');
test.assertDoesntExist('.content-list-content li.featured:first-of-type');
}, function onTimeout() {
test.assert(false, 'Success notification wont go away:(');
});
});
CasperTest.emberBegin('Post url can be changed', 7, function suite(test) {
// Create a sample post
CasperTest.Routines.createTestPost.run(false);
// Begin test
casper.thenOpenAndWaitForPageLoad('content', function testTitleAndUrl() {
test.assertTitle('Ghost Admin', 'Ghost admin has no title');
test.assertUrlMatch(/ghost\/ember\/\d+\/$/, "Landed on the correct URL");
});
casper.thenClick('a.post-settings');
casper.waitUntilVisible('.post-settings-menu', function onSuccess() {
test.assert(true, 'post settings menu should be visible after clicking post-settings icon');
});
// Test change permalink
casper.then(function () {
this.fillSelectors('.post-settings-menu form', {
'#url': 'new-url'
}, false);
this.click('a.post-settings')
});
casper.waitForSelector('.notification-success', function waitForSuccess() {
test.assert(true, 'got success notification');
test.assertSelectorHasText('.notification-success', 'Permalink successfully changed to new-url.');
casper.click('.notification-success a.close');
}, function onTimeout() {
test.assert(false, 'No success notification');
});
casper.waitWhileSelector('.notification-success', function () {
test.assert(true, 'notification cleared.');
test.assertNotVisible('.notification-success', 'success notification should not still exist');
});
});
CasperTest.emberBegin('Post published date can be changed', 7, function suite(test) {
// Create a sample post
CasperTest.Routines.createTestPost.run(false);
// Begin test
casper.thenOpenAndWaitForPageLoad('content', function testTitleAndUrl() {
test.assertTitle('Ghost Admin', 'Ghost admin has no title');
test.assertUrlMatch(/ghost\/ember\/\d+\/$/, "Landed on the correct URL");
});
casper.thenClick('a.post-settings');
casper.waitUntilVisible('.post-settings-menu', function onSuccess() {
test.assert(true, 'post settings menu should be visible after clicking post-settings icon');
});
// Test change published date
casper.then(function () {
this.fillSelectors('.post-settings-menu form', {
'.post-setting-date': '22 May 14 @ 23:39'
}, false);
this.click('a.post-settings')
});
casper.waitForSelector('.notification-success', function waitForSuccess() {
test.assert(true, 'got success notification');
test.assertSelectorHasText('.notification-success', 'Publish date successfully changed to 22 May 14 @ 23:39.');
casper.click('.notification-success a.close');
}, function onTimeout() {
test.assert(false, 'No success notification');
});
casper.waitWhileSelector('.notification-success', function () {
test.assert(true, 'notification cleared.');
test.assertNotVisible('.notification-success', 'success notification should not still exist');
});
});
CasperTest.emberBegin('Post can be changed to static page', 7, function suite(test) {
// Create a sample post
CasperTest.Routines.createTestPost.run(false);
// Begin test
casper.thenOpenAndWaitForPageLoad('content', function testTitleAndUrl() {
test.assertTitle('Ghost Admin', 'Ghost admin has no title');
test.assertUrlMatch(/ghost\/ember\/\d+\/$/, "Landed on the correct URL");
});
casper.thenClick('.content-preview a.post-settings');
casper.waitForOpaque('.content-preview .post-settings-menu.open', function onSuccess() {
test.assert(true, 'post settings should be visible after clicking post-settings icon');
});
casper.thenClick('.post-settings-menu .post-setting-static-page');
casper.waitForSelector('.notification-success', function waitForSuccess() {
test.assert(true, 'got success notification');
casper.click('.notification-success a.close');
}, function onTimeout() {
test.assert(false, 'No success notification');
});
casper.waitWhileSelector('.notification-success', function () {
test.assert(true, 'notification cleared.');
test.assertNotVisible('.notification-success', 'success notification should not still exist');
});
casper.thenClick('.post-settings-menu .post-setting-static-page');
casper.waitForSelector('.notification-success', function waitForSuccess() {
test.assert(true, 'got success notification');
casper.click('.notification-success a.close');
}, function onTimeout() {
test.assert(false, 'No success notification');
});
});

View file

@ -0,0 +1,376 @@
// # Settings Test
// Test the various tabs on the settings page
/*globals casper, CasperTest, url */
// These classes relate to elements which only appear when a given tab is loaded.
// These are used to check that a switch to a tab is complete, or that we are on the right tab.
var generalTabDetector = '.settings-content form#settings-general',
userTabDetector = '.settings-content form.user-profile';
CasperTest.emberBegin('Settings screen is correct', 17, function suite(test) {
casper.thenOpenAndWaitForPageLoad('settings', function testTitleAndUrl() {
test.assertTitle('Ghost Admin', 'Ghost admin has no title');
test.assertUrlMatch(/ghost\/ember\/settings\/general\/$/, 'Landed on the correct URL');
});
casper.then(function testViews() {
test.assertExists('.wrapper', 'Settings main view is present');
test.assertExists('.settings-sidebar', 'Settings sidebar view is present');
test.assertExists('.settings-menu', 'Settings menu is present');
test.assertExists('.settings-menu .general', 'General tab is present');
test.assertExists('.settings-menu .users', 'Users tab is present');
test.assertExists('.settings-menu .apps', 'Apps is present');
test.assertExists('.wrapper', 'Settings main view is present');
test.assertExists('.settings-content', 'Settings content view is present');
test.assertExists('.settings-menu .general.active', 'General tab is marked active');
test.assertExists(generalTabDetector, 'Form is present');
test.assertSelectorHasText('.settings-content.active h2.title', 'General', 'Title is general');
});
casper.then(function testSwitchingTabs() {
casper.thenClick('.settings-menu .users a');
casper.waitForSelector(userTabDetector, function then () {
// assert that the right menu item is active
test.assertExists('.settings-menu .users.active', 'User tab is active');
test.assertDoesntExist('.settings-menu .general.active', 'General tab is not active');
// Check Elements on the page are correct?
}, casper.failOnTimeout(test, 'waitForSelector `userTabDetector` timed out'));
casper.thenClick('.settings-menu .general a');
casper.waitForSelector(generalTabDetector, function then () {
// assert that the right menu item is active
test.assertExists('.settings-menu .general.active', 'General tab is active');
test.assertDoesntExist('.settings-menu .users.active', 'User tab is not active');
// Check Elements on the page are correct?
}, casper.failOnTimeout(test, 'waitForSelector `generalTabDetector` timed out'));
});
// ### Saving settings tests
// Please uncomment and fix these as the functionality is implemented
//CasperTest.emberBegin('Can save settings', 6, function suite(test) {
// casper.thenOpenAndWaitForPageLoad(url + 'ghost/ember/settings/user/', function testTitleAndUrl() {
// test.assertTitle('Ghost Admin', 'Ghost admin has no title');
// test.assertUrlMatch(/ghost\/ember\/settings\/user\/$/, 'Landed on the correct URL');
// });
//
// function handleUserRequest(requestData) {
// // make sure we only get requests from the user pane
// if (requestData.url.indexOf('settings/') !== -1) {
// test.fail('Saving the user pane triggered another settings pane to save');
// }
// }
//
// function handleSettingsRequest(requestData) {
// // make sure we only get requests from the user pane
// if (requestData.url.indexOf('users/') !== -1) {
// test.fail('Saving a settings pane triggered the user pane to save');
// }
// }
//
// casper.then(function listenForRequests() {
// casper.on('resource.requested', handleUserRequest);
// });
//
// casper.thenClick('#user .button-save');
// casper.waitFor(function successNotification() {
// 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 user pane did not result in a notification'));
//
// casper.then(function checkUserWasSaved() {
// casper.removeListener('resource.requested', handleUserRequest);
// });
//
// casper.waitForSelector('.notification-success', function onSuccess() {
// test.assert(true, 'Got success notification');
// }, casper.failOnTimeout(test, 'No success notification :('));
//
// casper.thenClick('#main-menu .settings a').then(function testOpeningSettingsTwice() {
// casper.on('resource.requested', handleSettingsRequest);
// test.assertEval(function testUserIsActive() {
// return document.querySelector('.settings-menu .general').classList.contains('active');
// }, 'general tab is marked active');
//
// });
//
// casper.thenClick('#general .button-save').waitFor(function successNotification() {
// 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'));
//
// casper.then(function checkSettingsWereSaved() {
// casper.removeListener('resource.requested', handleSettingsRequest);
// });
//
// casper.waitForSelector('.notification-success', function onSuccess() {
// 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);
// });
});
//
//CasperTest.begin('Ensure general blog title field length validation', 3, function suite(test) {
// casper.thenOpen(url + 'ghost/settings/general/', function testTitleAndUrl() {
// test.assertTitle('Ghost Admin', 'Ghost admin has no title');
// test.assertUrlMatch(/ghost\/settings\/general\/$/, 'Ghost doesn\'t require login this time');
// });
//
// casper.waitForSelector('#general', function then() {
// this.fill('form#settings-general', {
// 'general[title]': new Array(152).join('a')
// });
// }, casper.failOnTimeout(test, 'waitForSelector #general timed out'));
//
// casper.thenClick('#general .button-save');
//
// casper.waitForSelectorTextChange('.notification-error', function onSuccess() {
// test.assertSelectorHasText('.notification-error', 'too long');
// }, casper.failOnTimeout(test, 'Blog title length error did not appear'), 2000);
//});
//
//CasperTest.begin('Ensure general blog description field length validation', 3, function suite(test) {
// casper.thenOpen(url + 'ghost/settings/general/', function testTitleAndUrl() {
// test.assertTitle('Ghost Admin', 'Ghost admin has no title');
// test.assertUrlMatch(/ghost\/settings\/general\/$/, 'Ghost doesn\'t require login this time');
// });
//
// casper.waitForSelector('#general', function then() {
// this.fillSelectors('form#settings-general', {
// '#blog-description': new Array(202).join('a')
// });
// }, casper.failOnTimeout(test, 'waitForSelector #general timed out'));
//
// casper.thenClick('#general .button-save');
//
// casper.waitForSelectorTextChange('.notification-error', function onSuccess() {
// test.assertSelectorHasText('.notification-error', 'too long');
// }, casper.failOnTimeout(test, 'Blog description length error did not appear'));
//});
//
//CasperTest.begin('Ensure image upload modals display correctly', 6, function suite(test) {
// casper.thenOpen(url + 'ghost/settings/general/', function testTitleAndUrl() {
// test.assertTitle('Ghost Admin', 'Ghost admin has no title');
// test.assertUrlMatch(/ghost\/settings\/general\/$/, 'Ghost doesn\'t require login this time');
// });
//
// function assertImageUploaderModalThenClose() {
// test.assertSelectorHasText('.description', 'Add image');
// this.click('#modal-container .js-button-accept');
// casper.waitForSelector('.notification-success', function onSuccess() {
// test.assert(true, 'Got success notification');
// }, casper.failOnTimeout(test, 'No success notification'));
// }
//
// // Test Blog Logo Upload Button
// casper.waitForOpaque('#general', function then() {
// this.click('#general .js-modal-logo');
// }, casper.failOnTimeout(test, 'waitForOpaque #general timed out'));
//
// casper.waitForSelector('#modal-container .modal-content .js-drop-zone .description', assertImageUploaderModalThenClose,
// casper.failOnTimeout(test, 'No upload logo modal container appeared'));
//
// // Test Blog Cover Upload Button
// casper.waitForOpaque('#general', function then() {
// this.click('#general .js-modal-cover');
// }, casper.failOnTimeout(test, 'waitForOpaque #general timed out'));
//
// casper.waitForSelector('#modal-container .modal-content .js-drop-zone .description', assertImageUploaderModalThenClose,
// casper.failOnTimeout(test, 'No upload cover modal container appeared'));
//});
//
//CasperTest.begin('User settings screen validates email', 6, function suite(test) {
// var email, brokenEmail;
//
// casper.thenOpen(url + 'ghost/settings/user/', function testTitleAndUrl() {
// test.assertTitle('Ghost Admin', 'Ghost admin has no title');
// test.assertUrlMatch(/ghost\/settings\/user\/$/, 'Ghost doesn\'t require login this time');
// });
//
// casper.then(function setEmailToInvalid() {
// email = casper.getElementInfo('#user-email').attributes.value;
// brokenEmail = email.replace('.', '-');
//
// casper.fillSelectors('.user-profile', {
// '#user-email': brokenEmail
// }, false);
// });
//
// casper.thenClick('#user .button-save');
//
// casper.waitForResource('/users/');
//
// casper.waitForSelector('.notification-error', function onSuccess() {
// test.assert(true, 'Got error notification');
// test.assertSelectorDoesntHaveText('.notification-error', '[object Object]');
// }, casper.failOnTimeout(test, 'No error notification :('));
//
// casper.then(function resetEmailToValid() {
// casper.fillSelectors('.user-profile', {
// '#user-email': email
// }, false);
// });
//
// casper.thenClick('#user .button-save');
//
// casper.waitForResource(/users/);
//
// casper.waitForSelector('.notification-success', function onSuccess() {
// test.assert(true, 'Got success notification');
// test.assertSelectorDoesntHaveText('.notification-success', '[object Object]');
// }, casper.failOnTimeout(test, 'No success notification :('));
//});
//
//CasperTest.begin('Ensure postsPerPage number field form validation', 3, function suite(test) {
// casper.thenOpen(url + 'ghost/settings/general/', function testTitleAndUrl() {
// test.assertTitle('Ghost Admin', 'Ghost admin has no title');
// test.assertUrlMatch(/ghost\/settings\/general\/$/, 'Ghost doesn\'t require login this time');
// });
//
// casper.waitForSelector('#general', function then() {
// this.fill('form#settings-general', {
// 'general[postsPerPage]': 'notaninteger'
// });
// }, casper.failOnTimeout(test, 'waitForSelector #general timed out'));
//
// casper.thenClick('#general .button-save');
//
// casper.waitForSelectorTextChange('.notification-error', function onSuccess() {
// test.assertSelectorHasText('.notification-error', 'use a number');
// }, casper.failOnTimeout(test, 'postsPerPage error did not appear'), 2000);
//});
//
//CasperTest.begin('Ensure postsPerPage max of 1000', 3, function suite(test) {
// casper.thenOpen(url + 'ghost/settings/general/', function testTitleAndUrl() {
// test.assertTitle('Ghost Admin', 'Ghost admin has no title');
// test.assertUrlMatch(/ghost\/settings\/general\/$/, 'Ghost doesn\'t require login this time');
// });
//
// casper.waitForSelector('#general', function then() {
// this.fill('form#settings-general', {
// 'general[postsPerPage]': '1001'
// });
// }, casper.failOnTimeout(test, 'waitForSelector #general timed out'));
//
// casper.thenClick('#general .button-save');
//
// casper.waitForSelectorTextChange('.notification-error', function onSuccess() {
// test.assertSelectorHasText('.notification-error', 'use a number less than 1000');
// }, casper.failOnTimeout(test, 'postsPerPage max error did not appear', 2000));
//});
//
//CasperTest.begin('Ensure postsPerPage min of 0', 3, function suite(test) {
// casper.thenOpen(url + 'ghost/settings/general/', function testTitleAndUrl() {
// test.assertTitle('Ghost Admin', 'Ghost admin has no title');
// test.assertUrlMatch(/ghost\/settings\/general\/$/, 'Ghost doesn\'t require login this time');
// });
//
// casper.waitForSelector('#general', function then() {
// this.fill('form#settings-general', {
// 'general[postsPerPage]': '-1'
// });
// }, casper.failOnTimeout(test, 'waitForSelector #general timed out'));
//
// casper.thenClick('#general .button-save');
//
// casper.waitForSelectorTextChange('.notification-error', function onSuccess() {
// test.assertSelectorHasText('.notification-error', 'use a number greater than 0');
// }, casper.failOnTimeout(test, 'postsPerPage min error did not appear', 2000));
//});
//
//CasperTest.begin('User settings screen shows remaining characters for Bio properly', 4, function suite(test) {
//
// function getRemainingBioCharacterCount() {
// return casper.getHTML('.word-count');
// }
//
// casper.thenOpen(url + 'ghost/settings/user/', function testTitleAndUrl() {
// test.assertTitle('Ghost Admin', 'Ghost admin has no title');
// test.assertUrlMatch(/ghost\/settings\/user\/$/, 'Ghost doesn\'t require login this time');
// });
//
// casper.then(function checkCharacterCount() {
// test.assert(getRemainingBioCharacterCount() === '200', 'Bio remaining characters is 200');
// });
//
// casper.then(function setBioToValid() {
// casper.fillSelectors('.user-profile', {
// '#user-bio': 'asdf\n' // 5 characters
// }, false);
// });
//
// casper.then(function checkCharacterCount() {
// test.assert(getRemainingBioCharacterCount() === '195', 'Bio remaining characters is 195');
// });
//});
//
//CasperTest.begin('Ensure user bio field length validation', 3, function suite(test) {
// casper.thenOpen(url + 'ghost/settings/user/', function testTitleAndUrl() {
// test.assertTitle('Ghost Admin', 'Ghost admin has no title');
// test.assertUrlMatch(/ghost\/settings\/user\/$/, 'Ghost doesn\'t require login this time');
// });
//
// casper.waitForSelector('#user', function then() {
// this.fillSelectors('form.user-profile', {
// '#user-bio': new Array(202).join('a')
// });
// }, casper.failOnTimeout(test, 'waitForSelector #user timed out'));
//
// casper.thenClick('#user .button-save');
//
// 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.thenOpen(url + 'ghost/settings/user/', function testTitleAndUrl() {
// test.assertTitle('Ghost Admin', 'Ghost admin has no title');
// test.assertUrlMatch(/ghost\/settings\/user\/$/, 'Ghost doesn\'t require login this time');
// });
//
// casper.waitForSelector('#user', function then() {
// this.fillSelectors('form.user-profile', {
// '#user-website': 'notaurl'
// });
// }, casper.failOnTimeout(test, 'waitForSelector #user timed out'));
//
// casper.thenClick('#user .button-save');
//
// casper.waitForSelectorTextChange('.notification-error', function onSuccess() {
// test.assertSelectorHasText('.notification-error', 'use 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.thenOpen(url + 'ghost/settings/user/', function testTitleAndUrl() {
// test.assertTitle('Ghost Admin', 'Ghost admin has no title');
// test.assertUrlMatch(/ghost\/settings\/user\/$/, 'Ghost doesn\'t require login this time');
// });
//
// casper.waitForSelector('#user', function then() {
// this.fillSelectors('form.user-profile', {
// '#user-location': new Array(1002).join('a')
// });
// }, casper.failOnTimeout(test, 'waitForSelector #user timed out'));
//
// casper.thenClick('#user .button-save');
//
// 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

@ -0,0 +1,176 @@
// # Signin Test
// Test that signin works, including testing our spam prevention mechanisms
/*globals casper, __utils__, url, newUser, user, falseUser */
//CasperTest.emberBegin('Ensure Session is Killed', 1, function suite(test) {
// casper.thenOpenAndWaitForPageLoad('signout', function ensureSignedOut() {
// test.assertUrlMatch(/ghost\/ember\/sign/, 'We got redirected to signin or signup page');
// });
//}, true);
CasperTest.emberBegin('Ensure a User is Registered', 3, function suite(test) {
casper.thenOpenAndWaitForPageLoad('signup', function checkUrl() {
test.assertUrlMatch(/ghost\/ember\/signup\/$/, 'Landed on the correct URL');
});
casper.waitForOpaque(".signup-box",
function then() {
this.fillAndSave("#signup", newUser);
},
function onTimeout() {
test.fail('Sign up form didn\'t fade in.');
});
casper.captureScreenshot('login_register_test.png');
casper.waitForSelectorTextChange('.notification-error', function onSuccess() {
test.assertSelectorHasText('.notification-error', 'already registered');
// If the previous assert succeeds, then we should skip the next check and just pass.
casper.echoConcise('Already registered!');
casper.captureScreenshot('already_registered.png');
}, function onTimeout() {
test.assertUrlMatch(/ghost\/ember\/\d+\/$/, 'If we\'re not already registered, we should be logged in.');
casper.echoConcise('Successfully registered.');
}, 2000);
casper.thenOpenAndWaitForPageLoad('signout', function then() {
test.assertUrlMatch(/ghost\/ember\/signin/, 'We got redirected to signin page.');
});
}, true);
CasperTest.emberBegin("Ghost admin will load login page", 3, function suite(test) {
casper.thenOpenAndWaitForPageLoad('signin', function testTitleAndUrl() {
test.assertTitle("Ghost Admin", "Ghost admin has no title");
test.assertUrlMatch(/ghost\/ember\/signin\/$/, 'We should be presented with the signin page.');
casper.then(function testLink() {
var link = this.evaluate(function (selector) {
return document.querySelector(selector).getAttribute('href');
}, '.forgotten-password');
casper.echoConcise('LINK' + link);
test.assert(link === '/ghost/ember/forgotten/', 'Has correct forgotten password link');
});
});
}, true);
// Note, this test applies to a global redirect, which sends us to the standard admin.
// Once Ember becomes the standard admin, this test should still pass.
CasperTest.emberBegin('Redirects login to signin', 2, function suite(test) {
casper.start(url + 'ghost/login/', function testRedirect(response) {
test.assertEqual(response.status, 200, 'Response status should be 200.');
test.assertUrlMatch(/ghost\/signin\//, 'Should be redirected to /signin/.');
});
}, true);
CasperTest.emberBegin("Can't spam it", 4, function suite(test) {
casper.thenOpenAndWaitForPageLoad('signin', function testTitle() {
test.assertTitle("Ghost Admin", "Ghost admin has no title");
test.assertUrlMatch(/ghost\/ember\/signin\/$/, 'Landed on the correct URL');
});
casper.waitForOpaque(".login-box",
function then() {
this.fillAndSave("#login", falseUser);
},
function onTimeout() {
test.fail('Sign in form didn\'t fade in.');
});
casper.captureScreenshot('login_spam_test.png');
casper.wait(200, function doneWait() {
this.fillAndSave("#login", falseUser);
});
casper.captureScreenshot('login_spam_test2.png');
casper.waitForText('Slow down, there are way too many login attempts!', function onSuccess() {
test.assert(true, 'Spamming the login did result in an error notification');
test.assertSelectorDoesntHaveText('.notification-error', '[object Object]');
}, function onTimeout() {
test.assert(false, 'Spamming the login did not result in an error notification');
});
// This test causes the spam notification
// add a wait to ensure future tests don't get tripped up by this.
casper.wait(2000);
}, true);
CasperTest.emberBegin("Login limit is in place", 4, function suite(test) {
casper.thenOpenAndWaitForPageLoad('signin', function testTitleAndUrl() {
test.assertTitle("Ghost Admin", "Ghost admin has no title");
test.assertUrlMatch(/ghost\/ember\/signin\/$/, 'Landed on the correct URL');
});
casper.waitForOpaque(".login-box",
function then() {
this.fillAndSave("#login", falseUser);
},
function onTimeout() {
test.fail('Sign in form didn\'t fade in.');
});
casper.wait(2100, function doneWait() {
this.fillAndSave("#login", falseUser);
});
casper.waitForText('remaining', function onSuccess() {
test.assert(true, 'The login limit is in place.');
test.assertSelectorDoesntHaveText('.notification-error', '[object Object]');
}, function onTimeout() {
test.assert(false, 'We did not trip the login limit.');
});
// This test used login, add a wait to
// ensure future tests don't get tripped up by this.
casper.wait(2000);
}, true);
CasperTest.emberBegin("Can login to Ghost", 5, function suite(test) {
casper.thenOpenAndWaitForPageLoad('signin', function testTitleAndUrl() {
test.assertTitle("Ghost Admin", "Ghost admin has no title");
test.assertUrlMatch(/ghost\/ember\/signin\/$/, 'Landed on the correct URL');
});
casper.waitForOpaque(".login-box", function then() {
this.fillAndSave("#login", user);
});
casper.wait(2000);
casper.waitForResource(/posts/, function testForDashboard() {
test.assertUrlMatch(/ghost\/ember\/\d+\/$/, 'Landed on the correct URL');
test.assertExists("#global-header", "Global admin header is present");
test.assertExists(".manage", "We're now on content");
}, function onTimeOut() {
test.fail('Failed to signin');
});
}, true);
// Uncomment when signin / email validation has been readded to the frontend
//CasperTest.emberBegin('Ensure email field form validation', 3, function suite(test) {
// casper.thenOpenAndWaitForPageLoad('signin', function testTitleAndUrl() {
// test.assertTitle("Ghost Admin", "Ghost admin has no title");
// test.assertUrlMatch(/ghost\/ember\/signin\/$/, 'Landed on the correct URL');
// });
//
// casper.waitForOpaque(".js-login-box",
// function then() {
// this.fillAndSave("form.login-form", {
// 'email': 'notanemail'
// });
// },
// function onTimeout() {
// test.fail('Login form didn\'t fade in.');
// });
//
// casper.waitForSelectorTextChange('.notification-error', function onSuccess() {
// test.assertSelectorHasText('.notification-error', 'Invalid Email');
// }, function onTimeout() {
// test.fail('Email validation error did not appear');
// }, 2000);
//
//}, true);

View file

@ -0,0 +1,39 @@
// # Signout Test
// Test that signout works correctly
/*globals casper, __utils__, url, testPost, falseUser, email */
CasperTest.emberBegin("Ghost signout works correctly", 4, function suite(test) {
CasperTest.Routines.register.run(test);
CasperTest.Routines.logout.run(test);
CasperTest.Routines.login.run(test);
casper.thenOpenAndWaitForPageLoad('root', function then() {
test.assertTitle("Ghost Admin", "Ghost admin has no title");
test.assertUrlMatch(/ghost\/ember\/\d+\/$/, 'Landed on the correct URL without signing in');
});
casper.thenClick('#usermenu a').waitFor(function checkOpaque() {
return this.evaluate(function () {
var menu = document.querySelector('#usermenu .overlay.open');
return window.getComputedStyle(menu).getPropertyValue('display') === "block"
&& window.getComputedStyle(menu).getPropertyValue('opacity') === "1";
});
});
casper.captureScreenshot('user-menu-open.png');
casper.waitForSelector('.usermenu-signout a');
casper.thenClick('.usermenu-signout a');
casper.waitForSelector('#login').then(function assertSuccess() {
test.assert(true, 'Got login screen');
});
casper.captureScreenshot('user-menu-logout-clicked.png');
casper.waitForSelector('.notification-success', function onSuccess() {
test.assert(true, 'Got success notification');
}, function onTimeout() {
test.assert(false, 'No success notification :(');
});
}, true);

View file

@ -0,0 +1,32 @@
// # Signup Test
// Test that signup works correctly
CasperTest.emberBegin("Ghost signup fails properly", 5, function suite(test) {
casper.thenOpenAndWaitForPageLoad('signup', function then() {
test.assertUrlMatch(/ghost\/ember\/signup\/$/, 'Landed on the correct URL');
});
casper.then(function signupWithShortPassword() {
casper.fillAndSave("#signup", {email: email, password: 'test'});
});
// should now throw a short password error
casper.waitForSelector('.notification-error', function onSuccess() {
test.assert(true, 'Got error notification');
test.assertSelectorDoesntHaveText('.notification-error', '[object Object]');
}, function onTimeout() {
test.assert(false, 'No error notification :(');
});
casper.then(function signupWithLongPassword() {
casper.fillAndSave("#signup", {email: email, password: 'testing1234'});
});
// should now throw a 1 user only error
casper.waitForSelector('.notification-error', function onSuccess() {
test.assert(true, 'Got error notification');
test.assertSelectorDoesntHaveText('.notification-error', '[object Object]');
}, function onTimeout() {
test.assert(false, 'No error notification :(');
});
}, true);