From 6b74e1a34aa31c407189a07b14d44e950d0093d3 Mon Sep 17 00:00:00 2001 From: Hannah Wolfe Date: Tue, 29 Mar 2016 20:14:11 +0100 Subject: [PATCH] Dev tooling clean up - remove old casper.js tests - cleanup mochacli groups that are less useful than `grunt test:path` - improve inline Gruntfile.js docs - fixup coverage for new internal apps - add new coverage-all task which works for all our tests - reverse order of master-warn messages to make this clearer - remove bluebird from greenkeeper ignores --- Gruntfile.js | 199 ++--- core/test/functional/base.js | 541 -------------- core/test/functional/client/about_test.js | 38 - core/test/functional/client/app_test.js | 230 ------ core/test/functional/client/content_test.js | 94 --- core/test/functional/client/editor_test.js | 734 ------------------- core/test/functional/client/psm_test.js | 259 ------- core/test/functional/client/settings_test.js | 134 ---- core/test/functional/client/signin_test.js | 246 ------- core/test/functional/client/signout_test.js | 32 - core/test/functional/client/signup_test.js | 36 - core/test/functional/client/tags_test.js | 126 ---- core/test/functional/client/team_test.js | 316 -------- core/test/functional/setup/setup_test.js | 97 --- package.json | 1 - 15 files changed, 42 insertions(+), 3041 deletions(-) delete mode 100644 core/test/functional/base.js delete mode 100644 core/test/functional/client/about_test.js delete mode 100644 core/test/functional/client/app_test.js delete mode 100644 core/test/functional/client/content_test.js delete mode 100644 core/test/functional/client/editor_test.js delete mode 100644 core/test/functional/client/psm_test.js delete mode 100644 core/test/functional/client/settings_test.js delete mode 100644 core/test/functional/client/signin_test.js delete mode 100644 core/test/functional/client/signout_test.js delete mode 100644 core/test/functional/client/signup_test.js delete mode 100644 core/test/functional/client/tags_test.js delete mode 100644 core/test/functional/client/team_test.js delete mode 100644 core/test/functional/setup/setup_test.js diff --git a/Gruntfile.js b/Gruntfile.js index 8227ebbd23..5cb4cce5ab 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -188,61 +188,14 @@ var _ = require('lodash'), ] }, - // ##### Groups of unit tests - server: { - src: ['core/test/unit/**/server*_spec.js'] - }, - - helpers: { - src: ['core/test/unit/server_helpers/*_spec.js'] - }, - - metadata: { - src: ['core/test/unit/metadata/*_spec.js'] - }, - - middleware: { - src: ['core/test/unit/middleware/*_spec.js'] - }, - - showdown: { - src: ['core/test/unit/**/showdown*_spec.js'] - }, - - perm: { - src: ['core/test/unit/**/permissions_spec.js'] - }, - - migrate: { - src: [ - 'core/test/unit/**/export_spec.js', - 'core/test/unit/**/import_spec.js' - ] - }, - - storage: { - src: ['core/test/unit/**/storage*_spec.js'] - }, - // #### All Integration tests integration: { src: [ - 'core/test/integration/**/*_spec.js', 'core/test/integration/**/*_spec.js', 'core/test/integration/*_spec.js' ] }, - // ##### Model integration tests - model: { - src: ['core/test/integration/**/model*_spec.js'] - }, - - // ##### API integration tests - api: { - src: ['core/test/integration/**/api*_spec.js'] - }, - // #### All Route tests routes: { src: [ @@ -263,23 +216,30 @@ var _ = require('lodash'), // `grunt coverage`. mocha_istanbul: { coverage: { - // TODO fix the timing/async & cleanup issues with the route and integration tests so that // they can also have coverage generated for them & the order doesn't matter - src: ['core/test/unit'], + src: [ + 'core/test/unit', + 'core/server/apps' + ], options: { mask: '**/*_spec.js', coverageFolder: 'core/test/coverage/unit', mochaOptions: ['--timeout=15000'], - excludes: ['core/client/**'] + excludes: ['core/client/**', 'core/server/built'] } }, - coverage_integration: { - src: ['core/test/integration/api'], + coverage_all: { + src: [ + 'core/test/unit', + 'core/server/apps', + 'core/test/integration', + 'core/test/functional' + ], options: { - coverageFolder: 'core/test/coverage/integration', + coverageFolder: 'core/test/coverage/all', mask: '**/*_spec.js', mochaOptions: ['--timeout=15000'], - excludes: ['core/client/**', 'core/server/built', 'core/server/apps', 'core/server/config', 'core/server/data'] + excludes: ['core/client/**', 'core/server/built'] } } @@ -440,55 +400,6 @@ var _ = require('lodash'), // Load the configuration grunt.initConfig(cfg); - // ## Utilities - // - // ### 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 (target) { - target = _.contains(['client', 'setup'], target) ? target + '/' : undefined; - - var done = this.async(), - options = ['host', 'noPort', 'port', 'email', 'password'], - args = ['test'] - .concat(grunt.option('target') || target || ['client/']) - .concat(['--includes=base.js', '--log-level=debug', '--port=2369']); - - // Forward parameters from grunt to casperjs - _.each(options, function processOption(option) { - if (grunt.option(option)) { - args.push('--' + option + '=' + grunt.option(option)); - } - }); - - if (grunt.option('fail-fast')) { - args.push('--fail-fast'); - } - - // Show concise logs in Travis as ours are getting too long - if (grunt.option('concise') || process.env.TRAVIS) { - args.push('--concise'); - } else { - args.push('--verbose'); - } - - grunt.util.spawn({ - cmd: 'casperjs', - args: args, - opts: { - cwd: path.resolve('core/test/functional'), - stdio: 'inherit' - } - }, function (error, result, code) { - /*jshint unused:false*/ - if (error) { - grunt.fail.fatal(result.stderr); - } - grunt.log.writeln(result.stdout); - done(); - }); - }); - // # Custom Tasks // Ghost has a number of useful tasks that we use every day in development. Tasks marked as *Utility* are used @@ -507,8 +418,7 @@ var _ = require('lodash'), grunt.registerTask('help', 'Outputs help information if you type `grunt help` instead of `grunt --help`', function () { - console.log('Type `grunt --help` to get the details of available grunt tasks, ' + - 'or alternatively visit https://github.com/TryGhost/Ghost/wiki/Grunt-Toolkit'); + console.log('Type `grunt --help` to get the details of available grunt tasks.'); }); // ### Documentation @@ -587,7 +497,16 @@ var _ = require('lodash'), }); }); - grunt.registerTask('test', function (test) { + // ### Test + // **Testing utility** + // + // `grunt test:unit/apps_spec.js` will run just the tests inside the apps_spec.js file + // + // It works for any path relative to the core/test folder. It will also run all the tests in a single directory + // + // `grunt test:integration/api` - runs the api integration tests + // `grunt test:integration` - runs the integration tests in the root folder and excludes all api & model tests + grunt.registerTask('test', 'Run a particular spec file from the core/test directory e.g. `grunt test:unit/apps_spec.js`', function (test) { if (!test) { grunt.fail.fatal('No test provided. `grunt test` expects a filename. e.g.: `grunt test:unit/apps_spec.js`. Did you mean `npm test` or `grunt validate`?'); } @@ -652,15 +571,13 @@ var _ = require('lodash'), // ### Unit Tests *(sub task)* // `grunt test-unit` will run just the unit tests // - // Provided you already have a `config.js` file, you can run individual sections from - // [mochacli](#grunt-mocha-cli) by running: + // If you need to run an individual unit test file, you can use the `grunt test:` task: // - // `NODE_ENV=testing grunt mochacli:section` + // `grunt test:unit/config_spec.js` // - // 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: + // This also works for folders (although it isn't recursive), E.g. // - // `NODE_ENV=testing mocha --timeout=15000 --ui=bdd --reporter=spec core/test/unit/config_spec.js` + // `grunt test:unit/server_helpers` // // Unit tests are run with [mocha](http://mochajs.org/) using // [should](https://github.com/visionmedia/should.js) to describe the tests in a highly readable style. @@ -675,21 +592,19 @@ var _ = require('lodash'), // // Provided you already have a `config.js` file, you can run just the model integration tests by running: // - // `NODE_ENV=testing grunt mochacli:model` + // `grunt test:integration/model` // // Or just the api integration tests by running: // - // `NODE_ENV=testing grunt mochacli:api` + // `grunt test:integration/api` // // Integration tests are run with [mocha](http://mochajs.org/) using // [should](https://github.com/visionmedia/should.js) to describe the tests in a highly readable style. // Integration tests are different to the unit tests because they make requests to the database. // - // If you need to run an individual integration test file you can do so, providing you have mocha installed - // globally, by using a command in the form (replace path to api_tags_spec.js with the test file you want to - // run): + // If you need to run an individual integration test file you can use the `grunt test:` task: // - // `NODE_ENV=testing mocha --timeout=15000 --ui=bdd --reporter=spec core/test/integration/api/api_tags_spec.js` + // `grunt test:integration/api/api_tags_spec.js` // // Their purpose is to test that both the api and models behave as expected when the database layer is involved. // These tests are run against sqlite3, mysql and pg on travis and ensure that differences between the databases @@ -703,10 +618,9 @@ var _ = require('lodash'), // ### Route tests *(sub task)* // `grunt test-routes` will run just the route tests // - // If you need to run an individual route test file, you can do so, providing you have a `config.js` file and - // mocha installed globally by using a command in the form: + // If you need to run an individual route test file, you can use the `grunt test:` task: // - // `NODE_ENV=testing mocha --timeout=15000 --ui=bdd --reporter=spec core/test/functional/routes/admin_spec.js` + // `grunt test:functional/routes/admin_spec.js` // // Route tests are run with [mocha](http://mochajs.org/) using // [should](https://github.com/visionmedia/should.js) and [supertest](https://github.com/visionmedia/supertest) @@ -737,37 +651,6 @@ var _ = require('lodash'), ['test-setup', 'shell:ember:test'] ); - // ### Functional tests *(sub task)* - // `grunt test-functional` will run just the functional tests - // - // You can use the `--target` argument to run any individual test file, or the admin or frontend tests: - // - // `grunt test-functional --target=client/editor_test.js` - run just the editor tests - // - // `grunt test-functional --target=client/` - run all of the tests in the client directory - // - // Functional tests are run with [phantom.js](http://phantomjs.org/) and defined using the testing api from - // [casper.js](http://docs.casperjs.org/en/latest/testing.html). - // - // An express server is started with the testing environment set, and then a headless phantom.js browser is - // used to make requests to that server. The Casper.js API then allows us to describe the elements and - // interactions we expect to appear on the page. - // - // The purpose of the functional tests is to ensure that Ghost is working as is expected from a user perspective - // including buttons and other important interactions in the admin UI. - grunt.registerTask('test-functional', 'Run functional interface tests (CasperJS)', - ['test-setup', 'shell:ember:dev', 'cleanDatabase', 'express:test', 'spawnCasperJS', 'express:test:stop', 'test-functional-setup'] - ); - - // ### Functional tests for the setup process - // `grunt test-functional-setup will run just the functional tests for the setup page. - // - // Setup only works with a brand new database, so it needs to run isolated from the rest of - // the functional tests. - grunt.registerTask('test-functional-setup', 'Run functional tests for setup', - ['test-setup', 'cleanDatabase', 'express:test', 'spawnCasperJS:setup', 'express:test:stop'] - ); - // ### Coverage // `grunt coverage` will generate a report for the Unit Tests. // @@ -782,8 +665,8 @@ var _ = require('lodash'), ['test-setup', 'mocha_istanbul:coverage'] ); - grunt.registerTask('coverage-integration', 'Generate unit and integration tests coverage report', - ['test-setup', 'mocha_istanbul:coverage_integration'] + grunt.registerTask('coverage-all', 'Generate unit and integration tests coverage report', + ['test-setup', 'mocha_istanbul:coverage_all'] ); // #### Master Warning *(Utility Task)* @@ -794,9 +677,11 @@ var _ = require('lodash'), grunt.registerTask('master-warn', 'Outputs a warning to runners of grunt prod, that master shouldn\'t be used for live blogs', function () { - console.log('>', chalk.red('Always two there are, no more, no less. A master and a'), - chalk.bold.red('stable') + chalk.red('.')); - console.log('Use the', chalk.bold('stable'), 'branch for live blogs.', chalk.bold('Never'), 'master!'); + console.log(chalk.red( + 'Use the ' + chalk.bold('stable') + ' branch for live blogs. ' + + chalk.bold.underline('Never') + ' master!' + )); + console.log('>', 'Always two there are, no more, no less. A master and a ' + chalk.bold('stable') + '.'); }); // ### Build About Page *(Utility Task)* diff --git a/core/test/functional/base.js b/core/test/functional/base.js deleted file mode 100644 index 9f1956bb6f..0000000000 --- a/core/test/functional/base.js +++ /dev/null @@ -1,541 +0,0 @@ -/*globals casper */ - -/** - * Casper Tests - * - * Functional browser tests for checking that the Ghost Admin UI is working as expected - * The setup of these tests is a little hacky for now, which is why they are not wired in to grunt - * Requires that you are running Ghost locally and have already registered a single user - * - * Usage (from test/functional): - * - * casperjs test admin/ --includes=base.js [--host=localhost --port=2368 --noPort=false --email=ghost@tryghost.org --password=Sl1m3r] - * - * --host - your local host address e.g. localhost or local.tryghost.org - * --port - port number of your local Ghost - * --email - the email address your admin user is registered with - * --password - the password your admin user is registered with - * --noPort - don't include a port number - * - * 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, - 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 + '/'), - newUser = { - name: 'Test User', - slug: 'test', - email: email, - password: password - }, - newSetup = { - 'blog-title': 'Test Blog', - name: 'Test User', - email: email, - password: password - }, - user = { - identification: email, - password: password - }, - falseUser = { - identification: email, - password: 'letmethrough' - }, - testPost = { - title: 'Bacon ipsum dolor sit amet', - html: 'I am a test post.\n#I have some small content' - }, - screens, - CasperTest, - utils = require('utils'), - // ## Debugging - jsErrors = [], - pageErrors = [], - resourceErrors = []; - -screens = { - root: { - url: 'ghost/', - linkSelector: '.gh-nav-main-content', - selector: '.gh-nav-main-content.active' - }, - content: { - url: 'ghost/', - linkSelector: '.gh-nav-main-content', - selector: '.gh-nav-main-content.active' - }, - editor: { - url: 'ghost/editor/', - linkSelector: '.gh-nav-main-editor', - selector: '.gh-nav-main-editor.active' - }, - about: { - url: 'ghost/about', - linkSelector: '.gh-nav-menu-about', - selector: '.gh-about-header' - }, - 'editor.editing': { - url: 'ghost/editor/', - linkSelector: 'a.post-edit', - selector: '.entry-markdown-content .markdown-editor' - }, - 'settings.general': { - url: 'ghost/settings/general', - selector: '.gh-nav-settings-general.active' - }, - 'settings.tags': { - url: 'ghost/settings/tags', - selector: '.gh-nav-settings-tags.active' - }, - team: { - url: 'ghost/team', - linkSelector: '.gh-nav-main-users', - selector: '.gh-nav-main-users.active' - }, - 'team.user': { - url: 'ghost/team/test', - linkSelector: '.user-menu-profile', - selector: '.user-profile' - }, - signin: { - url: 'ghost/signin/', - selector: '.btn-blue' - }, - 'signin-authenticated': { - url: 'ghost/signin/', - // signin with authenticated user redirects to posts - selector: '.gh-nav-main-content.active' - }, - - signout: { - url: 'ghost/signout/', - linkSelector: '.user-menu-signout', - // When no user exists we get redirected to setup which has btn-green - selector: '.btn-blue, .btn-green' - }, - signup: { - url: 'ghost/signup/', - selector: '.btn-blue' - }, - setup: { - url: 'ghost/setup/one/', - selector: '.btn-green' - }, - 'setup.two': { - url: 'ghost/setup/two/', - linkSelector: '.btn-green', - selector: '.gh-flow-create' - }, - 'setup.three': { - url: 'ghost/setup/three/', - selector: '.gh-flow-invite' - }, - 'setup-authenticated': { - url: 'ghost/setup/', - selector: '.gh-nav-main-content.active' - } -}; - -casper.writeContentToEditor = function (content) { - // If we are on a new editor, the autosave is going to get triggered when we try to type, so we need to trigger - // that and wait for it to sort itself out - if (/ghost\/editor\/$/.test(casper.getCurrentUrl())) { - casper.waitForSelector('.entry-markdown-content textarea', function onSuccess() { - casper.click('.entry-markdown-content textarea'); - }, function onTimeout() { - casper.test.fail('Editor was not found on initial load.'); - }, 2000); - - casper.waitForUrl(/\/ghost\/editor\/\d+\/$/, function onSuccess() { - // do nothing - }, function onTimeout() { - casper.test.fail('The url didn\'t change: ' + casper.getCurrentUrl()); - }, 2000); - } - - casper.waitForSelector('.entry-markdown-content textarea', function onSuccess() { - casper.sendKeys('.entry-markdown-content textarea', content, {keepFocus: true}); - // Always end with a new line - casper.sendKeys('.entry-markdown-content textarea', '\n', {keepFocus: true}); - casper.captureScreenshot('EditorText.png'); - - return this; - }, function onTimeout() { - casper.test.fail('Editor was not found on main load.'); - }, 2000); -}; - -casper.waitForOpacity = function (classname, opacity, then, timeout) { - timeout = timeout || casper.failOnTimeout(casper.test, 'waitForOpacity failed on ' + classname + ' ' + opacity); - casper.waitForSelector(classname).then(function () { - casper.waitFor(function checkOpaque() { - var value = this.evaluate(function (element, opacity) { - var target = document.querySelector(element); - if (target === null) { - return null; - } - return window.getComputedStyle(target).getPropertyValue('opacity') === opacity; - }, classname, opacity); - if (value !== true && value !== false) { - casper.test.fail('Unable to find element: ' + classname); - } - return value; - }, then, timeout); - }); -}; - -casper.waitForOpaque = function (classname, then, timeout) { - casper.waitForOpacity(classname, '1', then, timeout); -}; - -casper.waitForTransparent = function (classname, then, timeout) { - casper.waitForOpacity(classname, '0', then, timeout); -}; - -// ### Then Open And Wait For Page Load -// Always wait for the `.page-content` 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); - - return casper.thenOpen(url + screens[screen].url).then(function () { - // HACK: phantomjs + flexbox = nope. Fix offending styles here. - casper.evaluate(function () { - var style = document.createElement('style'); - style.innerHTML = '.gh-main > section { width: auto; }'; - document.body.appendChild(style); - }); - return casper.waitForScreenLoad(screen, then, timeout); - }); -}; - -casper.waitForScreenLoad = function (screen, then, timeout) { - // Some screens fade in - return casper.waitForOpaque(screens[screen].selector, then, timeout, 10000); -}; - -casper.thenTransitionAndWaitForScreenLoad = function (screen, then, timeout) { - then = then || function () {}; - timeout = timeout || casper.failOnTimeout(casper.test, 'Unable to load ' + screen); - - return casper.thenClick(screens[screen].linkSelector).then(function () { - return casper.waitForScreenLoad(screen, then, timeout); - }); -}; - -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 button which always has a class of -// 'btn-blue'. This method handles that smoothly. -casper.fillAndSave = function (selector, data) { - casper.then(function doFill() { - casper.fill(selector, data, false); - casper.thenClick('.btn-blue'); - }); -}; - -// ### Fill And Add -// With Ember in place, we don't want to submit forms, rather press the green button which always has a class of -// 'btn-green'. This method handles that smoothly. -casper.fillAndAdd = function (selector, data) { - casper.then(function doFill() { - casper.fill(selector, data, false); - casper.thenClick('.btn-green'); - }); -}; - -// ## 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); - } -}; - -// ### Wait for Selector Text -// Does casper.waitForSelector but checks for the presence of specified text -// http://stackoverflow.com/questions/32104784/wait-for-an-element-to-have-a-specific-text-with-casperjs -casper.waitForSelectorText = function (selector, text, then, onTimeout, timeout) { - this.waitForSelector(selector, function _then() { - this.waitFor(function _check() { - var content = this.fetchText(selector); - if (utils.isRegExp(text)) { - return text.test(content); - } - return content.indexOf(text) !== -1; - }, then, onTimeout, timeout); - }, onTimeout, timeout); - return this; -}; - -// pass through all console.logs -casper.on('remote.message', function (msg) { - casper.echoConcise('CONSOLE LOG: ' + msg, 'INFO'); -}); - -// output any errors -casper.on('error', function (msg, trace) { - casper.echoConcise('ERROR, ' + msg, 'ERROR'); - if (trace && trace[0]) { - casper.echoConcise('file: ' + trace[0].file, 'WARNING'); - casper.echoConcise('line: ' + trace[0].line, 'WARNING'); - casper.echoConcise('function: ' + trace[0].function, 'WARNING'); - } - jsErrors.push(msg); -}); - -// output any page errors -casper.on('page.error', function (msg, trace) { - casper.echoConcise('PAGE ERROR: ' + msg, 'ERROR'); - if (trace && trace[0]) { - casper.echoConcise('file: ' + trace[0].file, 'WARNING'); - casper.echoConcise('line: ' + trace[0].line, 'WARNING'); - casper.echoConcise('function: ' + trace[0].function, 'WARNING'); - } - pageErrors.push(msg); -}); - -casper.on('resource.received', function (resource) { - var status = resource.status; - if (status >= 400) { - casper.echoConcise('RESOURCE ERROR: ' + resource.url + ' failed to load (' + status + ')', 'ERROR'); - - resourceErrors.push({ - url: resource.url, - status: resource.status - }); - } -}); - -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'; - casper.then(function () { - casper.capture(new Date().getTime() + '_' + filename); - }); - } -}; - -// on failure, grab a screenshot -casper.test.on('fail', function captureFailure() { - casper.captureScreenshot(casper.test.filename || 'casper_test_fail.png', false); - casper.then(function () { - console.log(casper.getHTML()); - casper.exit(1); - }); -}); - -// on exit, output any errors -casper.test.on('exit', function () { - if (jsErrors.length > 0) { - casper.echo(jsErrors.length + ' Javascript errors found', 'WARNING'); - } else { - casper.echo(jsErrors.length + ' Javascript errors found', 'INFO'); - } - if (pageErrors.length > 0) { - casper.echo(pageErrors.length + ' Page errors found', 'WARNING'); - } else { - casper.echo(pageErrors.length + ' Page errors found', 'INFO'); - } - - if (resourceErrors.length > 0) { - casper.echo(resourceErrors.length + ' Resource errors found', 'WARNING'); - } else { - casper.echo(resourceErrors.length + ' Resource errors found', 'INFO'); - } -}); - -CasperTest = (function () { - var _beforeDoneHandler, - _noop = function noop() { }, - _isUserRegistered = false; - - // Always log out at end of test. - casper.test.tearDown(function (done) { - casper.then(_beforeDoneHandler); - - CasperTest.Routines.signout.run(); - - casper.run(done); - }); - - // Wrapper around `casper.test.begin` - function begin(testName, expect, suite, doNotAutoLogin, doNotRunSetup) { - _beforeDoneHandler = _noop; - - var runTest = function (test) { - test.filename = testName.toLowerCase().replace(/ /g, '-').concat('.png'); - - casper.start('about:blank').viewport(1280, 1024); - // Only call register once for the lifetime of CasperTest - if (!_isUserRegistered && !doNotRunSetup) { - CasperTest.Routines.signout.run(); - CasperTest.Routines.setup.run(); - CasperTest.Routines.signout.run(); - - _isUserRegistered = true; - } - - if (!doNotAutoLogin) { - /* Ensure we're logged out at the start of every test or we may get - unexpected failures. */ - CasperTest.Routines.signout.run(); - CasperTest.Routines.signin.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) { - _beforeDoneHandler = fn; - } else { - _beforeDoneHandler = _noop; - } - } - - return { - begin: begin, - beforeDone: beforeDone - }; -}()); - -CasperTest.Routines = (function () { - function setup() { - casper.thenOpenAndWaitForPageLoad('setup.two', function then() { - casper.captureScreenshot('setting_up1.png'); - - casper.fillAndAdd('#setup', newSetup); - - casper.captureScreenshot('setting_up2.png'); - - casper.waitForSelectorTextChange('.gh-alert-success', function onSuccess() { - var errorText = casper.evaluate(function () { - return document.querySelector('.gh-alert').innerText; - }); - casper.echoConcise('Setup failed. Error text: ' + errorText); - }, function onTimeout() { - casper.echoConcise('Setup completed.'); - }, 2000); - - casper.captureScreenshot('setting_up3.png'); - }); - } - - function signin() { - casper.thenOpenAndWaitForPageLoad('signin', function then() { - casper.waitForOpaque('.gh-signin', function then() { - casper.captureScreenshot('signing_in.png'); - this.fillAndSave('#login', user); - casper.captureScreenshot('signing_in2.png'); - }); - - casper.waitForResource(/posts\/\?(?=.*status=all)(?=.*staticPages=all)/, function then() { - casper.captureScreenshot('signing_in.png'); - }, function timeout() { - casper.test.fail('Unable to signin and load admin panel'); - }); - }); - } - - function signout() { - 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.thenOpenAndWaitForPageLoad('settings.general', function then() { - var currentState = this.evaluate(function () { - return document.querySelector('#permalinks') && document.querySelector('#permalinks').checked ? 'on' : 'off'; - }); - if (currentState !== state) { - casper.thenClick('#permalinks'); - casper.thenClick('.btn-blue'); - - casper.captureScreenshot('saving.png'); - - casper.waitForSelector('.notification-success', function () { - casper.captureScreenshot('saved.png'); - }); - } - }); - } - - function createTestPost(publish) { - casper.thenOpenAndWaitForPageLoad('editor', function createTestPost() { - casper.sendKeys('#entry-title', testPost.title); - casper.writeContentToEditor(testPost.html); - }); - - casper.waitForSelectorTextChange('.entry-preview .rendered-markdown'); - - if (publish) { - // Open the publish options menu; - casper.thenClick('.js-publish-splitbutton .dropdown-toggle'); - - casper.waitForOpaque('.js-publish-splitbutton .open'); - - // Select the publish post button - casper.thenClick('.post-save-publish a'); - - casper.waitForSelectorTextChange('.js-publish-button', function onSuccess() { - casper.thenClick('.js-publish-button'); - }); - } else { - casper.thenClick('.js-publish-button'); - } - - casper.waitForResource(/posts\/\?include=tags$/); - } - - function _createRunner(fn) { - fn.run = function run(test) { - var self = this; - - casper.then(function () { - self.call(casper, test); - }); - }; - - return fn; - } - - return { - setup: _createRunner(setup), - signin: _createRunner(signin), - signout: _createRunner(signout), - createTestPost: _createRunner(createTestPost), - togglePermalinks: _createRunner(togglePermalinks) - }; -}()); diff --git a/core/test/functional/client/about_test.js b/core/test/functional/client/about_test.js deleted file mode 100644 index a7e02b4ad3..0000000000 --- a/core/test/functional/client/about_test.js +++ /dev/null @@ -1,38 +0,0 @@ -// # About Test -// Test the various parts of the About page - -/*globals CasperTest, casper */ - -CasperTest.begin('About screen is correct', 9, function suite(test) { - casper.thenOpenAndWaitForPageLoad('about', function testTitleAndUrl() { - test.assertTitle('About - Test Blog', 'Ghost admin has incorrect title'); - test.assertUrlMatch(/ghost\/about\/$/, 'Redirected to the correct URL'); - }); - - casper.then(function testVersionNumber() { - var versionNumber = casper.getHTML('.gh-env-list-version'); - test.assertMatch(versionNumber, /\d+\.\d+\.\d+/, 'Version is a number'); // Tests for a pattern like 0.0.0 to v11111.3334534.2342453-beta - }); - - casper.then(function testDatabaseType() { - var databaseTypeText = casper.getHTML('.gh-env-list-database-type'); - test.assertMatch(databaseTypeText, /sqlite3|mysql|pg/gi, 'Database is an allowed type'); - }); - - casper.waitForSelector('.gh-contributors article', function testContributors() { - var firstContribImageSrc = casper.getElementAttribute('.gh-contributors article:nth-child(1) a img', 'src'); - - // Check first contributor image tag is on the page - test.assertExist('.gh-contributors article:nth-child(1) img', 'First contributor image is in place'); - - // Check first contributor image resource exists & alt tag isnt empty - test.assertResourceExists(firstContribImageSrc, 'First contributor image file exists'); - test.assertDoesntExist('.gh-contributors article:nth-child(1) a img[alt=""]', 'First contributor image alt is not empty'); - - // Check first contributor links to GitHub - test.assertExists('.gh-contributors article:nth-child(1) a[href*="github.com"]', 'First contributor link to GitHub'); - - // Check first contributor links to GitHub - test.assertDoesntExist('.gh-contributors article:nth-child(1) a[title=""]', 'First contributor title is not empty'); - }); -}); diff --git a/core/test/functional/client/app_test.js b/core/test/functional/client/app_test.js deleted file mode 100644 index 9a4d1d9ce5..0000000000 --- a/core/test/functional/client/app_test.js +++ /dev/null @@ -1,230 +0,0 @@ -// # App Test -// Tests that the general layout & functionality of global admin components is correct - -/*globals CasperTest, casper, newUser */ - -CasperTest.begin('Admin navigation bar is correct', 65, function suite(test) { - casper.thenOpenAndWaitForPageLoad('root', function testTitleAndUrl() { - test.assertTitle('Content - Test Blog', 'Ghost admin has incorrect title'); - test.assertUrlMatch(/ghost\/\d+\/$/, 'Landed on the correct URL'); - }); - - casper.then(function testNavItems() { - var logoHref = this.getElementAttribute('.gh-nav-footer-sitelink', 'href'), - contentHref = this.getElementAttribute('.gh-nav-main-content', 'href'), - editorHref = this.getElementAttribute('.gh-nav-main-editor', 'href'), - usersHref = this.getElementAttribute('.gh-nav-main-users', 'href'), - settingsGeneralHref = this.getElementAttribute('.gh-nav-settings-general', 'href'), - settingsNavigationHref = this.getElementAttribute('.gh-nav-settings-navigation', 'href'), - settingsTagsHref = this.getElementAttribute('.gh-nav-settings-tags', 'href'), - settingsCodeInjectionHref = this.getElementAttribute('.gh-nav-settings-code-injection', 'href'), - settingsLabsHref = this.getElementAttribute('.gh-nav-settings-labs', 'href'); - - // Logo - test.assertExists('.gh-nav-footer-sitelink', 'Ghost home page link exists in nav footer'); - test.assertEquals(logoHref, 'http://127.0.0.1:2369/', 'Ghost logo link href is correct'); - - // Content - test.assertExists('.gh-nav-main-content', 'Content nav item exists'); - test.assertSelectorHasText('.gh-nav-main-content', 'Content', 'Content nav item has correct text'); - test.assertEquals(contentHref, '/ghost/', 'Content href is correct'); - test.assertExists('.gh-nav-main-content.active', 'Content nav item is not marked active'); - - // Editor - test.assertExists('.gh-nav-main-editor', 'Editor nav item exists'); - test.assertSelectorHasText('.gh-nav-main-editor', 'New Post', 'Editor nav item has correct text'); - test.assertEquals(editorHref, '/ghost/editor/', 'Editor href is correct'); - test.assertDoesntExist('.gh-nav-main-editor.active', 'Editor nav item is not marked active'); - - // Users - test.assertExists('.gh-nav-main-users', 'Users nav item exists'); - test.assertSelectorHasText('.gh-nav-main-users', 'Team', 'Users nav item has correct text'); - test.assertEquals(usersHref, '/ghost/team/', 'Users href is correct'); - test.assertDoesntExist('.gh-nav-main-users.active', 'Users nav item is not marked active'); - - // Settings - General - test.assertExists('.gh-nav-settings-general', 'Settings - General nav exists'); - test.assertSelectorHasText('.gh-nav-settings-general', 'General', 'Settings nav item has correct text'); - test.assertEquals(settingsGeneralHref, '/ghost/settings/general/', 'Settings href is correct'); - test.assertDoesntExist('.gh-nav-settings-general.active', 'Settings nav item is marked active'); - - // Settings - Navigation - test.assertExists('.gh-nav-settings-navigation', 'Settings - Navigation nav item exists'); - test.assertSelectorHasText('.gh-nav-settings-navigation', 'Navigation', 'Settings nav item has correct text'); - test.assertEquals(settingsNavigationHref, '/ghost/settings/navigation/', 'Settings Navigation href is correct'); - test.assertDoesntExist('.gh-nav-settings-navigation.active', 'Settings - Navigation nav item is marked active'); - - // Settings - Tags - test.assertExists('.gh-nav-settings-tags', 'Settings - Tags nav item exists'); - test.assertSelectorHasText('.gh-nav-settings-tags', 'Tags', 'Settings nav item has correct text'); - test.assertEquals(settingsTagsHref, '/ghost/settings/tags/', 'Settings Navigation href is correct'); - test.assertDoesntExist('.gh-nav-settings-tags.active', 'Settings - Navigation nav item is marked active'); - - // Settings - Code Injection - test.assertExists('.gh-nav-settings-code-injection', 'Settings - Code Injection nav item exists'); - test.assertSelectorHasText('.gh-nav-settings-code-injection', 'Code Injection', 'Settings nav item has correct text'); - test.assertEquals(settingsCodeInjectionHref, '/ghost/settings/code-injection/', 'Settings Navigation href is correct'); - test.assertDoesntExist('.gh-nav-settings-code-injection.active', 'Settings - Code Injection nav item is marked active'); - - // Settings - Labs - test.assertExists('.gh-nav-settings-labs', 'Settings - Labs nav item exists'); - test.assertSelectorHasText('.gh-nav-settings-labs', 'Labs', 'Settings nav item has correct text'); - test.assertEquals(settingsLabsHref, '/ghost/settings/labs/', 'Settings Labs href is correct'); - test.assertDoesntExist('.gh-nav-settings-labs.active', 'Settings - Labs nav item is marked active'); - }); - - casper.then(function testHelpMenuNotVisible() { - test.assertExists('.gh-help-button', 'Help menu nav item exists'); - test.assertNotExists('.gh-help-button .dropdown.open', 'Help menu should not be visible'); - }); - - casper.thenClick('.gh-help-button'); - casper.waitForSelector('.dropdown', function then() { - var supportHref = this.getElementAttribute('.help-menu-support', 'href'), - tweetHref = this.getElementAttribute('.help-menu-tweet', 'href'), - howtoHref = this.getElementAttribute('.help-menu-how-to', 'href'), - wishlistHref = this.getElementAttribute('.help-menu-wishlist', 'href'); - - test.assertVisible('.dropdown-menu', 'Help menu should be visible'); - - test.assertExists('.help-menu-support', 'Support menu item exists'); - test.assertSelectorHasText('.help-menu-support', 'Support Center', 'Support menu item has correct text'); - test.assertEquals(supportHref, 'http://support.ghost.org/', 'Support href is correct'); - - test.assertExists('.help-menu-tweet', 'Tweet menu item exists'); - test.assertSelectorHasText('.help-menu-tweet', 'Tweet @TryGhost!', 'Tweet menu item has correct text'); - test.assertEquals(tweetHref, 'https://twitter.com/intent/tweet?text=%40TryGhost+Hi%21+Can+you+help+me+with+&related=TryGhost', 'Tweet href is correct'); - - test.assertExists('.help-menu-how-to', 'How-to menu item exists'); - test.assertSelectorHasText('.help-menu-how-to', 'How to Use Ghost', 'How-to menu item has correct text'); - test.assertEquals(howtoHref, 'http://support.ghost.org/how-to-use-ghost/', 'How-to href is correct'); - - test.assertExists('.help-menu-wishlist', 'Wishlist menu item exists'); - test.assertSelectorHasText('.help-menu-wishlist', 'Wishlist', 'Wishlist menu item has correct text'); - test.assertEquals(wishlistHref, 'http://ideas.ghost.org/', 'Wishlist href is correct'); - - test.assertExists('.help-menu-markdown', 'Markdown menu item exists'); - test.assertSelectorHasText('.help-menu-markdown', 'Markdown Help', 'Markdown menu item has correct text'); - - casper.thenClick('.help-menu-markdown'); - - casper.waitUntilVisible('.modal-container', function onSuccess() { - test.assertSelectorHasText( - '.modal-content .modal-header', - 'Markdown Help', - 'delete modal has correct text'); - - test.assertExists('.modal-content .close', '.modal-content .close exists'); - }); - - casper.thenClick('.modal-content .close'); - - casper.waitWhileVisible('.modal-container', function onSuccess() { - test.assert(true, 'clicking close should remove the markdown help modal'); - }); - }, casper.failOnTimeout(test, 'WaitForSelector .gh-help-menu .ember-view.open failed')); - - casper.then(function testUserMenuNotVisible() { - test.assertExists('.gh-nav-menu .gh-nav-menu-details-user', 'User menu nav item exists'); - test.assertNotExists('.gh-nav-menu-details-user .user-menu-profile', 'User menu should not be visible'); - }); - - casper.thenClick('.gh-nav-menu'); - casper.waitForSelector('.dropdown', function then() { - var profileHref = this.getElementAttribute('.user-menu-profile', 'href'), - signoutHref = this.getElementAttribute('.user-menu-signout', 'href'); - - test.assertVisible('.dropdown-item.user-menu-profile', 'User menu should be visible'); - - test.assertExists('.dropdown-item.user-menu-profile', 'Profile menu item exists'); - test.assertSelectorHasText('.dropdown-item.user-menu-profile', 'Your Profile', - 'Profile menu item has correct text'); - test.assertEquals(profileHref, '/ghost/team/' + newUser.slug + '/', 'Profile href is correct'); - - test.assertExists('.user-menu-signout', 'Sign Out menu item exists'); - test.assertSelectorHasText('.user-menu-signout', 'Sign Out', 'Signout menu item has correct text'); - test.assertEquals(signoutHref, '/ghost/signout/', 'Sign Out href is correct'); - }, casper.failOnTimeout(test, 'WaitForSelector .user-menu .dropdown failed')); - - // TODO Add tests to check each pane gets active class appropriately -}); - -CasperTest.begin('Can transition to the editor and back', 6, function suite(test) { - casper.thenOpenAndWaitForPageLoad('root', function testTitleAndUrl() { - test.assertTitle('Content - Test Blog', 'Ghost admin has incorrect title'); - test.assertUrlMatch(/ghost\/\d+\/$/, 'Landed on the correct URL'); - }); - - casper.thenTransitionAndWaitForScreenLoad('editor', function testTransitionToEditor() { - test.assertUrlMatch(/ghost\/editor\//, 'Landed on the correct URL'); - test.assertExists('.entry-markdown', 'Ghost editor is present'); - test.assertExists('.entry-preview', 'Ghost preview is present'); - }); - - casper.thenTransitionAndWaitForScreenLoad('content', function testTransitionToContent() { - test.assertUrlMatch(/ghost\/\d+\/$/, 'Landed on the correct URL'); - }); -}); - -CasperTest.begin('Can search for posts and users', 8, function suite(test) { - var searchControl = '.gh-nav-search-input', - searchInput = '.gh-nav-search-input .selectize-input', - mouse = require('mouse').create(casper); - - casper.thenOpenAndWaitForPageLoad('root', function testTitleAndUrl() { - test.assertTitle('Content - Test Blog', 'Ghost admin has incorrect title'); - test.assertUrlMatch(/ghost\/\d+\/$/, 'Landed on the correct URL'); - }); - - casper.thenClick('.gh-nav-search-button'); - - casper.waitForResource(/posts\/\?fields=id%2Ctitle%2Cpage&limit=all&status=all&staticPages=all/, function then() { - test.assert(true, 'Queried filtered posts list on search focus'); - }, function timeout() { - casper.test.fail('Did not query filtered posts list on search focus'); - }); - - casper.waitForResource(/users\/\?fields=name%2Cslug&limit=all/, function then() { - test.assert(true, 'Queried filtered users list on search focus'); - }, function timeout() { - casper.test.fail('Did not query filtered users list on search focus'); - }); - - casper.then(function testUserResults() { - casper.sendKeys(searchInput, 'Test', {keepFocus: true}); - casper.waitForSelectorText(searchControl + ' .option.active', 'Test User', function success() { - test.assert(true, 'Queried user was displayed when searching'); - }, function timeout() { - casper.test.fail('Queried user was not displayed when searching'); - }); - }); - - casper.then(function testUserNavigation() { - casper.sendKeys(searchInput, casper.page.event.key.Enter, {keepFocus: true}); - casper.waitForSelector('.settings-user', function () { - test.assertUrlMatch(/ghost\/team\/test\//, 'Landed on correct URL'); - }); - }); - - // casper loses the focus somehow, click off/on the input to regain it - casper.thenClick('.gh-input.user-name'); - casper.thenClick(searchControl + ' .selectize-input'); - - casper.wait(500); - - casper.then(function testPostResultsAndClick() { - casper.sendKeys(searchInput, 'Welcome', {keepFocus: true}); - casper.wait(500); - casper.then(function () { - casper.waitForSelectorText(searchControl + ' .option.active', 'Welcome to Ghost', function success() { - test.assert(true, 'Queried post was displayed when searching'); - mouse.down(searchControl + ' .option.active'); - casper.waitForSelector('.view-editor', function () { - test.assertUrlMatch(/ghost\/editor\/\d\//, 'Landed on correct URL'); - }); - }, function timeout() { - casper.test.fail('Queried post was not displayed when searching'); - }); - }); - }); -}); diff --git a/core/test/functional/client/content_test.js b/core/test/functional/client/content_test.js deleted file mode 100644 index 994de07e48..0000000000 --- a/core/test/functional/client/content_test.js +++ /dev/null @@ -1,94 +0,0 @@ -// # Content Test -// Test the content screen, uses the editor to create dummy content - -/*globals CasperTest, casper, testPost */ - -CasperTest.begin('Content screen is correct', 15, 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('Content - Test Blog', 'Title is "Content - Test Blog"'); - test.assertUrlMatch(/ghost\/\d+\/$/, 'Landed on the correct URL'); - }); - - casper.then(function testViews() { - test.assertExists('.gh-main .gh-view', 'Content main view is present'); - test.assertExists('.content-list-content', 'Content list view is present'); - test.assertExists('.gh-nav-main-editor', 'add new post button exists'); - test.assertEquals( - this.getElementAttribute('.gh-nav-main-editor', 'href'), - '/ghost/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', 'correct status is present' - ); - test.assertExists('.content-preview', 'Content preview is present'); - }); - - casper.then(function testEditPostButton() { - test.assertExists('.content-preview a.post-edit', 'edit post button exists'); - }); - - 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.begin('Content list shows correct post status', 3, function testStaticPageStatus(test) { - CasperTest.Routines.createTestPost.run(true); - - // Begin test - casper.thenOpenAndWaitForPageLoad('content', function testTitleAndUrl() { - test.assertTitle('Content - Test Blog', 'Title is "Content - Test Blog"'); - test.assertUrlMatch(/ghost\/\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(3) a'); - - // Test for status of 'Published' - casper.then(function checkStatus() { - test.assertSelectorHasText('.content-list-content .active .published', 'Published', - 'status is present and labeled as published'); - }); - - casper.thenClick('.post-edit'); - casper.waitForSelector('#entry-title'); - - // // TODO readd this test when #3811 is fixed - // // Change post to static page - // casper.thenClick('.post-settings'); - // casper.waitForOpaque('.post-settings-menu.open'); - - // casper.thenClick('.post-setting-static-page'); - - // casper.thenTransitionAndWaitForScreenLoad('content', function onSuccess() { - // 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'); - // }); - // }); -}); - -// TODO: Implement this test... much needed! -// CasperTest.begin('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('Content - Test Blog', 'Title is "Content - Test Blog"'); -// test.assertUrlMatch(/ghost\/\d+\/$/, 'Landed on the correct URL'); -// }); -// }); diff --git a/core/test/functional/client/editor_test.js b/core/test/functional/client/editor_test.js deleted file mode 100644 index 977035e01f..0000000000 --- a/core/test/functional/client/editor_test.js +++ /dev/null @@ -1,734 +0,0 @@ -// # Editor Test -// Test the editor screen works as expected - -/*globals CasperTest, casper, testPost, $ */ -CasperTest.begin('Ghost editor functions correctly', 16, function suite(test) { - test.assertHTMLEquals = function (equals, message) { - test.assertEvalEquals(function () { - return document.querySelector('.entry-preview .rendered-markdown').innerHTML - .replace(/<\/script>/g, ''); - }, equals, message); - }; - - casper.thenOpenAndWaitForPageLoad('editor', function testTitleAndUrl() { - test.assertTitle('Editor - Test Blog', 'Ghost admin has incorrect title'); - test.assertUrlMatch(/ghost\/editor\/$/, 'Landed on the correct URL'); - test.assertExists('.entry-markdown', 'Ghost editor is present'); - test.assertExists('.entry-preview', 'Ghost preview is present'); - }); - - // Part 1: Test saving with no data - title should default - casper.waitForSelector('#entry-title', function then() { - test.assertEvalEquals(function () { - return document.getElementById('entry-title').value; - }, '', 'Title is empty'); - }); - - casper.thenClick('.js-publish-button'); - - casper.waitForSelector('.gh-notification', function onSuccess() { - test.assert(true, 'Can save with no title.'); - test.assertEvalEquals(function () { - return document.getElementById('entry-title').value; - }, '(Untitled)', 'Title is "(Untitled)"'); - }, function onTimeout() { - test.assert(false, 'Failed to save without a title.'); - }); - - casper.thenClick('.gh-notification-close'); - - // Part 2: Test saving with data - casper.then(function createTestPost() { - casper.sendKeys('#entry-title', testPost.title, {reset: true}); - casper.writeContentToEditor(testPost.html); - - // TODO: Expand markdown tests to cover more markdown, and keyboard shortcuts - casper.waitForSelectorTextChange('.entry-preview .rendered-markdown', function onSuccess() { - test.assertSelectorHasText( - '.entry-preview .rendered-markdown', - 'I am a test post. \n\nI have some small content\n', - 'Editor HTML preview has correct text.' - ); - test.assertHTMLEquals( - '

