From dd9aa0f873186c02921524dfb4b7b5825c226510 Mon Sep 17 00:00:00 2001 From: Kevin Ansfield Date: Wed, 19 Aug 2015 16:34:12 +0100 Subject: [PATCH] Add inline error handling when creating/editing tag closes #5684 - add inline error checking and display to tag name & meta data fields - add tests for tags screen --- core/client/app/controllers/settings/tags.js | 13 +-- .../templates/settings/tags/settings-menu.hbs | 37 +++--- core/test/functional/base.js | 4 + core/test/functional/client/tags_test.js | 110 ++++++++++++++++++ 4 files changed, 138 insertions(+), 26 deletions(-) create mode 100644 core/test/functional/client/tags_test.js diff --git a/core/client/app/controllers/settings/tags.js b/core/client/app/controllers/settings/tags.js index e1b9e01ac5..9ad1913e88 100644 --- a/core/client/app/controllers/settings/tags.js +++ b/core/client/app/controllers/settings/tags.js @@ -40,11 +40,6 @@ export default Ember.Controller.extend(PaginationMixin, SettingsMenuMixin, { } }), - showErrors: function (errors) { - errors = Ember.isArray(errors) ? errors : [errors]; - this.get('notifications').showErrors(errors); - }, - saveActiveTagProperty: function (propKey, newValue) { var activeTag = this.get('activeTag'), currentValue = activeTag.get(propKey), @@ -59,10 +54,10 @@ export default Ember.Controller.extend(PaginationMixin, SettingsMenuMixin, { activeTag.set(propKey, newValue); - this.get('notifications').closeNotifications(); - - activeTag.save().catch(function (errors) { - self.showErrors(errors); + activeTag.save().catch(function (error) { + if (error) { + self.notifications.showAPIError(error); + } }); }, diff --git a/core/client/app/templates/settings/tags/settings-menu.hbs b/core/client/app/templates/settings/tags/settings-menu.hbs index f4fd409179..ecd3ad1a82 100644 --- a/core/client/app/templates/settings/tags/settings-menu.hbs +++ b/core/client/app/templates/settings/tags/settings-menu.hbs @@ -1,6 +1,6 @@
{{#gh-tabs-manager selected="showSubview" class="settings-menu-container"}} -
+

Tag Settings

@@ -43,7 +44,7 @@
{{! .settings-menu-pane }} -
+
{{#gh-tab-pane}}
@@ -53,17 +54,19 @@
-
+ {{#gh-form-group errors=activeTag.errors property="meta_title"}} - {{gh-input class="gh-input" type="text" value=activeTagMetaTitleScratch focus-out="saveActiveTagMetaTitle"}} + {{gh-input id="meta-title" name="meta_title" type="text" value=activeTagMetaTitleScratch focus-out="saveActiveTagMetaTitle"}} + {{gh-error-message errors=activeTag.errors property="meta_title"}}

Recommended: 70 characters. You’ve used {{gh-count-down-characters activeTagMetaTitleScratch 70}}

-
+ {{/gh-form-group}} -
+ {{#gh-form-group errors=activeTag.errors property="meta_description"}} - {{gh-textarea class="gh-input" value=activeTagMetaDescriptionScratch focus-out="saveActiveTagMetaDescription"}} + {{gh-textarea id="meta-description" name="meta_description" value=activeTagMetaDescriptionScratch focus-out="saveActiveTagMetaDescription"}} + {{gh-error-message errors=activeTag.errors property="meta_description"}}

Recommended: 156 characters. You’ve used {{gh-count-down-characters activeTagMetaDescriptionScratch 156}}

-
+ {{/gh-form-group}}
diff --git a/core/test/functional/base.js b/core/test/functional/base.js index ed63ba9a27..1f443787b9 100644 --- a/core/test/functional/base.js +++ b/core/test/functional/base.js @@ -89,6 +89,10 @@ screens = { 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', diff --git a/core/test/functional/client/tags_test.js b/core/test/functional/client/tags_test.js new file mode 100644 index 0000000000..f50338102a --- /dev/null +++ b/core/test/functional/client/tags_test.js @@ -0,0 +1,110 @@ +// # Settings Test +// Test the various tabs on the settings page + +/*globals CasperTest, casper */ + +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', 14, 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 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'); + }); + }); + + 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'); + }); + }); +});