diff --git a/Gruntfile.js b/Gruntfile.js index b01d6d120e..0c578b7b39 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -98,15 +98,15 @@ var path = require('path'), }, all: { - src: ['core/test/**/*_spec.js'] + src: ['core/test/unit/**/*_spec.js'] }, api: { - src: ['core/test/**/api*_spec.js'] + src: ['core/test/unit/**/api*_spec.js'] }, perm: { - src: ['core/test/**/permissions_spec.js'] + src: ['core/test/unit/**/permissions_spec.js'] } }, diff --git a/core/test/functional/admin/01_login_test.js b/core/test/functional/admin/01_login_test.js new file mode 100644 index 0000000000..5434b788d2 --- /dev/null +++ b/core/test/functional/admin/01_login_test.js @@ -0,0 +1,47 @@ +/*globals casper, __utils__, url, user */ +casper.test.begin("Ghost admin will load login page", 2, function suite(test) { + + casper.test.filename = "admin_test.png"; + + casper.start(url + "ghost", function testTitleAndUrl() { + test.assertTitle("", "Ghost admin has no title"); + test.assertEquals(this.getCurrentUrl(), url + "ghost/login/", "Ghost requires login"); + }).viewport(1280, 1024); + + casper.run(function () { + test.done(); + }); +}); + + +casper.test.begin("Can login to Ghost", 3, function suite(test) { + + casper.test.filename = "login_test.png"; + + casper.start(url + "ghost/login/", function testTitle() { + test.assertTitle("", "Ghost admin has no title"); + }).viewport(1280, 1024); + + casper.waitFor(function checkOpaque() { + return this.evaluate(function () { + var loginBox = document.querySelector('.login-box'); + return window.getComputedStyle(loginBox).getPropertyValue('display') === "block" + && window.getComputedStyle(loginBox).getPropertyValue('opacity') === "1"; + }); + }, function then() { + this.fill("#login", user, true); + }); + + casper.wait(1000, function doneWait() { + this.echo("I've waited for 1 seconds."); + }); + + casper.then(function testForDashboard() { + this.test.assertExists("#global-header", "Global admin header is present"); + this.test.assertExists(".dashboard", "We're now on the dashboard"); + }); + + casper.run(function () { + test.done(); + }); +}); \ No newline at end of file diff --git a/core/test/functional/admin/02_dashboard_test.js b/core/test/functional/admin/02_dashboard_test.js new file mode 100644 index 0000000000..86063ce00a --- /dev/null +++ b/core/test/functional/admin/02_dashboard_test.js @@ -0,0 +1,30 @@ +/*globals casper, __utils__, url */ + +casper.test.begin("Ghost dashboard is correct", 13, function suite(test) { + + casper.test.filename = "dashboard_test.png"; + + casper.start(url + "ghost", function testTitleAndUrl() { + test.assertTitle("", "Ghost admin has no title"); + test.assertEquals(this.getCurrentUrl(), url + "ghost/", "Ghost doesn't require login this time"); + test.assertExists("#ghost", "Ghost is present"); + }).viewport(1280, 1024); + + casper.then(function testMenus() { + test.assertExists("#main-menu", "Main menu is present"); + test.assertSelectorHasText("#main-menu .dashboard a", "Dashboard"); + test.assertSelectorHasText("#main-menu .content a", "Content"); + test.assertSelectorHasText("#main-menu .editor a", "New Post"); + test.assertSelectorHasText("#main-menu .settings a", "Settings"); + + test.assertExists("#usermenu", "User menu is present"); + test.assertSelectorHasText("#usermenu .usermenu-profile a", "Your Profile"); + test.assertSelectorHasText("#usermenu .usermenu-help a", "Help / Support"); + test.assertSelectorHasText("#usermenu .usermenu-shortcuts a", "Keyboard Shortcuts"); + test.assertSelectorHasText("#usermenu .usermenu-signout a", "Sign Out"); + }); + + casper.run(function () { + test.done(); + }); +}); diff --git a/core/test/functional/admin/03_editor_test.js b/core/test/functional/admin/03_editor_test.js new file mode 100644 index 0000000000..84c47f0c25 --- /dev/null +++ b/core/test/functional/admin/03_editor_test.js @@ -0,0 +1,50 @@ +/*globals casper, __utils__, url, testPost */ + +casper.test.begin("Ghost editor is correct", 7, function suite(test) { + + casper.test.filename = "editor_test.png"; + + casper.start(url + "ghost/editor", function testTitleAndUrl() { + test.assertTitle("", "Ghost admin has no title"); + test.assertEquals(casper.getCurrentUrl(), url + "ghost/editor", "Ghost doesn't require login this time"); + test.assertExists(".entry-markdown", "Ghost editor is present"); + test.assertExists(".entry-preview", "Ghost preview is present"); + }).viewport(1280, 1024); + + function handleResource(resource) { + if (resource.url === 'http://localhost:2368/api/v0.1/posts') { + casper.removeListener('resource.received', handleResource); + casper.test.assertEquals(resource.status, 200, "Received correct response"); + } + } + + casper.then(function testCreatePost() { + // bind to resource events so we can get the API response + casper.on('resource.received', handleResource); + + casper.sendKeys('#entry-title', testPost.title); + casper.evaluate(function () { + var txt = document.querySelector('.CodeMirror-wrap textarea'); + txt.focus(); + // TODO: finish figuring out codemirror this works in chrome console.. but not in evaluate? + txt.value = "abcd"; + }); + + casper.click('.button-save'); + }); + + casper.wait(1000, function doneWait() { + this.echo("I've waited for 1 seconds."); + }); + + casper.then(function checkPostWasCreated() { + var urlRegExp = new RegExp("^" + url + "ghost\/editor\/[0-9]*"); + test.assertUrlMatch(urlRegExp, 'got an id on our URL'); + test.assertExists('.notification-success', 'got success notification'); + }); + + casper.run(function () { + casper.removeListener('resource.received', handleResource); + test.done(); + }); +}); diff --git a/core/test/functional/admin/04_content_test.js b/core/test/functional/admin/04_content_test.js new file mode 100644 index 0000000000..bbc60a5770 --- /dev/null +++ b/core/test/functional/admin/04_content_test.js @@ -0,0 +1,39 @@ +/*globals casper, __utils__, url, testPost */ + +casper.test.begin("Content screen is correct", 9, function suite(test) { + + casper.test.filename = "content_test.png"; + + casper.start(url + "ghost/content/", function testTitleAndUrl() { + test.assertTitle("", "Ghost admin has no title"); + test.assertEquals(this.getCurrentUrl(), url + "ghost/content/", "Ghost doesn't require login this time"); + }).viewport(1280, 1024); + + casper.then(function testViews() { + test.assertExists(".content-view-container", "Content main view is present"); + test.assertExists(".content-list-content", "Content list view is present"); + test.assertExists(".content-list-content li .entry-title", "Content list view has at least one item"); + test.assertExists(".content-preview", "Content preview is present"); + test.assertSelectorHasText(".content-list-content li:first-child h3", testPost.title, "first item is the post we created"); + }); + + casper.then(function testActiveItem() { + casper.test.assertEquals(casper.evaluate(function () { + return document.querySelector('.content-list-content li').className; + }), "active", "first item is active"); + + }).thenClick(".content-list-content li:nth-child(2) a", function then() { + casper.test.assertEquals(casper.evaluate(function () { + return document.querySelectorAll('.content-list-content li')[1].className; + }), "active", "second item is active"); + }); + + // TODO: finish testing delete +// casper.then(function testDeletePost() { +// casper.clickLabel(testPost.title, "h3"); +// }); + + casper.run(function () { + test.done(); + }); +}); \ No newline at end of file diff --git a/core/test/functional/admin/05_settings_test.js b/core/test/functional/admin/05_settings_test.js new file mode 100644 index 0000000000..8f41461806 --- /dev/null +++ b/core/test/functional/admin/05_settings_test.js @@ -0,0 +1,21 @@ +/*globals casper, __utils__, url */ + +casper.test.begin("Settings screen is correct", 3, function suite(test) { + + casper.test.filename = "settings_test.png"; + + casper.start(url + "ghost/settings", function testTitleAndUrl() { + test.assertTitle("", "Ghost admin has no title"); + test.assertEquals(this.getCurrentUrl(), url + "ghost/settings/general", "Ghost doesn't require login this time"); + }).viewport(1280, 1024); + + casper.then(function testViews() { + test.assertExists(".wrapper", "Settings main view is present"); + + // TODO: real settings tests + }); + + casper.run(function () { + test.done(); + }); +}); \ No newline at end of file diff --git a/core/test/functional/base.js b/core/test/functional/base.js new file mode 100644 index 0000000000..904bf139e9 --- /dev/null +++ b/core/test/functional/base.js @@ -0,0 +1,38 @@ +/*globals casper, __utils__ */ + +/** + * 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 --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 + * + * Requirements: + * you must have phantomjs 1.9.1 and casperjs 1.1.0-DEV installed in order for these tests to work + */ + +var host = casper.cli.options.url || 'localhost', + port = casper.cli.options.port || '2368', + email = casper.cli.options.email || 'ghost@tryghost.org', + password = casper.cli.options.password || 'Sl1m3r', + url = "http://" + host + ":" + port + "/", + user = { + email: email, + password: password + }, + testPost = {title: "A post title", content: "I am a post \n #With some content"}; + + +casper.test.on("fail", function captureFailure(failure) { + var filename = casper.test.filename || "casper_test_fail.png"; + casper.capture(new Date().getTime() + '_' + filename); +}); \ No newline at end of file diff --git a/core/test/ghost/api_permissions_spec.js b/core/test/unit/api_permissions_spec.js similarity index 100% rename from core/test/ghost/api_permissions_spec.js rename to core/test/unit/api_permissions_spec.js diff --git a/core/test/ghost/api_posts_spec.js b/core/test/unit/api_posts_spec.js similarity index 100% rename from core/test/ghost/api_posts_spec.js rename to core/test/unit/api_posts_spec.js diff --git a/core/test/ghost/api_settings_spec.js b/core/test/unit/api_settings_spec.js similarity index 100% rename from core/test/ghost/api_settings_spec.js rename to core/test/unit/api_settings_spec.js diff --git a/core/test/ghost/api_users_spec.js b/core/test/unit/api_users_spec.js similarity index 100% rename from core/test/ghost/api_users_spec.js rename to core/test/unit/api_users_spec.js diff --git a/core/test/ghost/errorHandling_spec.js b/core/test/unit/errorHandling_spec.js similarity index 100% rename from core/test/ghost/errorHandling_spec.js rename to core/test/unit/errorHandling_spec.js diff --git a/core/test/ghost/export_spec.js b/core/test/unit/export_spec.js similarity index 100% rename from core/test/ghost/export_spec.js rename to core/test/unit/export_spec.js diff --git a/core/test/ghost/fixtures/test.hbs b/core/test/unit/fixtures/test.hbs similarity index 100% rename from core/test/ghost/fixtures/test.hbs rename to core/test/unit/fixtures/test.hbs diff --git a/core/test/ghost/frontend_helpers_index_spec.js b/core/test/unit/frontend_helpers_index_spec.js similarity index 100% rename from core/test/ghost/frontend_helpers_index_spec.js rename to core/test/unit/frontend_helpers_index_spec.js diff --git a/core/test/ghost/ghost_spec.js b/core/test/unit/ghost_spec.js similarity index 98% rename from core/test/ghost/ghost_spec.js rename to core/test/unit/ghost_spec.js index 9d55549aff..5f7077a502 100644 --- a/core/test/ghost/ghost_spec.js +++ b/core/test/unit/ghost_spec.js @@ -7,7 +7,7 @@ var should = require('should'), Ghost = require('../../ghost'); describe("Ghost API", function () { - var testTemplatePath = 'core/test/ghost/fixtures/', + var testTemplatePath = 'core/test/unit/fixtures/', ghost; beforeEach(function () { diff --git a/core/test/ghost/helpers.js b/core/test/unit/helpers.js similarity index 100% rename from core/test/ghost/helpers.js rename to core/test/unit/helpers.js diff --git a/core/test/ghost/import_spec.js b/core/test/unit/import_spec.js similarity index 100% rename from core/test/ghost/import_spec.js rename to core/test/unit/import_spec.js diff --git a/core/test/ghost/permissions_spec.js b/core/test/unit/permissions_spec.js similarity index 100% rename from core/test/ghost/permissions_spec.js rename to core/test/unit/permissions_spec.js