I am a test post.

\n\n

I have some small content

\n', - 'generated HTML is correct' - ); - }, casper.failOnTimeout(test, 'markdown did not re-render')); - }); - - casper.thenClick('.js-publish-button'); - - casper.waitForSelector('.gh-notification', function onSuccess() { - test.assertUrlMatch(/ghost\/editor\/\d+\/$/, 'got an id on our URL'); - test.assertEvalEquals(function () { - return document.querySelector('#entry-title').value; - }, testPost.title, 'Title is correct'); - }, casper.failOnTimeout(test, 'Post was not successfully created')); - - // Part 3: Test title trimming - var untrimmedTitle = ' test title ', - trimmedTitle = 'test title'; - - casper.then(function populateTitle() { - // Clear element - casper.evaluate(function () { - $('#entry-title').val(''); - }); - casper.sendKeys('#entry-title', untrimmedTitle); - casper.click('#entry-markdown-content'); - - test.assertEvalEquals(function () { - return $('#entry-title').val(); - }, trimmedTitle, 'Entry title should match expected value.'); - }); - - // Reset the editor - casper.thenOpenAndWaitForPageLoad('editor', function testWordCount() { - // Part 4: Word count and plurality - casper.then(function checkZeroPlural() { - test.assertSelectorHasText('.entry-word-count', '0 words', 'count of 0 produces plural "words".'); - }); - - casper.then(function () { - casper.writeContentToEditor('test'); - }); - - casper.waitForSelectorTextChange('.entry-word-count', function onSuccess() { - test.assertSelectorHasText('.entry-word-count', '1 word', 'count of 1 produces singular "word".'); - }); - - casper.then(function () { - casper.writeContentToEditor('test'); - }); - - casper.waitForSelectorTextChange('.entry-word-count', function onSuccess() { - test.assertSelectorHasText('.entry-word-count', '2 words', 'count of 2 produces plural "words".'); - }); - - casper.then(function () { - casper.writeContentToEditor('even **more** words'); // append another word, assumes newline - }); - - casper.waitForSelectorTextChange('.entry-word-count', function onSuccess() { - test.assertSelectorHasText('.entry-word-count', '5 words', 'count of 5 produces plural "words".'); - }); - }); -}); - -CasperTest.begin('Image Uploads', 23, function suite(test) { - test.assertHTMLEquals = function (equals, message) { - test.assertEvalEquals(function () { - return document.querySelector('.entry-preview .rendered-markdown').innerHTML - .replace(/<\/script>/g, ''); - }, equals, message); - }; - - casper.thenOpenAndWaitForPageLoad('editor', function testTitleAndUrl() { - test.assertTitle('Editor - Test Blog', 'Ghost admin has incorrect title'); - test.assertUrlMatch(/ghost\/editor\/$/, 'Landed on the correct URL'); - }); - // - // Test standard image upload modal - casper.then(function testImage() { - casper.writeContentToEditor('![some text]()'); - }); - - casper.waitForSelectorTextChange('.entry-preview .rendered-markdown', function onSuccess() { - test.assertEvalEquals(function () { - return document.querySelector('.entry-markdown-content textarea').value; - }, '![some text]()\n', 'Editor value is correct'); - - test.assertHTMLEquals('
Image Upload
Add image of some text
Something went wrong :(
URL
\n', 'HTML is correct'); - - test.assertSelectorHasText( - '.entry-preview .rendered-markdown', 'Add image of some text', 'Alt value is correct' - ); - }, function onTimeout() { - test.assert('false', 'markdown did not re-render'); - }); - - function assertEmptyImageUploaderDisplaysCorrectly() { - test.assertExists('.entry-preview .js-upload-target', 'Upload target exists'); - test.assertExists('.entry-preview .js-fileupload', 'File upload target exists'); - test.assertExists('.entry-preview .icon-link', 'Image URL button exists'); - } - - casper.then(function waitForUploader() { - casper.waitForSelector('.entry-preview .js-drop-zone.image-uploader', assertEmptyImageUploaderDisplaysCorrectly); - }); - - // Test image URL upload modal - casper.thenClick('.entry-preview .image-uploader a.image-url'); - - casper.then(function checkUploader() { - casper.waitForSelector('.image-uploader-url', function onSuccess() { - test.assertExists('.image-uploader-url .url.js-upload-url', 'Image URL uploader exists'); - test.assertExists('.image-uploader-url .btn-blue.js-button-accept', 'Image URL accept button exists'); - test.assertExists('.image-uploader-url .image-upload', 'Back to normal image upload style button exists'); - }); - }); - - // Test image source location - casper.thenOpenAndWaitForPageLoad('editor', function testTitleAndUrl() { - test.assertTitle('Editor - Test Blog', 'Ghost admin has incorrect title'); - test.assertUrlMatch(/ghost\/editor\/$/, 'Landed on the correct URL'); - }); - - var testFileLocation = '/test/file/location', - imageURL = 'http://www.random.url'; - - casper.then(function () { - var markdownImageString = '![](' + testFileLocation + ')'; - casper.writeContentToEditor(markdownImageString); - }); - - casper.waitForSelector('img.js-upload-target', function () { - var imageJQuerySelector = '.entry-preview img.js-upload-target[src="' + testFileLocation + '"]'; - test.assertExists(imageJQuerySelector, 'Uploaded image tag properly links to source location'); - }); - - // Test cancel image button - casper.thenClick('.pre-image-uploader a.image-cancel.js-cancel'); - - casper.waitForSelector('.entry-preview .js-drop-zone.image-uploader', assertEmptyImageUploaderDisplaysCorrectly); - - // Test image url source location - casper.thenOpenAndWaitForPageLoad('editor', function testTitleAndUrl() { - test.assertTitle('Editor - Test Blog', 'Ghost admin has incorrect title'); - test.assertUrlMatch(/ghost\/editor\/$/, 'Landed on the correct URL'); - }); - - casper.then(function () { - casper.writeContentToEditor('![]()'); - }); - - casper.then(function () { - casper.waitForSelector('.entry-preview .js-drop-zone.image-uploader', function onSuccess() { - casper.thenClick('.entry-preview .image-uploader .image-url'); - }); - }); - - casper.then(function () { - 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'); - }); - }); - - casper.waitForSelector('img.js-upload-target', function onSuccess() { - var imageJQuerySelector = '.entry-preview img.js-upload-target[src="' + imageURL + '"]'; - test.assertExists(imageJQuerySelector, 'Uploaded image tag properly links to inputted image URL'); - }); - - // Save the post with the image - casper.thenClick('.js-publish-button'); - - casper.waitForSelector('.gh-notification', function onSuccess() { - test.assertUrlMatch(/ghost\/editor\/\d+\/$/, 'got an id on our URL'); - }, casper.failOnTimeout(test, 'Post was not successfully created')); - - casper.thenTransitionAndWaitForScreenLoad('content', function canTransition() { - test.assert(true, 'Can transition to content screen'); - test.assertUrlMatch(/ghost\/\d+\/$/, 'content transitions to correct url'); - }); - - // TODO fix this test - // Edit the draft post we just created - // casper.thenClick('a.post-edit'); - // - // casper.waitForScreenLoad('editor.editing', function () { - // casper.writeContentToEditor('abcdefghijklmnopqrstuvwxyz'); - // casper.waitForSelectorTextChange('.entry-preview .rendered-markdown', function onSuccess() { - // test.assertSelectorHasText( - // '.entry-preview .rendered-markdown',// - // 'abcdefghijklmnopqrstuvwxyz', - // 'Editor HTML preview has correct text after editing.' - // ); - // }, casper.failOnTimeout(test, 'markdown did not re-render')); - // - // }, casper.failOnTimeout(test, 'Editor did not load')); -}); - -CasperTest.begin('Publish menu - new post', 10, function suite(test) { - casper.thenOpenAndWaitForPageLoad('editor', function testTitleAndUrl() { - test.assertTitle('Editor - Test Blog', 'Ghost admin has incorrect title'); - test.assertUrlMatch(/ghost\/editor\/$/, 'Landed on the correct URL'); - }); - - // ... check default option status, label, class - casper.then(function () { - test.assertExists('.js-publish-splitbutton', '.js-publish-splitbutton exists'); - test.assertExists('.js-publish-button', '.js-publish-button exists'); - test.assertExists('.js-publish-button.btn-blue', '.js-publish-button.btn-blue exists'); - test.assertSelectorHasText('.js-publish-button', 'Save Draft', '.js-publish-button says Save Draft'); - }); - - // Fill headline and content - casper.then(function fillContent() { - casper.sendKeys('#entry-title', 'Headline'); - casper.writeContentToEditor('Just a bit of test text'); - }); - - casper.then(function switchMenuToPublish() { - // Open the publish options menu; - casper.thenClick('.js-publish-splitbutton .dropdown-toggle'); - - casper.waitForOpaque('.js-publish-splitbutton .dropdown-menu'); - - // Select the publish post button - casper.thenClick('.js-publish-splitbutton li:first-child a'); - - // ... check status, label, class - casper.waitForSelector('.js-publish-splitbutton .js-publish-button:not([disabled])', function onSuccess() { - test.assertExists('.js-publish-button.btn-red', 'Publish button should have .btn-red'); - test.assertSelectorHasText('.js-publish-button', 'Publish Now', '.js-publish-button says Publish Now'); - }, function onTimeout() { - test.assert(false, 'Publish split button works'); - }); - }); - - // Do publish - casper.thenClick('.js-publish-button'); - - // ... check status, label, class - casper.waitForSelector('.js-publish-splitbutton .js-publish-button:not([disabled])', function onSuccess() { - test.assertExists('.js-publish-button.btn-blue', 'Update button should have .btn-blue'); - test.assertSelectorHasText('.js-publish-button', 'Update Post', '.js-publish-button says Update Post'); - }, function onTimeout() { - test.assert(false, 'Publish split button works'); - }); -}); - -CasperTest.begin('Publish menu - new page', 10, function suite(test) { - casper.thenOpenAndWaitForPageLoad('editor', function testTitleAndUrl() { - test.assertTitle('Editor - Test Blog', 'Ghost admin has incorrect title'); - test.assertUrlMatch(/ghost\/editor\/$/, 'Landed on the correct URL'); - }); - - // ... check default option status, label, class - casper.then(function () { - test.assertExists('.js-publish-splitbutton', '.js-publish-splitbutton exists'); - test.assertExists('.js-publish-button', '.js-publish-button exists'); - test.assertExists('.js-publish-button.btn-blue', '.js-publish-button.btn-blue exists'); - test.assertSelectorHasText('.js-publish-button', 'Save Draft', '.js-publish-button says Save Draft'); - }); - - // Fill headline and content - casper.then(function fillContent() { - casper.sendKeys('#entry-title', 'Page Headline'); - casper.writeContentToEditor('There once was a page, this was it'); - }); - - // Open post settings menu - casper.thenClick('.post-settings'); - - // Check the checkbox is checked - casper.thenClick('label[for=static-page]'); - - casper.then(function switchMenuToPublish() { - // Open the publish options menu; - casper.thenClick('.js-publish-splitbutton .dropdown-toggle'); - - casper.waitForOpaque('.js-publish-splitbutton .dropdown-menu'); - - // Select the publish post button - casper.thenClick('.js-publish-splitbutton li:first-child a'); - - // ... check status, label, class - casper.waitForSelector('.js-publish-splitbutton .js-publish-button:not([disabled])', function onSuccess() { - test.assertExists('.js-publish-button.btn-red', 'Publish button should have .btn-red'); - test.assertSelectorHasText('.js-publish-button', 'Publish Now', '.js-publish-button says Publish Now'); - }, function onTimeout() { - test.assert(false, 'Publish split button works'); - }); - }); - - // Do publish - casper.thenClick('.js-publish-button'); - - // ... check status, label, class - casper.waitForSelector('.js-publish-splitbutton .js-publish-button:not([disabled])', function onSuccess() { - test.assertExists('.js-publish-button.btn-blue', 'Update button should have .btn-blue'); - test.assertSelectorHasText('.js-publish-button', 'Update Page', '.js-publish-button says Update Page'); - }, function onTimeout() { - test.assert(false, 'Publish split button works'); - }); -}); - -CasperTest.begin('Publish menu - existing post', 23, function suite(test) { - // Create a post, save it and test refreshed editor - casper.thenOpenAndWaitForPageLoad('editor', function testTitleAndUrl() { - test.assertTitle('Editor - Test Blog', 'Ghost admin has incorrect title'); - test.assertUrlMatch(/ghost\/editor\/$/, 'Landed on the correct URL'); - }); - - casper.thenClick('.js-publish-splitbutton .dropdown-toggle'); - - casper.waitForOpaque('.js-publish-splitbutton .dropdown-menu', function onSuccess() { - test.assert(true, 'popup menu should be visible after clicking post-settings icon'); - test.assertNotVisible( - '.js-publish-splitbutton .delete', 'delete post button shouldn\'t be visible on unsaved drafts' - ); - }); - - casper.then(function createTestPost() { - casper.sendKeys('#entry-title', testPost.title); - casper.writeContentToEditor(testPost.html); - }); - - casper.waitForSelectorTextChange('.entry-preview .rendered-markdown', function onSuccess() { - test.assertSelectorHasText('.entry-preview .rendered-markdown', 'test', 'Editor value is correct'); - }); - - casper.thenClick('.js-publish-splitbutton .dropdown-toggle'); - - // Create a post in draft status - casper.thenClick('.js-publish-button'); - - casper.waitForSelector('.gh-notification', function checkPostWasCreated() { - test.assertUrlMatch(/ghost\/editor\/\d+\/$/, 'got an id on our URL'); - }); - - // ... check option status, label, class now that we're *saved* as 'draft' - casper.waitForSelector('.js-publish-splitbutton .js-publish-button:not([disabled])', function () { - test.assertExists('.js-publish-splitbutton', '.js-publish-splitbutton exists'); - test.assertExists('.js-publish-button', '.js-publish-button exists'); - test.assertExists('.js-publish-button.btn-blue', '.js-publish-button.btn-blue exists'); - test.assertSelectorHasText('.js-publish-button', 'Save Draft', '.js-publish-button says Save Draft'); - }); - - casper.thenClick('.js-publish-splitbutton .dropdown-toggle'); - - casper.waitForOpaque('.js-publish-splitbutton .dropdown-menu', function onSuccess() { - test.assert(true, 'delete post button should be visible for saved drafts'); - test.assertVisible( - '.js-publish-splitbutton .delete', 'delete post button should be visible on saved drafts' - ); - }); - - casper.thenClick('.js-publish-splitbutton .dropdown-toggle'); - - casper.then(function switchMenuToPublish() { - // Open the publish options menu; - casper.thenClick('.js-publish-splitbutton .dropdown-toggle'); - - casper.waitForOpaque('.js-publish-splitbutton .dropdown-menu'); - - // Select the publish post button - casper.thenClick('.js-publish-splitbutton li:first-child a'); - - // ... check status, label, class - casper.waitForSelector('.js-publish-splitbutton', function onSuccess() { - test.assertExists('.js-publish-button.btn-red', 'Publish button should have .btn-red'); - test.assertSelectorHasText('.js-publish-button', 'Publish Now', '.js-publish-button says Publish Now'); - }, function onTimeout() { - test.assert(false, 'Publish split button works'); - }); - }); - - // Do publish - casper.thenClick('.js-publish-button'); - - casper.waitForSelector('.gh-notification', function checkPostWasCreated() { - test.assertUrlMatch(/ghost\/editor\/\d+\/$/, 'got an id on our URL'); - }); - - // ... check option status, label, class for saved as 'published' - casper.waitForSelector('.js-publish-splitbutton .js-publish-button:not([disabled])', function () { - test.assertExists('.js-publish-splitbutton', '.js-publish-splitbutton exists'); - test.assertExists('.js-publish-button', '.js-publish-button exists'); - test.assertExists('.js-publish-button.btn-blue', '.js-publish-button.btn-blue exists'); - test.assertSelectorHasText('.js-publish-button', 'Update Post', '.js-publish-button says Update Post'); - }); - - casper.then(function switchMenuToUnpublish() { - // Open the publish options menu; - casper.thenClick('.js-publish-splitbutton .dropdown-toggle'); - - casper.waitForOpaque('.js-publish-splitbutton .dropdown-menu'); - - // Select the publish post button - casper.thenClick('.js-publish-splitbutton li:nth-child(2) a'); - - // ... check status, label, class - casper.waitForSelector('.js-publish-splitbutton', function onSuccess() { - test.assertExists('.js-publish-button.btn-red', 'Publish button should have .btn-red'); - test.assertSelectorHasText('.js-publish-button', 'Unpublish', '.js-publish-button says Unpublish'); - }, function onTimeout() { - test.assert(false, 'Publish split button works'); - }); - }); - // Do unpublish - casper.thenClick('.js-publish-button'); - - casper.waitForSelector('.gh-notification', function checkPostWasCreated() { - // ... check status, label, class - casper.waitForSelector('.js-publish-splitbutton .js-publish-button:not([disabled])', function onSuccess() { - test.assertExists('.js-publish-button.btn-blue', 'Publish button should have .btn-blue'); - test.assertSelectorHasText('.js-publish-button', 'Save Draft', '.js-publish-button says Save Draft'); - }, function onTimeout() { - test.assert(false, 'Publish split button works'); - }); - }); -}); - -CasperTest.begin('Publish menu - delete post', 6, function testDeleteModal(test) { - // Create a post that can be deleted - CasperTest.Routines.createTestPost.run(false); - - // Begin test - casper.thenOpenAndWaitForPageLoad('content', function testTitleAndUrl() { - test.assertTitle('Content - Test Blog', 'Title is "Content - Test Blog"'); - test.assertUrlMatch(/ghost\/\d+\/$/, 'Landed on the correct URL'); - }); - - // Transition to the editor - casper.thenClick('.post-edit'); - casper.waitForSelector('#entry-title'); - - // Open post settings menu - casper.thenClick('.js-publish-splitbutton .dropdown-toggle'); - casper.waitForOpaque('.js-publish-splitbutton .dropdown-menu'); - casper.thenClick('.js-publish-splitbutton li:nth-child(4) a'); - - 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('.js-publish-splitbutton .dropdown-toggle'); - casper.waitForOpaque('.js-publish-splitbutton .dropdown-menu'); - casper.thenClick('.js-publish-splitbutton li:nth-child(4) a'); - - 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.waitWhileVisible('.modal-container', function onSuccess() { - test.assert(true, 'clicking delete button should close the delete post modal'); - }); - }); -}); - -CasperTest.begin('Publish menu - new post status is correct after failed save', 2, function suite(test) { - casper.thenOpenAndWaitForPageLoad('editor', function testTitleAndUrl() { - test.assertTitle('Editor - Test Blog', 'Ghost admin has incorrect title'); - test.assertUrlMatch(/ghost\/editor\/$/, 'Landed on the correct URL'); - }); - - // Fill title and content - casper.then(function writePost() { - casper.sendKeys('#entry-title', new Array(160).join('x')); - }); - - casper.then(function switchMenuToPublish() { - // Open the publish options menu; - casper.thenClick('.js-publish-splitbutton .dropdown-toggle'); - - casper.waitForOpaque('.js-publish-splitbutton .dropdown-menu'); - - // Select the publish post button - casper.thenClick('.js-publish-splitbutton li:first-child a'); - }); - - // attempt to save - casper.thenClick('.js-publish-button'); - - // Click on "Content" in the main nav - casper.thenClick('.gh-nav-main-content'); - - // The "Are you sure?" modal appears - casper.waitUntilVisible('.modal-content', function onSuccess() { - casper.thenClick('.btn-red'); - }, function onTimeout() { - test.assert(false, 'Are you sure you want to leave modal did not appear.'); - }); -}); - -CasperTest.begin('Publish menu - existing post status is correct after failed save', 6, function suite(test) { - casper.thenOpenAndWaitForPageLoad('editor', function testTitleAndUrl() { - test.assertTitle('Editor - Test Blog', 'Ghost admin has incorrect title'); - test.assertUrlMatch(/ghost\/editor\/$/, 'Landed on the correct URL'); - }); - - // Fill title and content - casper.then(function writePost() { - casper.sendKeys('#entry-title', 'a valid title'); - casper.writeContentToEditor('body content'); - }); - - // save - casper.thenClick('.js-publish-button'); - - casper.waitForSelector('.gh-notification'); - - casper.then(function updateTitle() { - casper.sendKeys('#entry-title', new Array(160).join('y')); - }); - - casper.then(function switchMenuToPublish() { - // Open the publish options menu; - casper.thenClick('.js-publish-splitbutton .dropdown-toggle'); - - casper.waitForOpaque('.js-publish-splitbutton .dropdown-menu'); - - // Select the publish post button - casper.thenClick('.js-publish-splitbutton li:first-child a'); - - // ... check status, label, class - casper.waitForSelector('.js-publish-splitbutton .js-publish-button:not([disabled])', function onSuccess() { - test.assertExists('.js-publish-button.btn-red', 'Publish button should have .btn-red'); - test.assertSelectorHasText('.js-publish-button', 'Publish Now', '.js-publish-button says Publish Now'); - }, function onTimeout() { - test.assert(false, 'Publish split button works'); - }); - }); - - // attempt to save - casper.thenClick('.js-publish-button'); - - // ... check status, label, class - casper.waitForSelector('.gh-alert-red', function onSuccess() { - test.assertExists('.js-publish-button.btn-blue', 'Update button should have .btn-blue'); - // wait for button to settle - casper.wait(1100); - casper.then(function () { - test.assertSelectorHasText('.js-publish-button', 'Save Draft', '.js-publish-button says Save Draft'); - }); - }, function onTimeout() { - test.assert(false, 'Saving post with invalid title should trigger an error'); - }); -}); - -// test the markdown help modal -CasperTest.begin('Markdown help modal', 5, function suite(test) { - casper.thenOpenAndWaitForPageLoad('editor', function testTitleAndUrl() { - test.assertTitle('Editor - Test Blog', 'Ghost admin has incorrect title'); - test.assertUrlMatch(/ghost\/editor\/$/, 'Landed on the correct URL'); - }); - - // open markdown help modal - casper.thenClick('a.markdown-help'); - - casper.waitUntilVisible('.modal-container', function onSuccess() { - test.assertSelectorHasText( - '.modal-content .modal-header', - 'Markdown Help', - 'delete modal has correct text'); - - test.assertExists('.modal-content .close', '.modal-content .close exists'); - }); - - casper.thenClick('.modal-content .close'); - - casper.waitWhileVisible('.modal-container', function onSuccess() { - test.assert(true, 'clicking close should remove the markdown help modal'); - }); -}); - -// test editor title input is correct after changing a post attribute in the post-settings-menu -CasperTest.begin('Title input is set correctly after using the Post-Settings-Menu', function suite(test) { - casper.thenOpenAndWaitForPageLoad('editor', function testTitleAndUrl() { - test.assertTitle('Editor - Test Blog', 'Ghost admin has incorrect title'); - test.assertUrlMatch(/ghost\/editor\/$/, 'Landed on the correct URL'); - }); - - // add a new post - casper.then(function fillContent() { - casper.sendKeys('#entry-title', 'post title', {reset: true}); - casper.writeContentToEditor('Just a bit of test text'); - }); - - // save draft - casper.thenClick('.js-publish-button'); - - casper.waitForSelector('.gh-notification'); - - // change the title - casper.then(function updateTitle() { - casper.sendKeys('#entry-title', 'changed post title', {reset: true}); - casper.click('#entry-markdown-content'); - }); - - // change a post attribute via the post-settings-menu - - casper.thenClick('.post-settings'); - - casper.then(function () { - this.fillSelectors('.settings-menu form', { - '#url': 'changed-slug' - }, false); - - this.click('.post-settings'); - }); - - casper.waitForResource(/\/posts\/\d+\/\?include=tags/, function testGoodResponse(resource) { - test.assert(resource.status < 400); - }); - - casper.then(function checkTitleInput() { - test.assertEvalEquals(function () { - return $('#entry-title').val(); - }, 'changed post title', 'Title input should match expected value.'); - }); -}); - -// test editor content input is correct after changing a post attribute in the post-settings-menu -CasperTest.begin('Editor content is set correctly after using the Post-Settings-Menu', function suite(test) { - casper.thenOpenAndWaitForPageLoad('editor', function testTitleAndUrl() { - test.assertTitle('Editor - Test Blog', 'Ghost admin has incorrect title'); - test.assertUrlMatch(/ghost\/editor\/$/, 'Landed on the correct URL'); - }); - - // add a new post - casper.then(function fillContent() { - casper.sendKeys('#entry-title', 'post title'); - casper.writeContentToEditor('Just a bit of test text'); - }); - - // save draft - casper.thenClick('.js-publish-button'); - - casper.waitForSelector('.gh-notification'); - - // change the content - casper.then(function updateContent() { - casper.writeContentToEditor('updated content'); - casper.click('#entry-title'); - }); - - // change a post attribute via the post-settings-menu - - casper.thenClick('.post-settings'); - - casper.then(function () { - this.fillSelectors('.settings-menu form', { - '#url': 'changed-slug-after-update' - }, false); - - this.click('.post-settings'); - }); - - casper.waitForResource(/\/posts\/\d+\/\?include=tags/, function testGoodResponse(resource) { - test.assert(resource.status < 400); - }); - - casper.waitForSelectorTextChange('.entry-preview .rendered-markdown', function onSuccess() { - test.assertSelectorHasText( - '.entry-preview .rendered-markdown', - 'updated content', - 'Editor has correct content.' - ); - }, casper.failOnTimeout(test, 'markdown was not available')); -}); diff --git a/core/test/functional/client/psm_test.js b/core/test/functional/client/psm_test.js deleted file mode 100644 index 7ed2c40acb..0000000000 --- a/core/test/functional/client/psm_test.js +++ /dev/null @@ -1,259 +0,0 @@ -// # Post Settings Menu Tests -// Test the post settings menu on the editor screen works as expected - -/*globals CasperTest, casper, __utils__ */ - -CasperTest.begin('Post settings menu', 8, function suite(test) { - casper.thenOpenAndWaitForPageLoad('editor', function testTitleAndUrl() { - test.assertTitle('Editor - Test Blog', 'Ghost admin has incorrect title'); - test.assertUrlMatch(/ghost\/editor\/$/, 'Landed on the correct URL'); - }); - - casper.then(function () { - test.assertExists('.post-settings', 'icon toggle should exist'); - test.assertExists('.settings-menu', 'popup menu should be rendered at startup'); - test.assertExists('.settings-menu #url', 'url field exists'); - test.assertExists('.settings-menu .post-setting-date', 'publication date field exists'); - test.assertExists('.settings-menu .post-setting-static-page', 'static page checkbox field exists'); - }); - - // 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.sendKeys('#entry-title', 'aTitle'); - casper.thenClick('.js-publish-button'); - }); - - casper.thenClick('.post-settings'); - - casper.waitForOpaque('.settings-menu', function onSuccess() { - test.assert(true, 'post settings menu should be visible after clicking post-settings icon'); - }); -}); - -CasperTest.begin('Post url can be changed', 4, function suite(test) { - // Create a sample post - CasperTest.Routines.createTestPost.run(false); - - // Begin test - casper.thenOpenAndWaitForPageLoad('content', function testTitleAndUrl() { - test.assertTitle('Content - Test Blog', 'Title is "Content - Test Blog"'); - test.assertUrlMatch(/ghost\/\d+\/$/, 'Landed on the correct URL'); - }); - - // Transition to the editor - casper.thenClick('.post-edit'); - casper.waitForSelector('#entry-title'); - - casper.thenClick('.post-settings'); - - // Test change permalink - casper.then(function () { - this.fillSelectors('.settings-menu form', { - '#url': 'new-url' - }, false); - - this.click('.post-settings'); - }); - - casper.waitForResource(/\/posts\/\d+\/\?include=tags/, function testGoodResponse(resource) { - test.assert(resource.status < 400, 'resource.status < 400'); - }); - - casper.then(function checkValueMatches() { - // using assertField(name) checks the htmls initial "value" attribute, so have to hack around it. - var slugVal = this.evaluate(function () { - return __utils__.getFieldValue('post-setting-slug'); - }); - test.assertEquals(slugVal, 'new-url', 'slug has correct value'); - }); -}); - -CasperTest.begin('Post published date can be changed', 4, function suite(test) { - // Create a sample post - CasperTest.Routines.createTestPost.run(false); - - // Begin test - casper.thenOpenAndWaitForPageLoad('content', function testTitleAndUrl() { - test.assertTitle('Content - Test Blog', 'Title is "Content - Test Blog"'); - test.assertUrlMatch(/ghost\/\d+\/$/, 'Landed on the correct URL'); - }); - - // Transition to the editor - casper.thenClick('.post-edit'); - casper.waitForSelector('#entry-title'); - - casper.thenClick('.post-settings'); - - // Test change published date - casper.then(function () { - this.fillSelectors('.settings-menu form', { - '.post-setting-date': '22 May 14 @ 23:39' - }, false); - - this.click('.post-settings'); - }); - - casper.waitForResource(/\/posts\/\d+\/\?include=tags/, function testGoodResponse(resource) { - test.assert(resource.status < 400, 'resource.status < 400'); - }); - - casper.then(function checkValueMatches() { - // using assertField(name) checks the htmls initial "value" attribute, so have to hack around it. - var dateVal = this.evaluate(function () { - return __utils__.getFieldValue('post-setting-date'); - }); - test.assertEquals(dateVal, '22 May 14 @ 23:39', 'date is correct'); - }); -}); - -CasperTest.begin('Post can be changed to static page', 2, function suite(test) { - // Create a sample post - CasperTest.Routines.createTestPost.run(false); - - // Begin test - casper.thenOpenAndWaitForPageLoad('content', function testTitleAndUrl() { - test.assertTitle('Content - Test Blog', 'Title is "Content - Test Blog"'); - test.assertUrlMatch(/ghost\/\d+\/$/, 'Landed on the correct URL'); - }); - - // Transition to the editor - casper.thenClick('.post-edit'); - casper.waitForSelector('#entry-title'); - - casper.thenClick('.post-settings'); - - casper.thenClick('label[for=static-page]'); - - casper.waitForSelector('.post-setting-static-page:checked', function onSuccess() { - casper.click('label[for=static-page]'); - }, function onTimeout() { - casper.test.fail('Post was not changed to static page.'); - }, 2000); - - casper.waitForSelector('.post-setting-static-page:not(checked)', function onSuccess() { - return; - }, function onTimeout() { - casper.test.fail('Static page was not changed to post.'); - }, 2000); -}); - -CasperTest.begin('Post url input is reset from all whitespace back to original value', 4, function suite(test) { - // Create a sample post - CasperTest.Routines.createTestPost.run(false); - - // Begin test - casper.thenOpenAndWaitForPageLoad('content', function testTitleAndUrl() { - test.assertTitle('Content - Test Blog', 'Title is "Content - Test Blog"'); - test.assertUrlMatch(/ghost\/\d+\/$/, 'Landed on the correct URL'); - }); - - // Transition to the editor - casper.thenClick('.post-edit'); - casper.waitForSelector('#entry-title'); - - casper.thenClick('.post-settings'); - - var originalSlug; - casper.then(function () { - originalSlug = casper.evaluate(function () { - return __utils__.getFieldValue('post-setting-slug'); - }); - }); - - // Test change permalink - casper.then(function () { - this.fillSelectors('.settings-menu form', { - '#url': ' ' - }, false); - }); - - // Click in a different field - casper.thenClick('#post-setting-date'); - - casper.then(function checkValueMatches() { - // using assertField(name) checks the htmls initial "value" attribute, so have to hack around it. - var slugVal = this.evaluate(function () { - return __utils__.getFieldValue('post-setting-slug'); - }); - test.assertNotEquals(slugVal, ' ', 'slug is not just spaces'); - test.assertEquals(slugVal, originalSlug, 'slug gets reset to original value'); - }); -}); - -CasperTest.begin('Tag Editor', 9, function suite(test) { - var testTag = 'Test1', - createdTag = '#tag-input + .selectize-control .item', - tagInput = '#tag-input + .selectize-control input[type="text"]'; - - casper.thenOpenAndWaitForPageLoad('editor', function testTitleAndUrl() { - test.assertTitle('Editor - Test Blog', 'Ghost admin has incorrect title'); - test.assertUrlMatch(/ghost\/editor\/$/, 'Landed on the correct URL'); - }); - - casper.then(function () { - test.assertExists('#tag-input + .selectize-control', 'should have tag list area'); - }); - - casper.thenClick(tagInput); - casper.then(function () { - casper.sendKeys(tagInput, testTag, {keepFocus: true}); - }); - casper.then(function () { - casper.sendKeys(tagInput, casper.page.event.key.Enter, {keepFocus: true}); - }); - - casper.waitForSelector(createdTag, function onSuccess() { - test.assertSelectorHasText(createdTag, testTag, 'typing enter after tag name should create tag'); - }); - - casper.thenClick(createdTag + ' a.remove'); - casper.waitWhileSelector(createdTag, function onSuccess() { - test.assert(true, 'clicking the tag remove button should delete the tag'); - }); - - casper.then(function () { - casper.sendKeys(tagInput, testTag, {keepFocus: true}); - }); - casper.then(function () { - casper.sendKeys(tagInput, casper.page.event.key.Tab, {keepFocus: true}); - }); - casper.waitForSelector(createdTag, function onSuccess() { - test.assertSelectorHasText(createdTag, testTag, 'typing tab after tag name should create tag'); - }); - - casper.then(function () { - casper.sendKeys(tagInput, casper.page.event.key.Backspace, {keepFocus: true}); - }); - casper.waitWhileSelector(createdTag, function onSuccess() { - test.assert(true, 'hitting backspace should delete the last tag'); - }); - - casper.then(function () { - casper.sendKeys(tagInput, testTag, {keepFocus: true}); - }); - casper.then(function () { - casper.sendKeys(tagInput, casper.page.event.key.Enter, {keepFocus: true}); - }); - casper.thenClick(createdTag); - casper.waitForSelector(createdTag + '.active', function onSuccess() { - test.assert(true, 'clicking a tag should highlight it'); - }); - - casper.then(function () { - casper.sendKeys(createdTag + '.active', casper.page.event.key.Backspace); - }); - casper.waitWhileSelector(createdTag + '.active', function onSuccess() { - test.assert(true, 'hitting backspace on a higlighted tag should delete it'); - }); - - // TODO: add this back in if create-on-blur functionality is required - // casper.then(function () { - // casper.sendKeys(tagInput, testTag, {keepFocus: true}); - // }); - // // Click in a different field - // casper.thenClick('#post-setting-date'); - // casper.waitForSelector(createdTag, function onSuccess() { - // test.assertSelectorHasText(createdTag, testTag, 'de-focusing from tag input should create tag with leftover text'); - // }); -}); diff --git a/core/test/functional/client/settings_test.js b/core/test/functional/client/settings_test.js deleted file mode 100644 index 2e5128c899..0000000000 --- a/core/test/functional/client/settings_test.js +++ /dev/null @@ -1,134 +0,0 @@ -// # Settings Test -// Test the various tabs on the settings page - -/*globals CasperTest, casper */ - -// 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 = '.gh-nav-settings-general.active'; - -CasperTest.begin('Settings screen is correct', 5, function suite(test) { - casper.thenOpenAndWaitForPageLoad('settings.general', function testTitleAndUrl() { - test.assertTitle('Settings - General - Test Blog', 'Ghost admin has incorrect title'); - test.assertUrlMatch(/ghost\/settings\/general\/$/, 'Landed on the correct URL'); - }); - - casper.then(function testViews() { - test.assertExists('.gh-main .gh-view', 'Settings content view is present'); - test.assertExists(generalTabDetector, 'Form is present'); - test.assertSelectorHasText('.view-title', 'General', 'Title is "General"'); - }); -}); - -// ## General settings tests -CasperTest.begin('General settings pane is correct', 4, function suite(test) { - casper.thenOpenAndWaitForPageLoad('settings.general', function testTitleAndUrl() { - test.assertUrlMatch(/ghost\/settings\/general\/$/, 'Landed on the correct URL'); - }); - - function assertImageUploaderModalThenClose() { - test.assertSelectorHasText('.description', 'Add image', '.description has the correct text'); - casper.click('.modal-container .js-button-accept'); - } - - // Ensure image upload modals display correctly - - // Test Blog Logo Upload Button - casper.waitForSelector('.js-modal-logo', function () { - casper.click('.js-modal-logo'); - }); - - 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.waitForSelector('.js-modal-cover', function () { - casper.click('.js-modal-cover'); - }); - - casper.waitForSelector('.modal-container .modal-content .js-drop-zone .description', - assertImageUploaderModalThenClose, casper.failOnTimeout(test, 'No upload cover modal container appeared')); - - 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', handleSettingsRequest); - }); - - // Ensure can save - casper.waitForSelector('header .btn-blue').then(function () { - casper.thenClick('header .btn-blue'); - casper.waitForResource('settings/', function onSuccess() { - test.assert(true, 'Settings were saved'); - }, function doneWaiting() { - test.fail('Settings were not saved'); - }); - }); - - casper.then(function stopListeningForRequests() { - casper.removeListener('resource.requested', handleSettingsRequest); - }); -}); - -// ## General settings validations tests -CasperTest.begin('General settings validation is correct', 7, function suite(test) { - casper.thenOpenAndWaitForPageLoad('settings.general', function testTitleAndUrl() { - test.assertTitle('Settings - General - Test Blog', 'Ghost admin has incorrect title'); - test.assertUrlMatch(/ghost\/settings\/general\/$/, 'Landed on the correct URL'); - }); - - // Ensure general blog title field length validation - casper.fillAndSave('form#settings-general', { - 'general[title]': new Array(152).join('a') - }); - - casper.waitForText('Title is too long', function onSuccess() { - test.assert(true, 'Blog title length error was shown'); - }, casper.failOnTimeout(test, 'Blog title length error did not appear')); - - // Ensure general blog description field length validation - casper.fillAndSave('form#settings-general', { - 'general[description]': new Array(202).join('a') - }); - - casper.waitForText('Description is too long', function onSuccess() { - test.assert(true, 'Blog description length error was shown'); - }, casper.failOnTimeout(test, 'Blog description length error did not appear')); - - // TODO move these to ember tests, note: async issues - field will be often be null without a casper.wait - // Check postsPerPage autocorrect - casper.fillAndSave('form#settings-general', { - 'general[postsPerPage]': 'notaninteger' - }); - - casper.wait(2000); - - casper.then(function checkSlugInputValue() { - test.assertField('general[postsPerPage]', '5', 'posts per page is set correctly'); - }); - - casper.fillAndSave('form#settings-general', { - 'general[postsPerPage]': '1001' - }); - - casper.wait(2000); - - casper.then(function checkSlugInputValue() { - test.assertField('general[postsPerPage]', '5', 'posts per page is set correctly'); - }); - - // Ensure private blog password validation - casper.fillAndSave('form#settings-general', { - 'general[isPrivate]': '1', - 'general[password]': '' - }); - - casper.waitForText('Password must be supplied', function onSuccess() { - test.assert(true, 'Password required error was shown'); - }, casper.failOnTimeout(test, 'Password required error did not appear')); -}); diff --git a/core/test/functional/client/signin_test.js b/core/test/functional/client/signin_test.js deleted file mode 100644 index 650ba773dc..0000000000 --- a/core/test/functional/client/signin_test.js +++ /dev/null @@ -1,246 +0,0 @@ -// # Signin Test -// Test that signin works, including testing our spam prevention mechanisms - -/*globals CasperTest, casper, url, user, falseUser */ - -CasperTest.begin('Ghost admin will load login page', 4, function suite(test) { - CasperTest.Routines.signout.run(test); - casper.thenOpenAndWaitForPageLoad('signin', function testTitleAndUrl() { - test.assertTitle('Sign In - Test Blog', 'Ghost admin has incorrect title'); - test.assertUrlMatch(/ghost\/signin\/$/, 'We should be presented with the signin page.'); - - casper.then(function testLink() { - var text = this.evaluate(function (selector) { - return document.querySelector(selector).innerText; - }, '.forgotten-link'); - - casper.echoConcise('Text' + text); - test.assertExists('.forgotten-link', '.forgotten-link exists'); - test.assertEquals(text, 'Forgot?', 'Forgotten text is correct'); - }); - }); -}, true); - -// Note, this test applies to a global redirect, which sends us to the standard admin. -CasperTest.begin('Redirects login to signin', 2, function suite(test) { - CasperTest.Routines.signout.run(test); - casper.start(url + 'ghost/login/', function testRedirect(response) { - test.assertEquals(response.status, 200, 'Response status should be 200.'); - test.assertUrlMatch(/ghost\/signin\//, 'Should be redirected to /signin/.'); - }); -}, true); - -CasperTest.begin('Login limit is in place', 7, function suite(test) { - CasperTest.Routines.signout.run(test); - - casper.thenOpenAndWaitForPageLoad('signin', function testTitleAndUrl() { - test.assertTitle('Sign In - Test Blog', 'Ghost admin has incorrect title'); - test.assertUrlMatch(/ghost\/signin\/$/, 'Landed on the correct URL'); - }); - - casper.waitForOpaque('.gh-signin', - 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('.gh-alert', '[object Object]'); - test.assertTextExists('password is incorrect'); - test.assertDoesntExist('.form-group.error input[name="identification"]', 'email field was highlighted'); - test.assertExists('.form-group.error input[name="password"]', 'password field was not highlighted'); - }, function onTimeout() { - test.assert(false, 'We did not trip the login limit.'); - }); -}, true); - -CasperTest.begin('Can login to Ghost', 4, function suite(test) { - CasperTest.Routines.signout.run(test); - - casper.thenOpenAndWaitForPageLoad('signin', function testTitleAndUrl() { - test.assertTitle('Sign In - Test Blog', 'Ghost admin has incorrect title'); - test.assertUrlMatch(/ghost\/signin\/$/, 'Landed on the correct URL'); - }); - - casper.waitForOpaque('.gh-signin', function then() { - this.fillAndSave('#login', user); - }); - - casper.wait(2000); - - casper.waitForResource(/posts/, function testForDashboard() { - test.assertUrlMatch(/ghost\/\d+\/$/, 'Landed on the correct URL'); - test.assertExists('.gh-nav-main-content.active', 'Now we are on Content'); - }, function onTimeOut() { - test.fail('Failed to signin'); - }); -}, true); - -CasperTest.begin('Authenticated user is redirected', 6, function suite(test) { - CasperTest.Routines.signout.run(test); - - casper.thenOpenAndWaitForPageLoad('signin', function testTitleAndUrl() { - test.assertTitle('Sign In - Test Blog', 'Ghost admin has incorrect title'); - test.assertUrlMatch(/ghost\/signin\/$/, 'Landed on the correct URL'); - }); - - casper.waitForOpaque('' + - '.gh-signin', function then() { - this.fillAndSave('#login', user); - }); - - casper.wait(2000); - - casper.waitForResource(/posts/, function testForDashboard() { - test.assertUrlMatch(/ghost\/\d+\/$/, 'Landed on the correct URL'); - test.assertExists('.gh-nav-main-content.active', 'Now we are on Content'); - }, function onTimeOut() { - test.fail('Failed to signin'); - }); - - casper.thenOpenAndWaitForPageLoad('signin-authenticated', function testTitleAndUrl() { - test.assertUrlMatch(/ghost\/\d+\/$/, 'Landed on the correct URL'); - test.assertExists('.gh-nav-main-content.active', 'Now we are on Content'); - }, function onTimeOut() { - test.fail('Failed to redirect'); - }); -}, true); - -CasperTest.begin('Validates unknown email for sign-in', 5, function suite(test) { - CasperTest.Routines.signout.run(test); - - casper.thenOpenAndWaitForPageLoad('signin', function testTitleAndUrl() { - test.assertTitle('Sign In - Test Blog', 'Ghost admin has incorrect title'); - test.assertUrlMatch(/ghost\/signin\/$/, 'Landed on the correct URL'); - }); - - casper.waitForOpaque('.gh-signin', - function testUnknownEmail() { - this.fillAndSave('form.gh-signin', { - identification: 'unknown@ghost.org', - password: 'testing' - }); - }, - function onTimeout() { - test.fail('Login form didn\'t fade in.'); - }); - - casper.waitForText('no user with that email address', function onSuccess() { - test.assert(true, 'Unknown email error was shown'); - test.assertExists('.form-group.error input[name="identification"]', 'email field was not highlighted'); - test.assertDoesntExist('.form-group.error input[name="password"]', 'password field was highlighted'); - }, casper.failOnTimeout(test, 'Unknown email error was not shown')); -}, true); - -CasperTest.begin('Validates missing details for sign-in', 11, function suite(test) { - CasperTest.Routines.signout.run(test); - - casper.thenOpenAndWaitForPageLoad('signin', function testTitleAndUrl() { - test.assertTitle('Sign In - Test Blog', 'Ghost admin has incorrect title'); - test.assertUrlMatch(/ghost\/signin\/$/, 'Landed on the correct URL'); - }); - - casper.waitForOpaque('.gh-signin', - function testMissingEverything() { - this.fillAndSave('form.gh-signin', { - identification: '', - password: '' - }); - }, - function onTimeout() { - test.fail('Login form didn\'t fade in.'); - }); - - casper.waitForText('fill out the form', function onSuccess() { - test.assert(true, 'Missing details error was shown'); - test.assertExists('.form-group.error input[name="identification"]', 'email field was not highlighted'); - test.assertExists('.form-group.error input[name="password"]', 'password field was not highlighted'); - }, casper.failOnTimeout(test, 'Missing details error was not shown')); - - casper.then(function testMissingEmail() { - this.fillAndSave('form.gh-signin', { - identification: '', - password: 'testing' - }); - }); - - casper.waitForText('fill out the form', function onSuccess() { - test.assert(true, 'Missing details error was shown'); - test.assertExists('.form-group.error input[name="identification"]', 'email field was not highlighted'); - test.assertDoesntExist('.form-group.error input[name="password"]', 'password field was still highlighted'); - }, casper.failOnTimeout(test, 'Missing details error was not shown')); - - casper.then(function testMissingPassword() { - this.fillAndSave('form.gh-signin', { - identification: 'test@test.com', - password: '' - }); - }); - - casper.waitForText('fill out the form', function onSuccess() { - test.assert(true, 'Missing details error was shown'); - test.assertDoesntExist('.form-group.error input[name="identification"]', 'email field was still highlighted'); - test.assertExists('.form-group.error input[name="password"]', 'password field was not highlighted'); - }, casper.failOnTimeout(test, 'Missing details error was not shown')); -}, true); - -CasperTest.begin('Validates missing details for forgotten password', 5, function suite(test) { - CasperTest.Routines.signout.run(test); - - casper.thenOpenAndWaitForPageLoad('signin', function testTitleAndUrl() { - test.assertTitle('Sign In - Test Blog', 'Ghost admin has incorrect title'); - test.assertUrlMatch(/ghost\/signin\/$/, 'Landed on the correct URL'); - }); - - casper.waitForOpaque('.gh-signin', - function testMissingEmail() { - casper.fill('form.gh-signin', { - identification: '', - password: '' - }); - casper.click('.forgotten-link'); - }, - function onTimeout() { - test.fail('Login form didn\'t fade in.'); - }); - - casper.waitForText('enter an email address', function onSuccess() { - test.assert(true, 'Missing email error was shown'); - test.assertExists('.form-group.error input[name="identification"]', 'email field was not highlighted'); - test.assertDoesntExist('.form-group.error input[name="password"]', 'password field was highlighted'); - }, casper.failOnTimeout(test, 'Missing email error was not shown')); -}, true); - -CasperTest.begin('Validates unknown email for forgotten password', 5, function suite(test) { - CasperTest.Routines.signout.run(test); - - casper.thenOpenAndWaitForPageLoad('signin', function testTitleAndUrl() { - test.assertTitle('Sign In - Test Blog', 'Ghost admin has incorrect title'); - test.assertUrlMatch(/ghost\/signin\/$/, 'Landed on the correct URL'); - }); - - casper.waitForOpaque('.gh-signin', - function testMissingEmail() { - casper.fill('form.gh-signin', { - identification: 'unknown@ghost.org', - password: '' - }); - casper.click('.forgotten-link'); - }, - function onTimeout() { - test.fail('Login form didn\'t fade in.'); - }); - - casper.waitForText('no user with that email address', function onSuccess() { - test.assert(true, 'Unknown email error was shown'); - test.assertExists('.form-group.error input[name="identification"]', 'email field was not highlighted'); - test.assertDoesntExist('.form-group.error input[name="password"]', 'password field was highlighted'); - }, casper.failOnTimeout(test, 'Unknown email error was not shown')); -}, true); diff --git a/core/test/functional/client/signout_test.js b/core/test/functional/client/signout_test.js deleted file mode 100644 index 22b3a80e0c..0000000000 --- a/core/test/functional/client/signout_test.js +++ /dev/null @@ -1,32 +0,0 @@ -// # Signout Test -// Test that signout works correctly - -/*globals CasperTest, casper */ -CasperTest.begin('Ghost signout works correctly', 3, function suite(test) { - CasperTest.Routines.signout.run(test); - CasperTest.Routines.signin.run(test); - - casper.thenOpenAndWaitForPageLoad('root', function then() { - test.assertTitle('Content - Test Blog', 'Ghost admin has incorrect title'); - test.assertUrlMatch(/ghost\/\d+\/$/, 'Landed on the correct URL without signing in'); - }); - - casper.thenClick('.gh-nav-menu').waitFor(function checkOpaque() { - return this.evaluate(function () { - var menu = document.querySelector('.gh-nav-menu.open'); - return window.getComputedStyle(menu).getPropertyValue('display') === 'block' && - window.getComputedStyle(menu).getPropertyValue('opacity') === '1'; - }); - }); - - casper.captureScreenshot('user-menu-open.png'); - - casper.waitForSelector('.user-menu-signout'); - casper.thenClick('.user-menu-signout'); - - casper.waitForSelector('#login').then(function assertSuccess() { - test.assert(true, 'Got login screen'); - }); - - casper.captureScreenshot('user-menu-logout-clicked.png'); -}, true); diff --git a/core/test/functional/client/signup_test.js b/core/test/functional/client/signup_test.js deleted file mode 100644 index 1e3425a8c8..0000000000 --- a/core/test/functional/client/signup_test.js +++ /dev/null @@ -1,36 +0,0 @@ -// # Signup Test -// Test that signup works correctly - -/*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'); - // }); - - // 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); diff --git a/core/test/functional/client/tags_test.js b/core/test/functional/client/tags_test.js deleted file mode 100644 index 0c60fedc5a..0000000000 --- a/core/test/functional/client/tags_test.js +++ /dev/null @@ -1,126 +0,0 @@ -// # Settings Test -// Test the various tabs on the settings page - -/* - NOTE: These tests have been replaced with: - core/client/tests/acceptance/settings/tags-test.js - core/client/tests/integration/components/gh-tag-settings-form-test.js -*/ - -// CasperTest.begin('Tags screen is correct', 6, function suite(test) { -// casper.thenOpenAndWaitForPageLoad('settings.tags', function testTitleAndUrl() { -// test.assertTitle('Settings - Tags - Test Blog', 'Ghost admin has incorrect title'); -// test.assertUrlMatch(/ghost\/settings\/tags\/$/, 'Landed on the correct URL'); -// }); -// -// casper.then(function tagsScreenHasContent() { -// test.assertExists('.settings-tags .settings-tag', 'Has a tag'); -// test.assertSelectorHasText('.settings-tag .tag-title', 'Getting Started', 'Tag title is displayed'); -// test.assertSelectorHasText('.settings-tag .label', '/getting-started', 'Tag slug is displayed'); -// test.assertSelectorHasText('.settings-tag .tags-count', '1', 'Number of posts using tag is displayed'); -// }); -// }); -// -// CasperTest.begin('Tag creation', 16, function suite(test) { -// casper.thenOpenAndWaitForPageLoad('settings.tags'); -// -// casper.thenClick('.view-actions .btn-green'); -// -// casper.waitForOpaque('.tag-settings-pane', function onSuccess() { -// test.assert(true, 'tag settings menu is visible after clicking New Tag button'); -// }); -// -// casper.then(function enterName() { -// casper.sendKeys('#tag-name', 'Test Tag', {keepFocus: true}); -// }); -// casper.thenClick('#tag-description'); -// casper.waitForResource(/\/tags\//, function onSuccess() { -// test.assert(true, 'Losing focus on the name field triggered a save request'); -// }, function doneWaiting() { -// test.fail('Name field did not trigger a save request on blur'); -// }); -// -// casper.waitForText('/test-tag').then(function verifyUIUpdates() { -// test.assertField('url', 'test-tag'); -// test.assertSelectorHasText('.ghost-url-preview', '127.0.0.1:2369/tag/test-tag'); -// test.assertSelectorHasText('.settings-tags .tag-title', 'Test Tag'); -// test.assertSelectorHasText('.settings-tags .label', '/test-tag'); -// test.assertSelectorHasText('.settings-tags .tags-count', '0'); -// }); -// -// casper.then(function testMissingNameValidation() { -// casper.fill('.tag-settings-pane form', { -// name: '' -// }); -// casper.waitForText('You must specify a name for the tag.', function onSuccess() { -// test.assertExists('.form-group.error input[name="name"]'); -// test.assert(true, 'Error displayed for missing tag name'); -// }, function doneWaiting() { -// test.fail('Error not displayed for missing tag name'); -// }); -// }); -// -// casper.then(function testNameStartsWithCommaValidation() { -// casper.fill('.tag-settings-pane form', { -// name: ',, commas' -// }); -// casper.waitForText('Tag names can\'t start with commas.', function onSuccess() { -// test.assertExists('.form-group.error input[name="name"]'); -// test.assert(true, 'Error displayed for tag name starting with comma'); -// }, function doneWaiting() { -// test.fail('Error not displayed for tag name starting with comma'); -// }); -// }); -// -// casper.thenClick('.meta-data-button'); -// -// casper.waitForOpaque('.tag-meta-settings-pane', function onSuccess() { -// test.assert(true, 'tags meta settings menu is visible after clicking Meta Data button'); -// }); -// -// casper.then(function testMetaTitleValidation() { -// casper.fill('.tag-meta-settings-pane form', { -// meta_title: new Array(152).join('a') -// }); -// casper.waitForText('Meta Title cannot be longer than 150 characters.', function onSuccess() { -// test.assertExists('.form-group.error input[name="meta_title"]'); -// test.assert(true, 'Error displayed when meta title is too long'); -// }, function doneWaiting() { -// test.fail('Error not displayed when meta title is too long'); -// }); -// }); -// -// casper.then(function testMetaDescriptionValidation() { -// casper.fill('.tag-meta-settings-pane form', { -// meta_description: new Array(202).join('a') -// }); -// casper.waitForText('Meta Description cannot be longer than 200 characters.', function onSuccess() { -// test.assertExists('.form-group.error textarea[name="meta_description"]'); -// test.assert(true, 'Error displayed when meta description is too long'); -// }, function doneWaiting() { -// test.fail('Error not displayed when meta description is too long'); -// }); -// }); -// }); -// -// CasperTest.begin('Tag editing', 3, function suite(test) { -// casper.thenOpenAndWaitForPageLoad('settings.tags'); -// -// casper.thenClick('.settings-tags .settings-tag .tag-edit-button'); -// -// casper.waitForOpaque('.tag-settings-pane', function onSuccess() { -// test.assert(true, 'tag settings menu is visible after clicking tag'); -// }); -// -// casper.then(function testNameValidation() { -// casper.fill('.tag-settings-pane form', { -// name: '' -// }); -// casper.waitForText('You must specify a name for the tag.', function onSuccess() { -// test.assertExists('.form-group.error input[name="name"]'); -// test.assert(true, 'Error displayed for missing tag name'); -// }, function doneWaiting() { -// test.fail('Error not displayed for missing tag name'); -// }); -// }); -// }); diff --git a/core/test/functional/client/team_test.js b/core/test/functional/client/team_test.js deleted file mode 100644 index 5092f404b9..0000000000 --- a/core/test/functional/client/team_test.js +++ /dev/null @@ -1,316 +0,0 @@ -// # Settings Test - -/*globals CasperTest, casper */ - -// 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 = '.gh-nav-settings-general.active', - usersTabDetector = '.gh-nav-main-users.active'; - -CasperTest.begin('Team tab is correct', 4, function suite(test) { - // TODO make sure settings nav tests are refactored into app_test.js - - casper.then(function testSwitchingTabs() { - casper.thenClick('.gh-nav-main-users'); - casper.waitForSelector(usersTabDetector, function then() { - // assert that the right menu item is active - test.assert(true, 'Users link is active'); - test.assertDoesntExist('.gh-nav-settings-general.active', 'General link is not active'); - }, casper.failOnTimeout(test, 'waitForSelector `usersTabDetector` timed out')); - - casper.thenClick('.gh-nav-settings-general'); - casper.waitForSelector(generalTabDetector, function then() { - // assert that the right menu item is active - test.assert(true, 'General link is active'); - test.assertDoesntExist('.gh-nav-main-users.active', 'User link is not active'); - }, casper.failOnTimeout(test, 'waitForSelector `generalTabDetector` timed out')); - }); -}); - -CasperTest.begin('Users screen is correct', 9, function suite(test) { - casper.thenOpenAndWaitForPageLoad('settings.general'); - casper.thenTransitionAndWaitForScreenLoad('team', function canTransition() { - test.assert(true, 'Can transition to users screen from settings.general'); - test.assertUrlMatch(/ghost\/team\/$/, 'team transitions to correct url'); - }); - casper.then(function usersScreenHasContent() { - test.assertSelectorHasText('.team .user-list .user-list-title', 'Active users', 'active users text is correct'); - test.assertExists('.team .user-list .user-list-item', 'Has an active user'); - test.assertSelectorHasText('.team .user-list-item .name', 'Test User', 'test user text is correct'); - test.assertExists('.team .user-list-item .role-label.owner', 'First user has owner role displayed'); - - test.assertExists('.view-actions .btn-green', 'Add user button is on page.'); - }); - casper.thenClick('.view-actions .btn-green'); - casper.waitForOpaque('.invite-new-user .modal-content', function then() { - test.assertEval(function testOwnerRoleNotAnOption() { - var options = document.querySelectorAll('.invite-new-user #new-user-role select option'), - i = 0; - for (; i < options.length; i = i + 1) { - if (options[i].text === 'Owner') { - return false; - } - } - return true; - }, '"Owner" is not a role option for new users'); - }); - - // role options get loaded asynchronously; give them a chance to come in - casper.waitForSelector('.invite-new-user #new-user-role select option', function then() { - test.assertEval(function authorIsSelectedByDefault() { - var options = document.querySelectorAll('.invite-new-user #new-user-role select option'), - i = 0; - for (; i < options.length; i = i + 1) { - if (options[i].selected) { - return options[i].text === 'Author'; - } - } - return false; - }, 'The "Author" role is selected by default when adding a new user'); - }); -}); - -// ### User settings tests -CasperTest.begin('Can save settings', 5, function suite(test) { - casper.thenOpenAndWaitForPageLoad('team.user', function testTitleAndUrl() { - test.assertTitle('Team - User - Test Blog', 'Ghost Admin title is correct'); - test.assertUrlMatch(/ghost\/team\/test\/$/, 'team.user has 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('team/') !== -1) { - test.fail('Saving a settings pane triggered the user pane to save'); - } - } - - casper.then(function listenForRequests() { - casper.on('resource.requested', handleUserRequest); - }); - - casper.thenClick('.btn-blue'); - casper.waitForResource(/\/users\/\d\/\?include=roles/, function onSuccess() { - test.assert(true, 'Saving the user pane triggered a save request'); - }, function doneWaiting() { - test.fail('Saving the user pane did not trigger a save request'); - }); - - casper.then(function checkUserWasSaved() { - casper.removeListener('resource.requested', handleUserRequest); - }); - - casper.thenClick('.gh-nav-settings-general').then(function testTransitionToGeneral() { - casper.waitForSelector(generalTabDetector, function then() { - casper.on('resource.requested', handleSettingsRequest); - test.assertEval(function testGeneralIsActive() { - return document.querySelector('.gh-nav-settings-general').classList.contains('active'); - }, 'general tab is marked active'); - }, - casper.failOnTimeout(test, 'waitForSelector `generalTabDetector` timed out')); - }); - - casper.thenClick('.btn-blue'); - casper.waitForResource(/\/users\/\d\/\?include=roles/, function onSuccess() { - test.assert(true, 'Saving the user pane triggered a save request'); - }, function doneWaiting() { - test.fail('Saving the user pane did not trigger a save request'); - }); - - casper.then(function checkSettingsWereSaved() { - casper.removeListener('resource.requested', handleSettingsRequest); - }); - - CasperTest.beforeDone(function () { - casper.removeListener('resource.requested', handleUserRequest); - casper.removeListener('resource.requested', handleSettingsRequest); - }); -}); - -CasperTest.begin('User settings screen resets all whitespace slug to original value', 3, function suite(test) { - var slug; - - casper.thenOpenAndWaitForPageLoad('team.user', function testTitleAndUrl() { - test.assertTitle('Team - User - Test Blog', 'Ghost admin has incorrect title'); - test.assertUrlMatch(/ghost\/team\/test\/$/, 'Ghost doesn\'t require login this time'); - }); - - casper.then(function getSlugValue() { - slug = this.evaluate(function () { - return document.querySelector('#user-slug').value; - }); - }); - - casper.then(function changeSlugInput() { - casper.fillSelectors('.user-profile', { - '#user-slug': ' ' - }, false); - }); - - casper.thenClick('body'); - - casper.then(function checkSlugInputValue() { - casper.wait(250); - test.assertField('user', slug, 'user slug is correct'); - }); -}); - -CasperTest.begin('User settings screen change slug handles duplicate slug', 4, function suite(test) { - var slug; - - casper.thenOpenAndWaitForPageLoad('team.user', function testTitleAndUrl() { - test.assertTitle('Team - User - Test Blog', 'Ghost admin has incorrect title'); - test.assertUrlMatch(/ghost\/team\/test\/$/, 'Ghost doesn\'t require login this time'); - }); - - casper.then(function getSlugValue() { - slug = this.evaluate(function () { - return document.querySelector('#user-slug').value; - }); - }); - - casper.then(function changeSlug() { - casper.fillSelectors('.user-profile', { - '#user-slug': slug + '!' - }, false); - }); - - casper.thenClick('body'); - - casper.waitForResource(/\/slugs\/user\//, function testGoodResponse(resource) { - test.assert(resource.status < 400, 'resource.status < 400'); - }); - - casper.then(function checkSlugInputValue() { - test.assertField('user', slug, 'user slug is correct'); - }); -}); - -CasperTest.begin('User settings screen validates email', 4, function suite(test) { - var email; - - casper.thenOpenAndWaitForPageLoad('team.user', function testTitleAndUrl() { - test.assertTitle('Team - User - Test Blog', 'Ghost admin has incorrect title'); - test.assertUrlMatch(/ghost\/team\/test\/$/, 'Ghost doesn\'t require login this time'); - }); - - casper.then(function getEmail() { - email = this.evaluate(function () { - return document.querySelector('#user-email').value; - }); - }); - - casper.then(function setEmailToInvalid() { - var brokenEmail = email.replace('.', '-'); - this.fillAndSave('.user-profile', { - email: brokenEmail - }); - }); - - casper.waitForText('Please supply a valid email address', function onSuccess() { - test.assert(true, 'Invalid email error was shown'); - }, casper.failOnTimeout(test, 'Invalid email error was not shown')); - - casper.then(function resetEmailToValid() { - casper.fillSelectors('.user-profile', { - '#user-email': email - }, false); - }); - - casper.then(function checkEmailErrorWasCleared() { - test.assertTextDoesntExist('Please supply a valid email address', 'Invalid email error was not cleared'); - }); - - casper.thenClick('.view-actions .btn-blue'); - - casper.waitForResource(/users/); -}); - -// TODO: user needs to be loaded whenever it is edited (multi user) -CasperTest.begin('User settings screen shows remaining characters for Bio properly', 4, function suite(test) { - casper.thenOpenAndWaitForPageLoad('team.user', function testTitleAndUrl() { - test.assertTitle('Team - User - Test Blog', 'Ghost admin has incorrect title'); - test.assertUrlMatch(/ghost\/team\/test\/$/, 'Ghost doesn\'t require login this time'); - }); - - function getRemainingBioCharacterCount() { - return casper.getHTML('.word-count'); - } - - 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.thenOpenAndWaitForPageLoad('team.user', function testTitleAndUrl() { - test.assertTitle('Team - User - Test Blog', 'Ghost admin has incorrect title'); - test.assertUrlMatch(/ghost\/team\/test\/$/, 'Ghost doesn\'t require login this time'); - }); - - casper.then(function setBioToInvalid() { - this.fillSelectors('form.user-profile', { - '#user-bio': new Array(202).join('a') - }); - }); - - casper.thenClick('.view-actions .btn-blue'); - - casper.waitForText('Bio is too long', function onSuccess() { - test.assert(true, 'Bio too long error was shown'); - }, casper.failOnTimeout(test, 'Bio too long error was not shown')); -}); - -CasperTest.begin('Ensure user url field validation', 3, function suite(test) { - casper.thenOpenAndWaitForPageLoad('team.user', function testTitleAndUrl() { - test.assertTitle('Team - User - Test Blog', 'Ghost admin has incorrect title'); - test.assertUrlMatch(/ghost\/team\/test\/$/, 'Ghost doesn\'t require login this time'); - }); - - casper.then(function setWebsiteToInvalid() { - this.fillSelectors('form.user-profile', { - '#user-website': 'notaurl' - }); - }); - - casper.thenClick('.view-actions .btn-blue'); - - casper.waitForText('Website is not a valid url', function onSuccess() { - test.assert(true, 'Website invalid error was shown'); - }, casper.failOnTimeout(test, 'Website invalid error was not shown')); -}); - -CasperTest.begin('Ensure user location field length validation', 3, function suite(test) { - casper.thenOpenAndWaitForPageLoad('team.user', function testTitleAndUrl() { - test.assertTitle('Team - User - Test Blog', 'Ghost admin has incorrect title'); - test.assertUrlMatch(/ghost\/team\/test\/$/, 'Ghost doesn\'t require login this time'); - }); - - casper.then(function setLocationToInvalid() { - this.fillSelectors('form.user-profile', { - '#user-location': new Array(1002).join('a') - }); - }); - - casper.thenClick('.view-actions .btn-blue'); - - casper.waitForText('Location is too long', function onSuccess() { - test.assert(true, 'Location too long error was shown'); - }, casper.failOnTimeout(test, 'Location too long error was not shown')); -}); diff --git a/core/test/functional/setup/setup_test.js b/core/test/functional/setup/setup_test.js deleted file mode 100644 index a9ffba8607..0000000000 --- a/core/test/functional/setup/setup_test.js +++ /dev/null @@ -1,97 +0,0 @@ -// Test that setup works correctly - -/*global CasperTest, casper, email, user, password */ - -CasperTest.begin('Ghost setup fails properly', 11, function suite(test) { - casper.thenOpenAndWaitForPageLoad('setup', function then() { - test.assertUrlMatch(/ghost\/setup\/one\/$/, 'Landed on the correct URL'); - }); - - casper.thenTransitionAndWaitForScreenLoad('setup.two', function setupWithShortPassword() { - casper.fillAndAdd('#setup', {'blog-title': 'ghost', name: 'slimer', email: email, password: 'short'}); - }); - - // should now show a short password error - casper.waitForText('Password must be at least 8 characters long', function onSuccess() { - test.assert(true, 'Short password error was shown'); - }, casper.failOnTimeout(test, 'Short password error was not shown')); - - casper.then(function setupWithLongPassword() { - casper.fillAndAdd('#setup', {'blog-title': 'ghost', name: 'slimer', email: email, password: password}); - }); - - // This can take quite a long time - casper.wait(5000); - - casper.waitForScreenLoad('setup.three', function inviteUsers() { - casper.thenClick('.gh-flow-content .btn'); - }); - - casper.waitForText('No users to invite', function onSuccess() { - test.assert(true, 'Got error message'); - - test.assertExists('.gh-flow-content .btn-minor', 'Submit button is not minor'); - test.assertSelectorHasText('.gh-flow-content .btn', 'No users to invite', 'Submit button has wrong text'); - }, function onTimeout() { - test.assert(false, 'No error message for empty invitation list'); - }); - - casper.then(function fillInvalidEmail() { - casper.fill('form.gh-flow-invite', {users: 'test'}); - casper.thenClick('.gh-flow-content .btn'); - }); - - casper.waitForText('1 invalid email address', function onSuccess() { - test.assert(true, 'Got invalid email error'); - }, casper.failOnTimeout(test, 'Invalid email error not shown')); - - casper.then(function fillInvitationForm() { - casper.fill('form.gh-flow-invite', {users: 'test@example.com'}); - test.assertSelectorHasText('.gh-flow-content .btn', 'Invite 1 user', 'One invitation button text is incorrect'); - - test.assertExists('.gh-flow-content .btn-green', 'Submit button is not green'); - - casper.fill('form.gh-flow-invite', {users: 'test@example.com\ntest2@example.com'}); - test.assertSelectorHasText('.gh-flow-content .btn', 'Invite 2 users', 'Two invitations button text is incorrect'); - }); - - casper.thenClick('.gh-flow-content .btn'); - - // This might take awhile - casper.wait(5000); - - // These invitations will fail, because Casper can't send emails - casper.waitForSelector('.gh-alert', function onSuccess() { - test.assert(true, 'Got error notification'); - test.assertSelectorHasText('.gh-alert', 'Failed to send 2 invitations: test@example.com, test2@example.com'); - }, function onTimeout() { - test.assert(false, 'No error notification after invite.'); - }); -}, true, true); - -CasperTest.begin('Authenticated user is redirected', 6, function suite(test) { - casper.thenOpenAndWaitForPageLoad('signin', function testTitleAndUrl() { - test.assertTitle('Sign In - ghost', 'Ghost admin has incorrect title'); - test.assertUrlMatch(/ghost\/signin\/$/, 'Landed on the correct URL'); - }); - - casper.waitForOpaque('.gh-signin', function then() { - this.fillAndSave('#login', user); - }); - - casper.wait(2000); - - casper.waitForResource(/\d+/, function testForDashboard() { - test.assertUrlMatch(/ghost\/\d+\/$/, 'Landed on the correct URL'); - test.assertExists('.gh-nav-main-content.active', 'Now we are on Content'); - }, function onTimeOut() { - test.fail('Failed to signin'); - }); - - casper.thenOpenAndWaitForPageLoad('setup-authenticated', function testTitleAndUrl() { - test.assertUrlMatch(/ghost\/\d+\/$/, 'Landed on the correct URL'); - test.assertExists('.gh-nav-main-content.active', 'Now we are on Content'); - }, function onTimeOut() { - test.fail('Failed to redirect'); - }); -}, true, true); diff --git a/package.json b/package.json index a083bd0b29..121df1a764 100644 --- a/package.json +++ b/package.json @@ -106,7 +106,6 @@ "greenkeeper": { "ignore": [ "bower", - "bluebird", "glob", "lodash", "mysql",