mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-01-13 22:41:32 -05:00
Merge pull request #5687 from kevinansfield/fix-tags-validation
Add inline error handling and tests for tag creation/editing
This commit is contained in:
commit
55c07338d9
4 changed files with 138 additions and 26 deletions
|
@ -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);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<div>
|
||||
{{#gh-tabs-manager selected="showSubview" class="settings-menu-container"}}
|
||||
<div class="{{if isViewingSubview 'settings-menu-pane-out-left' 'settings-menu-pane-in'}} settings-menu settings-menu-pane">
|
||||
<div class="{{if isViewingSubview 'settings-menu-pane-out-left' 'settings-menu-pane-in'}} settings-menu settings-menu-pane tag-settings-pane">
|
||||
<div class="settings-menu-header">
|
||||
<h4>Tag Settings</h4>
|
||||
<button class="close icon-x settings-menu-header-action" {{action "closeMenus"}}>
|
||||
|
@ -10,25 +10,26 @@
|
|||
<div class="settings-menu-content">
|
||||
{{gh-uploader uploaded="setCoverImage" canceled="clearCoverImage" description="Add tag image" image=activeTag.image initUploader="setUploaderReference" tagName="section"}}
|
||||
<form>
|
||||
<div class="form-group">
|
||||
<label>Name</label>
|
||||
{{gh-input class="gh-input" type="text" value=activeTagNameScratch focus-out="saveActiveTagName"}}
|
||||
</div>
|
||||
{{#gh-form-group errors=activeTag.errors property="name"}}
|
||||
<label for="tag-name">Name</label>
|
||||
{{gh-input id="tag-name" name="name" type="text" value=activeTagNameScratch focus-out="saveActiveTagName"}}
|
||||
{{gh-error-message errors=activeTag.errors property="name"}}
|
||||
{{/gh-form-group}}
|
||||
|
||||
<div class="form-group">
|
||||
<label>URL</label>
|
||||
{{gh-input class="gh-input" type="text" value=activeTagSlugScratch focus-out="saveActiveTagSlug"}}
|
||||
<label for="tag-url">URL</label>
|
||||
{{gh-input id="tag-url" name="url" type="text" value=activeTagSlugScratch focus-out="saveActiveTagSlug"}}
|
||||
{{gh-url-preview prefix="tag" slug=activeTagSlugScratch tagName="p" classNames="description"}}
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Description</label>
|
||||
{{gh-textarea class="gh-input" value=activeTagDescriptionScratch focus-out="saveActiveTagDescription"}}
|
||||
<label for="tag-description">Description</label>
|
||||
{{gh-textarea id="tag-description" name="description" value=activeTagDescriptionScratch focus-out="saveActiveTagDescription"}}
|
||||
</div>
|
||||
|
||||
<ul class="nav-list nav-list-block">
|
||||
{{#gh-tab tagName="li" classNames="nav-list-item"}}
|
||||
<button type="button">
|
||||
<button type="button" class="meta-data-button">
|
||||
<b>Meta Data</b>
|
||||
<span>Extra content for SEO and social media.</span>
|
||||
</button>
|
||||
|
@ -43,7 +44,7 @@
|
|||
</div>
|
||||
</div>{{! .settings-menu-pane }}
|
||||
|
||||
<div class="{{if isViewingSubview 'settings-menu-pane-in' 'settings-menu-pane-out-right'}} settings-menu settings-menu-pane">
|
||||
<div class="{{if isViewingSubview 'settings-menu-pane-in' 'settings-menu-pane-out-right'}} settings-menu settings-menu-pane tag-meta-settings-pane">
|
||||
{{#gh-tab-pane}}
|
||||
<div class="settings-menu-header subview">
|
||||
<button {{action "closeSubview"}} class="back icon-arrow-left settings-menu-header-action"><span class="hidden">Back</span></button>
|
||||
|
@ -53,17 +54,19 @@
|
|||
|
||||
<div class="settings-menu-content">
|
||||
<form>
|
||||
<div class="form-group">
|
||||
{{#gh-form-group errors=activeTag.errors property="meta_title"}}
|
||||
<label for="meta-title">Meta Title</label>
|
||||
{{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"}}
|
||||
<p>Recommended: <b>70</b> characters. You’ve used {{gh-count-down-characters activeTagMetaTitleScratch 70}}</p>
|
||||
</div>
|
||||
{{/gh-form-group}}
|
||||
|
||||
<div class="form-group">
|
||||
{{#gh-form-group errors=activeTag.errors property="meta_description"}}
|
||||
<label for="meta-description">Meta Description</label>
|
||||
{{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"}}
|
||||
<p>Recommended: <b>156</b> characters. You’ve used {{gh-count-down-characters activeTagMetaDescriptionScratch 156}}</p>
|
||||
</div>
|
||||
{{/gh-form-group}}
|
||||
|
||||
<div class="form-group">
|
||||
<label>Search Engine Result Preview</label>
|
||||
|
|
|
@ -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',
|
||||
|
|
110
core/test/functional/client/tags_test.js
Normal file
110
core/test/functional/client/tags_test.js
Normal file
|
@ -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');
|
||||
});
|
||||
});
|
||||
});
|
Loading…
Add table
Reference in a new issue