0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-03-11 02:12:21 -05:00

Merge pull request #3805 from TryGhost/gui-update-yolo

Gui Update
This commit is contained in:
Hannah Wolfe 2014-08-18 19:20:40 +01:00
commit b1c77c70fd
46 changed files with 890 additions and 974 deletions

View file

@ -10,7 +10,7 @@
"ember-resolver": "git://github.com/stefanpenner/ember-jj-abrams-resolver.git#181251821cf513bb58d3e192faa13245a816f75e",
"ember-simple-auth": "0.6.4",
"fastclick": "1.0.0",
"ghost-ui": "0.8.13",
"ghost-ui": "~0.9",
"handlebars": "1.3.0",
"ic-ajax": "1.0.1",
"jquery": "1.11.0",

View file

@ -129,7 +129,7 @@ UploadUi = function ($dropzone, settings) {
$dropzone.append('<div class="js-fail failed" style="display: none">Something went wrong :(</div>');
}
if (!$dropzone.find('button.js-fail')[0]) {
$dropzone.append('<button class="js-fail button-add" style="display: none">Try Again</button>');
$dropzone.append('<button class="js-fail btn btn-green" style="display: none">Try Again</button>');
}
if (!$dropzone.find('a.image-url')[0]) {
$dropzone.append('<a class="image-url" title="Add image from URL"><span class="hidden">URL</span></a>');
@ -177,7 +177,7 @@ UploadUi = function ($dropzone, settings) {
$dropzone.find('div.description').before($url);
if (settings.editor) {
$dropzone.find('div.js-url').append('<button class="js-button-accept button-save">Save</button>');
$dropzone.find('div.js-url').append('<button class="btn btn-blue js-button-accept">Save</button>');
}
$dropzone.find('.js-button-accept').on('click', function () {

View file

@ -48,11 +48,11 @@ var ModalDialog = Ember.Component.extend({
}.property('type', 'style', 'animation'),
acceptButtonClass: function () {
return this.get('confirm.accept.buttonClass') ? this.get('confirm.accept.buttonClass') : 'button-add';
return this.get('confirm.accept.buttonClass') ? this.get('confirm.accept.buttonClass') : 'btn btn-green';
}.property('confirm.accept.buttonClass'),
rejectButtonClass: function () {
return this.get('confirm.reject.buttonClass') ? this.get('confirm.reject.buttonClass') : 'button-delete';
return this.get('confirm.reject.buttonClass') ? this.get('confirm.reject.buttonClass') : 'btn btn-red';
}.property('confirm.reject.buttonClass')
});

View file

@ -17,7 +17,7 @@ var UploadModal = ModalDialog.extend({
text: 'Cancel' // The reject button text
},
accept: {
buttonClass: 'button-save right',
buttonClass: 'btn btn-blue right',
text: 'Save', // The accept button texttext: 'Save'
func: function () {
var imageType = 'model.' + this.get('imageType');

View file

@ -20,11 +20,11 @@ var DeleteAllController = Ember.Controller.extend({
confirm: {
accept: {
text: 'Delete',
buttonClass: 'button-delete'
buttonClass: 'btn btn-red'
},
reject: {
text: 'Cancel',
buttonClass: 'button'
buttonClass: 'btn btn-default btn-minor'
}
}
});

View file

@ -24,11 +24,11 @@ var DeletePostController = Ember.Controller.extend({
confirm: {
accept: {
text: 'Delete',
buttonClass: 'button-delete'
buttonClass: 'btn btn-red'
},
reject: {
text: 'Cancel',
buttonClass: 'button'
buttonClass: 'btn btn-default btn-minor'
}
}
});

View file

@ -21,11 +21,11 @@ var DeleteUserController = Ember.Controller.extend({
confirm: {
accept: {
text: 'Delete User',
buttonClass: 'button-delete'
buttonClass: 'btn btn-red'
},
reject: {
text: 'Cancel',
buttonClass: 'button'
buttonClass: 'btn btn-default btn-minor'
}
}
});

View file

@ -47,11 +47,11 @@ var LeaveEditorController = Ember.Controller.extend({
confirm: {
accept: {
text: 'Leave',
buttonClass: 'button-delete'
buttonClass: 'btn btn-red'
},
reject: {
text: 'Stay',
buttonClass: 'button'
buttonClass: 'btn btn-default btn-minor'
}
}
});

View file

@ -39,12 +39,12 @@ var TransferOwnerController = Ember.Controller.extend({
confirm: {
accept: {
text: 'YEP - I\'M SURE',
buttonClass: 'button-delete'
text: 'Yep - I\'m sure',
buttonClass: 'btn btn-red'
},
reject: {
text: 'CANCEL',
buttonClass: 'button'
text: 'Cancel',
buttonClass: 'btn btn-default btn-minor'
}
}
});

View file

@ -83,7 +83,7 @@
<section class="settings-content active">
<header class="fade-in">
<button class="button-back">Back</button>
<button class="btn btn-default">Back</button>
<h2 class="title">About</h2>
</header>
@ -111,8 +111,8 @@
</p>
</div>
<div class="about-help">
<a href="http://docs.ghost.org" class="button-dark">User Documentation</a>
<a href="https://ghost.org/forum/" class="button-dark">Get Help With Ghost</a>
<a href="http://docs.ghost.org" class="btn btn-alt">User Documentation</a>
<a href="https://ghost.org/forum/" class="btn btn-alt">Get Help With Ghost</a>
</div>
</div>
</section>
@ -151,7 +151,7 @@
<p class="about-contributors-info">Ghost is built by an incredible group of contributors from all over the world. Here are just a few of the people who helped create the version youre using right now.</p>
<a href="https://github.com/TryGhost/Ghost/blob/master/CONTRIBUTING.md" class="about-get-involved button-save large">Find out how you can get involved</a>
<a href="https://github.com/TryGhost/Ghost/blob/master/CONTRIBUTING.md" class="about-get-involved btn btn-blue btn-lg">Find out how you can get involved</a>
<p class="about-copyright">
Copyright 2013 - 2014 Ghost Foundation, released under the <a href="https://github.com/TryGhost/Ghost/blob/master/LICENSE">MIT license</a>.<br>

View file

@ -1,22 +0,0 @@
<header class="floatingheader">
<button type="button" class="button-back" href="#">Back</button>
<button type="button" {{bind-attr class="featured:featured:unfeatured"}} title="Feature this post" {{action "toggleFeatured"}}>
<span class="hidden">Star</span>
</button>
<small>
<span class="status">{{#if isPublished}}Published{{else}}Written{{/if}}</span>
<span class="normal">by</span>
<span class="author">{{#if author.name}}{{author.name}}{{else}}{{author.email}}{{/if}}</span>
</small>
<section class="post-controls">
{{#link-to "editor.edit" this class="post-edit" title="Edit Post"}}
<span class="hidden">Edit Post</span>
{{/link-to}}
{{#gh-popover-button popoverName="post-settings-menu" classNames="post-settings" title="Post Settings"}}
<span class="hidden">Post Settings</span>
{{/gh-popover-button}}
{{#gh-popover name="post-settings-menu" classNames="post-settings-menu menu-drop-right"}}
{{render "post-settings-menu" model}}
{{/gh-popover}}
</section>
</header>

View file

@ -1,37 +1,54 @@
<header id="global-header" class="navbar">
<nav class="global-nav" role="navigation">
<a class="nav-item ghost-logo" {{bind-attr href=ghostPaths.blogRoot title=ghostPaths.blogRoot}}>
<div class="nav-label"><i class="icon-ghost"></i> <span>Visit blog</span> </div>
</a>
<button {{action "toggleSidebar" target="view"}} class="ghost-logo ghost-logo-button">
<span class="hidden">Ghost</span>
</button>
<a class="ghost-logo ghost-logo-link" {{bind-attr href=view.blogRoot}}>
<span class="hidden">Ghost</span>
{{#link-to "posts" classNames="nav-item nav-content"}}
<div class="nav-label"><i class="icon-content"></i> Content</div>
{{/link-to}}
{{#link-to "editor.new" classNames="nav-item nav-new"}}
<div class="nav-label"><i class="icon-add"></i> New Post</div>
{{/link-to}}
{{#unless session.user.isAuthor}}
{{#link-to "settings" classNames="nav-item nav-settings"}}
<div class="nav-label"><i class="icon-settings2"></i> Settings</div>
{{/link-to}}
{{/unless}}
{{! TODO: Mobile-only menu items
<a class="nav-item thing" href="#">
<div class="nav-label">Thing</div>
</a>
<a class="nav-item thing2" href="#">
<div class="nav-label">Thing2</div>
</a>
<nav id="global-nav" role="navigation">
<ul id="main-menu" >
{{gh-activating-list-item route="posts" title="Content" classNames="content js-close-sidebar"}}
{{gh-activating-list-item route="editor.new" title="New Post" classNames="editor js-close-sidebar"}}
{{#unless session.user.isAuthor}}
{{gh-activating-list-item route="settings" title="Settings" classNames="settings js-close-sidebar"}}
{{/unless}}
}}
<li id="usermenu" class="usermenu subnav">
{{#gh-popover-button popoverName="user-menu" classNames="dropdown"}}
{{#if session.user.image}}
<img class="avatar" {{bind-attr src="session.user.image"}} alt="Avatar" />
{{else}}
<img class="avatar" src="/shared/img/user-image.png" alt="Avatar" />
{{/if}}
<span class="name">{{session.user.name}}</span>
{{/gh-popover-button}}
{{#gh-popover tagName="ul" classNames="overlay" name="user-menu" closeOnClick="true"}}
<li class="usermenu-profile">{{#link-to "settings.users.user" session.user.slug}}Your Profile{{/link-to}}</li>
<li class="divider"></li>
<li class="usermenu-help"><a href="http://support.ghost.org/" target="_blank">Help / Support</a></li>
<li class="divider"></li>
<li class="usermenu-signout">{{#link-to "signout"}}Sign Out{{/link-to}}</li>
{{/gh-popover}}
</li>
</ul>
</nav>
</header>
<div class="nav-item user-menu" data-href="#">
{{#gh-popover-button popoverName="user-menu" tagName="div" classNames="nav-label"}}
{{#if session.user.image}}
<div class="image"><img {{bind-attr src="session.user.image"}} alt="{{session.user.name}}'s profile picture" /></div>
{{else}}
<div class="image"><img src="/shared/img/user-image.png" alt="Profile picture" /></div>
{{/if}}
<div class="name">
{{session.user.name}} <i class="icon-chevron-down"></i>
<small>Profile &amp; Settings</small>
</div>
{{/gh-popover-button}}
{{#gh-popover tagName="div" classNames="dropdown" name="user-menu" closeOnClick="true"}}
<ul class="dropdown-menu dropdown-triangle-top-right" role="menu">
<li role="presentation">{{#link-to "settings.users.user" session.user.slug classNames="dropdown-item user-menu-profile" role="menuitem" tabindex="-1"}}Your Profile{{/link-to}}</li>
<li role="presentation"><a class="dropdown-item user-menu-support" role="menuitem" tabindex="-1" href="http://support.ghost.org/">Help / Support</a></li>
<li class="divider"></li>
<li role="presentation">{{#link-to "signout" classNames="dropdown-item user-menu-signout" role="menuitem" tabindex="-1"}}Sign Out{{/link-to}}</li>
</ul>
{{/gh-popover}}
</div>{{! .user-menu }}
</nav>{{! .global-nav }}

View file

@ -1,19 +1,19 @@
<footer id="publish-bar">
<nav>
{{render 'post-tags-input'}}
{{render 'post-tags-input'}}
<div class="right">
<div class="right">
<section id="entry-controls" {{bind-attr class="isNew:unsaved"}}>
{{#gh-popover-button popoverName="post-settings-menu" classNames="post-settings" title="Post Settings"}}
<span class="hidden">Post Settings</span>
{{/gh-popover-button}}
{{#gh-popover name="post-settings-menu" classNames="post-settings-menu menu-right"}}
<section id="entry-controls" {{bind-attr class="isNew:unsaved"}}>
{{#gh-popover-button popoverName="post-settings-menu" classNames="post-settings" title="Post Settings"}}
<span class="hidden">Post Settings</span>
{{/gh-popover-button}}
{{#gh-popover name="post-settings-menu" classNames="dropdown post-settings-menu"}}
<div class="dropdown-menu dropdown-triangle-bottom-right">
{{render "post-settings-menu" model}}
{{/gh-popover}}
</section>
</div>
{{/gh-popover}}
</section>
{{view "editor-save-button" id="entry-actions"}}
</div>
</nav>
{{view "editor-save-button" id="entry-actions"}}
</div>
</footer>

View file

@ -1,11 +1,16 @@
<div id="container">
<a class="sr-only sr-only-focusable" href="#gh-main">Skip to main content</a>
{{#unless hideNav}}
{{partial "navbar"}}
{{/unless}}
<main role="main" id="main" {{bind-attr data-notification-count=topNotificationCount}}>
<main id="gh-main" class="viewport" role="main" {{bind-attr data-notification-count=topNotificationCount}}>
{{gh-notifications location="top" notify="topNotificationChange"}}
{{gh-notifications location="bottom"}}
{{outlet}}
</main>
{{outlet modal}}
</div>

View file

@ -1,4 +1,4 @@
<input data-url="upload" class="button-add" type="file" name="importfile" {{bind-attr accept=options.acceptEncoding}}>
<button type="submit" class="button-save" id="startupload" {{bind-attr disabled=uploadButtonDisabled}} {{action "upload"}}>
<input data-url="upload" class="btn btn-green" type="file" name="importfile" {{bind-attr accept=options.acceptEncoding}}>
<button type="submit" class="btn btn-blue" id="startupload" {{bind-attr disabled=uploadButtonDisabled}} {{action "upload"}}>
{{uploadButtonText}}
</button>

View file

@ -11,7 +11,7 @@
<fieldset>
<div class="form-group">
<label>Export</label>
<a class="button-save" {{action "exportData"}}>Export</a>
<a class="btn btn-blue" {{action "exportData"}}>Export</a>
<p>Export the blog settings and data.</p>
</div>
</fieldset>
@ -30,7 +30,7 @@
<fieldset>
<div class="form-group">
<label>Delete all Content</label>
<a href="javascript:void(0);" class="button-delete js-delete" {{action "openModal" "deleteAll"}}>Delete</a>
<a href="javascript:void(0);" class="btn btn-red js-delete" {{action "openModal" "deleteAll"}}>Delete</a>
<p>Delete all posts and tags from the database.</p>
</div>
</fieldset>
@ -39,7 +39,7 @@
<fieldset>
<div class="form-group">
<label>Send a test email</label>
<button type="submit" id="sendtestmail" class="button-save" {{action "sendTestEmail"}}>Send</button>
<button type="submit" id="sendtestmail" class="btn btn-blue" {{action "sendTestEmail"}}>Send</button>
<p>Sends a test email to your address.</p>
</div>
</fieldset>

View file

@ -1,14 +1,15 @@
<button type="button" {{action "save"}} {{bind-attr class="view.isDangerous:button-delete:button-save :js-publish-button" }}>
{{view.save-text}}
</button>
{{#gh-popover-button popoverName="post-save-menu" classNameBindings="open:active :options :up" title="Post Settings"}}
<span class="hidden">Post Settings</span>
{{/gh-popover-button}}
{{#gh-popover name="post-save-menu" closeOnClick="true" tagName="ul" classNames="editor-options overlay" publishTextBinding="view.publish-text" draftTextBinding="view.draft-text"}}
<li {{bind-attr class="controller.willPublish:active" }}>
<a {{action "setSaveType" "publish"}} href="#">{{view.publishText}}</a>
</li>
<li {{bind-attr class="controller.willPublish::active" }}>
<a {{action "setSaveType" "draft"}} href="#">{{view.draftText}}</a>
</li>
<button type="button" {{action "save"}} {{bind-attr class=":btn :btn-sm view.isDangerous:btn-red:btn-blue :js-publish-button" }}>{{view.save-text}}</button>
{{#gh-popover-button popoverName="post-save-menu" classNameBindings=":btn :btn-sm view.isDangerous:btn-red:btn-blue btnopen:active :dropdown-toggle :up"}}
<i class="options"></i>
<span class="sr-only">Toggle Settings Menu</span>
{{/gh-popover-button}}
{{#gh-popover name="post-save-menu" closeOnClick="true" tagName="div" classNames="dropdown editor-options" publishTextBinding="view.publish-text" draftTextBinding="view.draft-text"}}
<ul class="dropdown-menu dropdown-triangle-bottom-right">
<li class="post-save-publish" {{bind-attr class="controller.willPublish:active" }}>
<a {{action "setSaveType" "publish"}} href="#">{{view.publishText}}</a>
</li>
<li class="post-save-draft" {{bind-attr class="controller.willPublish::active" }}>
<a {{action "setSaveType" "draft"}} href="#">{{view.draftText}}</a>
</li>
</ul>
{{/gh-popover}}

View file

@ -1,27 +1,35 @@
<header>
<section class="box entry-title">
{{gh-trim-focus-input type="text" id="entry-title" placeholder="Your Post Title" value=titleScratch tabindex="1" focus=shouldFocusTitle}}
</section>
<header class="page-header">
<a class="menu-button" href="#"><span class="sr-only">Menu</span></a>
<h2 class="page-title">Editor</h2>
</header>
<section class="entry-markdown active">
<header class="floatingheader" id="entry-markdown-header">
<small>Markdown</small>
<a class="markdown-help" href="" {{action "openModal" "markdown"}}><span class="hidden">What is Markdown?</span></a>
<div class="page-content">
<header>
<section class="box entry-title">
{{gh-trim-focus-input type="text" id="entry-title" placeholder="Your Post Title" value=titleScratch tabindex="1" focus=shouldFocusTitle}}
</section>
</header>
<section id="entry-markdown-content" class="entry-markdown-content">
{{gh-codemirror value=scratch scrollInfo=view.markdownScrollInfo setCodeMirror="setCodeMirror"}}
</section>
</section>
<section class="entry-preview">
<header class="floatingheader" id="entry-preview-header">
<small>Preview <span class="entry-word-count js-entry-word-count">{{gh-count-words scratch}}</span></small>
</header>
<section class="entry-preview-content">
{{gh-markdown markdown=scratch scrollPosition=view.scrollPosition
uploadStarted="disableCodeMirror" uploadFinished="enableCodeMirror" uploadSuccess="handleImgUpload"}}
<section class="entry-markdown active">
<header class="floatingheader">
<small>Markdown</small>
<a class="markdown-help" href="" {{action "openModal" "markdown"}}><span class="hidden">What is Markdown?</span></a>
</header>
<section id="entry-markdown-content" class="entry-markdown-content">
{{gh-codemirror value=scratch scrollInfo=view.markdownScrollInfo setCodeMirror="setCodeMirror"}}
</section>
</section>
</section>
{{partial "publish-bar"}}
<section class="entry-preview">
<header class="floatingheader" id="entry-preview-header">
<small>Preview <span class="entry-word-count js-entry-word-count">{{gh-count-words scratch}}</span></small>
</header>
<section class="entry-preview-content">
{{gh-markdown markdown=scratch scrollPosition=view.scrollPosition
uploadStarted="disableCodeMirror" uploadFinished="enableCodeMirror" uploadSuccess="handleImgUpload"}}
</section>
</section>
{{partial "publish-bar"}}
</div>

View file

@ -4,6 +4,6 @@
{{gh-trim-focus-input value=email class="email" type="email" placeholder="Email Address" name="email"
autofocus="autofocus" autocapitalize="off" autocorrect="off"}}
</div>
<button class="button-save" type="submit" {{action "submit"}} {{bind-attr disabled=submitting}}>Send new password</button>
<button class="btn btn-blue" type="submit" {{action "submit"}} {{bind-attr disabled=submitting}}>Send new password</button>
</form>
</section>

View file

@ -1,47 +1,49 @@
<form>
<table class="plain">
<tbody>
<tr class="post-setting">
<td class="post-setting-label">
<label for="url">URL</label>
</td>
<td class="post-setting-field">
{{gh-blur-input class="post-setting-slug" id="url" value=slugValue name="post-setting-slug" action="updateSlug" placeholder=slugPlaceholder selectOnClick="true" stopEnterKeyDownPropagation="true"}}
</td>
</tr>
<tr class="post-setting">
<td class="post-setting-label">
<label for="pub-date">Pub Date</label>
</td>
<td class="post-setting-field">
{{gh-blur-input class="post-setting-date" value=publishedAtValue name="post-setting-date" action="setPublishedAt" placeholder=publishedAtPlaceholder stopEnterKeyDownPropagation="true"}}
</td>
</tr>
<tr class="post-setting">
<td class="post-setting-label">
<label for="post-setting-author">Author</label>
</td>
<td class="post-setting-field">
<table class="plain">
<tbody>
<tr class="post-setting">
<td class="post-setting-label">
<label for="url">URL</label>
</td>
<td class="post-setting-field">
{{gh-blur-input class="post-setting-slug" id="url" value=slugValue name="post-setting-slug" action="updateSlug" placeholder=slugPlaceholder selectOnClick="true" stopEnterKeyDownPropagation="true"}}
</td>
</tr>
<tr class="post-setting">
<td class="post-setting-label">
<label for="pub-date">Pub Date</label>
</td>
<td class="post-setting-field">
{{gh-blur-input class="post-setting-date" value=publishedAtValue name="post-setting-date" action="setPublishedAt" placeholder=publishedAtPlaceholder stopEnterKeyDownPropagation="true"}}
</td>
</tr>
<tr class="post-setting">
<td class="post-setting-label">
<label for="post-setting-author">Author</label>
</td>
<td class="post-setting-field">
<span class="gh-select">
{{view Ember.Select
name="post-setting-author"
content=authors
optionValuePath="content.id"
optionLabelPath="content.name"
selection=selectedAuthor}}
</span>
</td>
</tr>
<tr class="post-setting">
<td class="post-setting-label">
<label class="label" for="static-page">Static Page</label>
</td>
<td class="post-setting-item">
{{input type="checkbox" name="static-page" id="static-page" class="post-setting-static-page" checked=page}}
<label class="checkbox" for="static-page" {{action 'togglePage' bubbles="false"}}></label>
</td>
</tr>
</tbody>
</table>
{{view Ember.Select
name="post-setting-author"
content=authors
optionValuePath="content.id"
optionLabelPath="content.name"
selection=selectedAuthor}}
</span>
</td>
</tr>
<tr class="post-setting">
<td class="post-setting-label">
<label for="static-page" {{action "togglePage" bubbles="false"}}>Static Page</label>
</td>
<td class="post-setting-item">
<label class="checkbox" for="static-page" {{action "togglePage" bubbles="false"}}>
{{input type="checkbox" name="static-page" id="static-page" class="post-setting-static-page" checked=page}}
<span class="input-toggle-component"></span>
</label>
</td>
</tr>
</tbody>
</table>
</form>
<button type="button" class="delete" {{action "openModal" "delete-post" this}}>Delete This Post</button>

View file

@ -1,35 +1,42 @@
<section class="content-list js-content-list">
<header class="floatingheader">
<section class="content-filter">
<small>All Posts</small>
</section>
{{#link-to "editor.new" class="button button-add" title="New Post"}}<span class="hidden">New Post</span>{{/link-to}}
</header>
{{#view "content-list-content-view" tagName="section"}}
<ol class="posts-list">
{{#each itemController="posts/post" itemView="post-item-view" itemTagName="li"}}
{{#link-to "posts.post" this class="permalink" title="Edit this post"}}
<h3 class="entry-title">{{title}}</h3>
<section class="entry-meta">
<span class="status">
{{#if isPublished}}
{{#if page}}
<span class="page">Page</span>
{{else}}
<time datetime="{{unbound published_at}}" class="date published">
Published {{gh-format-timeago published_at}}
</time>
{{/if}}
{{else}}
<span class="draft">Draft</span>
{{/if}}
</span>
</section>
{{/link-to}}
{{/each}}
</ol>
{{/view}}
</section>
<section class="content-preview js-content-preview">
{{outlet}}
</section>
<header class="page-header">
<a class="menu-button" href="#"><span class="sr-only">Menu</span></a>
<h2 class="page-title">Content</h2>
</header>
<div class="page-content">
<section class="content-list js-content-list">
<header class="floatingheader">
<section class="content-filter">
<small>All Posts</small>
</section>
{{#link-to "editor.new" class="btn btn-green" title="New Post"}}<span class="hidden">New Post</span>{{/link-to}}
</header>
{{#view "content-list-content-view" tagName="section"}}
<ol class="posts-list">
{{#each itemController="posts/post" itemView="post-item-view" itemTagName="li"}}
{{#link-to "posts.post" this class="permalink" title="Edit this post"}}
<h3 class="entry-title">{{title}}</h3>
<section class="entry-meta">
<span class="status">
{{#if isPublished}}
{{#if page}}
<span class="page">Page</span>
{{else}}
<time datetime="{{unbound published_at}}" class="date published">
Published {{gh-format-timeago published_at}}
</time>
{{/if}}
{{else}}
<span class="draft">Draft</span>
{{/if}}
</span>
</section>
{{/link-to}}
{{/each}}
</ol>
{{/view}}
</section>
<section class="content-preview js-content-preview">
{{outlet}}
</section>
</div>

View file

@ -1,6 +1,6 @@
<div class="no-posts-box">
<div class="no-posts">
<h3>You Haven't Written Any Posts Yet!</h3>
{{#link-to "editor.new"}}<button type="button" class="button-add large" title="New Post">Write a new Post</button>{{/link-to}}
{{#link-to "editor.new"}}<button type="button" class="btn btn-green btn-lg" title="New Post">Write a new Post</button>{{/link-to}}
</div>
</div>

View file

@ -1,4 +1,17 @@
{{partial "floating-header"}}
<header class="post-preview-header">
<button type="button" class="btn btn-default btn-back" href="#">Back</button>
<button type="button" {{bind-attr class="featured:featured:unfeatured"}} title="Feature this post" {{action "toggleFeatured"}}>
<span class="hidden">Star</span>
</button>
<small>
<span class="status">{{#if isPublished}}Published{{else}}Written{{/if}}</span>
<span class="normal">by</span>
<span class="author">{{#if author.name}}{{author.name}}{{else}}{{author.email}}{{/if}}</span>
</small>
<section class="post-controls">
{{#link-to "editor.edit" this class="btn btn-default post-edit"}} Edit{{/link-to}}
</section>
</header>
{{#view "content-preview-content-view" tagName="section"}}
<div class="wrapper">

View file

@ -6,6 +6,6 @@
<div class="password-wrap">
{{input value=passwords.ne2Password class="password" type="password" placeholder="Confirm Password" name="ne2password" }}
</div>
<button class="button-save" type="submit" {{bind-attr disabled='submitButtonDisabled'}}>Reset Password</button>
<button class="btn btn-blue" type="submit" {{bind-attr disabled='submitButtonDisabled'}}>Reset Password</button>
</form>
</section>

View file

@ -1,19 +1,21 @@
<aside class="settings-sidebar" role="complementary">
<header>
<h1 class="title">Settings</h1>
</header>
<header class="page-header">
<a class="menu-button" href="#"><span class="sr-only">Menu</span></a>
<h2 class="page-title">Settings</h2>
</header>
<div class="page-content">
<nav class="settings-menu">
<ul>
{{#unless session.user.isAuthor}}
{{#unless session.user.isEditor}}
{{gh-activating-list-item route="settings.general" title="General" classNames="general"}}
{{gh-activating-list-item route="settings.general" title="General" classNames="settings-menu-general"}}
{{/unless}}
{{gh-activating-list-item route="settings.users" title="Users" classNames="users"}}
{{gh-activating-list-item route="settings.users" title="Users" classNames="settings-menu-users"}}
{{/unless}}
</ul>
</nav>
</aside>
{{outlet}}
{{outlet}}
</div>

View file

@ -1,5 +1,5 @@
<header class="settings-content-header">
{{#link-to 'settings' class='button-back button'}}Back{{/link-to}}
<header>
{{#link-to 'settings' class='btn btn-default'}}Back{{/link-to}}
<h2 class="title">Apps</h2>
</header>
@ -16,7 +16,7 @@
{{#if package}}{{package.name}} - {{package.version}}{{else}}{{name}} - package.json missing :({{/if}}
</td>
<td>
<button type="button" {{action toggleApp this}} {{bind-attr class=":js-button-active activeClass:button-delete inactiveClass:button-add activeClass:js-button-deactivate"}}>
<button type="button" {{action toggleApp this}} {{bind-attr class=":btn :js-button-active activeClass:btn-red inactiveClass:btn-green activeClass:js-button-deactivate"}}>
{{buttonText}}
</button>
</td>

View file

@ -1,13 +1,9 @@
<header class="settings-content-header">
<h2 class="title">General</h2>
<div class="settings-header-inner">
{{#link-to 'settings' class='button-back button'}}Back{{/link-to}}
<section class="page-actions">
<button type="button" class="button-save" {{action "save"}}>Save</button>
</section>
</div>
<header class="settings-view-header">
{{#link-to "settings" class="btn btn-default btn-back"}}Back{{/link-to}}
<h2 class="page-title">General</h2>
<section class="page-actions">
<button type="button" class="btn btn-blue" {{action "save"}}>Save</button>
</section>
</header>
<section class="content settings-general">
@ -30,25 +26,27 @@
</div>
</fieldset>
<div class="form-group">
<label for="blog-logo">Blog Logo</label>
{{#if logo}}
<button type="button" class="js-modal-logo" {{action "openModal" "upload" this "logo"}}><img id="blog-logo" {{bind-attr src=logo}} alt="logo"></button>
{{else}}
<button type="button" class="button-add js-modal-logo" {{action "openModal" "upload" this "logo"}}>Upload Image</button>
{{/if}}
<p>Display a sexy logo for your publication</p>
</div>
<div class="form-group">
<label for="blog-cover">Blog Cover</label>
{{#if cover}}
<button type="button" class="js-modal-cover" {{action "openModal" "upload" this "cover"}}><img id="blog-cover" {{bind-attr src=cover}} alt="cover photo"></button>
{{else}}
<button type="button" class="button-add js-modal-cover" {{action "openModal" "upload" this "cover"}}>Upload Image</button>
{{/if}}
<p>Display a cover image on your site</p>
</div>
<div class="form-group">
<label for="blog-logo">Blog Logo</label>
{{#if logo}}
<button type="button" class="js-modal-logo" {{action "openModal" "upload" this "logo"}}><img id="blog-logo" {{bind-attr src=logo}} alt="logo"></button>
{{else}}
<button type="button" class="btn btn-green js-modal-logo" {{action "openModal" "upload" this "logo"}}>Upload Image</button>
{{/if}}
<p>Display a sexy logo for your publication</p>
</div>
<div class="form-group">
<label for="blog-cover">Blog Cover</label>
{{#if cover}}
<button type="button" class="js-modal-cover" {{action "openModal" "upload" this "cover"}}><img id="blog-cover" {{bind-attr src=cover}} alt="cover photo"></button>
{{else}}
<button type="button" class="btn btn-green js-modal-cover" {{action "openModal" "upload" this "cover"}}>Upload Image</button>
{{/if}}
<p>Display a cover image on your site</p>
</div>
<fieldset>
<div class="form-group">
<label for="email-address">Email Address</label>
@ -64,9 +62,11 @@
<div class="form-group for-checkbox">
<label for="permalinks">Dated Permalinks</label>
{{input id="permalinks" name="general[permalinks]" type="checkbox" checked=isDatedPermalinks}}
<label class="checkbox" for="permalinks"></label>
<p>Include the date in your post URLs</p>
<label class="checkbox" for="permalinks">
{{input id="permalinks" name="general[permalinks]" type="checkbox" checked=isDatedPermalinks}}
<span class="input-toggle-component"></span>
<p>Include the date in your post URLs</p>
</label>
</div>
<div class="form-group for-select">
@ -83,7 +83,6 @@
</span>
<p>Select a theme for your blog</p>
</div>
</fieldset>
</form>
</section>

View file

@ -1,8 +1,14 @@
<header class="settings-content-header">
{{#link-to 'settings' class='button-back button'}}Back{{/link-to}}
<h2 class="title">Users</h2>
<script>
$(document).ready(function() {
$('body').addClass('settings-view');
});
</script>
<header class="settings-view-header">
{{#link-to "settings" class="btn btn-default btn-back"}}Back{{/link-to}}
<h2 class="page-title">Users</h2>
<section class="page-actions">
<button class="button-add" {{action "openModal" "invite-new-user"}} >New&nbsp;User</button>
<button class="btn btn-green" {{action "openModal" "invite-new-user"}} >New&nbsp;User</button>
</section>
</header>

View file

@ -1,34 +1,26 @@
<header class="settings-content-header user-settings-header">
<h2 class="hidden">Your Profile</h2>
<div class="settings-header-inner">
{{#link-to 'settings' class='button-back button'}}Back{{/link-to}}
<section class="page-actions page-actions-alt">
{{#unless session.user.isAuthor}}
{{#link-to "settings.users" class="button has-icon users-back" tagName="button"}}<i class="icon-chevron-left"></i>Users{{/link-to}}
{{/unless}}
</section>
<section class="page-actions">
{{#if view.userActionsAreVisible}}
<header class="settings-subview-header">
{{#unless session.user.isAuthor}}
{{#link-to "settings.users" class="button has-icon users-back" tagName="button"}}<i class="icon-chevron-left"></i>Users{{/link-to}}
{{/unless}}
<h2 class="page-title">{{user.name}}</h2>
<section class="page-actions">
{{#if view.userActionsAreVisible}}
<span class="dropdown">
{{#gh-popover-button popoverName="user-actions-menu" classNames="button only-has-icon user-actions-cog" title="User Actions"}}
<i class="icon-settings"></i>
<span class="hidden">User Settings</span>
{{/gh-popover-button}}
{{#gh-popover name="user-actions-menu" classNames="user-actions-menu menu-drop-right"}}
{{#gh-popover name="user-actions-menu" tagName="ul" classNames="user-actions-menu dropdown-menu dropdown-triangle-top-right"}}
{{render "user-actions-menu" model}}
{{/gh-popover}}
{{/if}}
<button class="button-save" {{action "save"}}>Save</button>
</section>
</div>
</span>
{{/if}}
<button class="btn btn-blue" {{action "save"}}>Save</button>
</section>
</header>
<section class="content settings-user no-padding">
<section class="content settings-user">
<header class="user-profile-header">
<img id="user-cover" class="cover-image" {{bind-attr src=cover title=coverTitle}} />
@ -122,7 +114,7 @@
{{input value=user.ne2Password type="password" id="user-new-password-verification"}}
</div>
<div class="form-group">
<button type="button" class="button-delete button-change-password" {{action "password"}}>Change Password</button>
<button type="button" class="btn btn-red button-change-password" {{action "password"}}>Change Password</button>
</div>
</fieldset>

View file

@ -31,7 +31,7 @@
<p>Must be at least 8 characters</p>
</div>
<footer>
<button type="submit" class="button-add large" {{action "setup"}} {{bind-attr disabled=submitting}}>Ok, Let's Do This</button>
<button type="submit" class="btn btn-green btn-lg" {{action "setup"}} {{bind-attr disabled=submitting}}>Ok, Let's Do This</button>
</footer>
</form>
</div>

View file

@ -7,7 +7,7 @@
<div class="password-wrap">
{{input class="password" type="password" placeholder="Password" name="password" value=password}}
</div>
<button class="button-save" type="submit" {{action "validateAndAuthenticate"}} {{bind-attr disabled=submitting}}>Log in</button>
<button class="btn btn-blue" type="submit" {{action "validateAndAuthenticate"}} {{bind-attr disabled=submitting}}>Log in</button>
<section class="meta">
{{#link-to 'forgotten' class="forgotten-password"}}Forgotten password?{{/link-to}}
</section>

View file

@ -26,7 +26,7 @@
<p>Must be at least 8 characters</p>
</div>
<footer>
<button type="submit" class="button-add large" {{action "signup"}} {{bind-attr disabled=submitting}}>Create Account</button>
<button type="submit" class="btn btn-green btn-lg" {{action "signup"}} {{bind-attr disabled=submitting}}>Create Account</button>
</footer>
</form>
</div>

View file

@ -1,6 +1,6 @@
{{#if view.parentView.canMakeOwner}}
<a href="javascript:void(0);" {{action "openModal" "transfer-owner" this}}>Make Owner</a>
<li><button {{action "openModal" "transfer-owner" this}}>Make Owner</button></li>
{{/if}}
{{#if view.parentView.deleteUserActionIsVisible}}
<a href="javascript:void(0);" {{action "openModal" "delete-user" this}} class="delete">Delete User</a>
<li><button {{action "openModal" "delete-user" this}} class="delete">Delete User</button></li>
{{/if}}

View file

@ -1,8 +1,7 @@
var EditorSaveButtonView = Ember.View.extend({
templateName: 'editor-save-button',
tagName: 'section',
classNames: ['js-publish-splitbutton'],
classNameBindings: ['isDangerous:splitbutton-delete:splitbutton-save'],
classNames: ['splitbtn js-publish-splitbutton'],
//Tracks whether we're going to change the state of the post on save
isDangerous: function () {

View file

@ -23,7 +23,7 @@ var PostsView = Ember.View.extend({
});
// ### Hide content preview
$('.manage').on('click', '.content-preview .button-back', function (event) {
$('.manage').on('click', '.content-preview .btn .btn-default', function (event) {
responsiveAction(event, '(max-width: 800px)', function () {
self.send('hideContentPreview');
});

View file

@ -1,7 +1,6 @@
import {mobileQuery} from 'ghost/utils/mobile';
var SettingsView = Ember.View.extend({
classNames: ['wrapper'],
// used by SettingsContentBaseView and on resize to mobile from desktop
showSettingsContent: function () {
if (mobileQuery.matches) {

View file

@ -10,6 +10,7 @@
<meta name="HandheldFriendly" content="True" />
<meta name="MobileOptimized" content="320" />
<meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1, maximum-scale=1, minimal-ui" />
<meta name="pinterest" content="nopin" />
<meta http-equiv="cleartype" content="on" />
<meta name="apple-mobile-web-app-capable" content="yes" />
@ -36,4 +37,4 @@
{{{ghost_script_tags}}}
</body>
</html>
</html>

View file

@ -57,64 +57,64 @@ var DEBUG = false, // TOGGLE THIS TO GET MORE SCREENSHOTS
screens = {
'root': {
url: 'ghost/',
linkSelector: '#main-menu > li.content a',
selector: '#main-menu .content.active'
linkSelector: '.nav-content',
selector: '.nav-content.active'
},
'content': {
url: 'ghost/content/',
linkSelector: '#main-menu > li.content a',
selector: '#main-menu .content.active'
linkSelector: '.nav-content',
selector: '.nav-content.active'
},
'editor': {
url: 'ghost/editor/',
linkSelector: '#main-menu > li.editor a',
linkSelector: '.nav-new',
selector: '#entry-title'
},
'settings': {
url: 'ghost/settings/',
linkSelector: '#main-menu > li.settings a',
selector: '.settings-content'
linkSelector: '.nav-settings',
selector: '.nav-settings.active'
},
'settings.general': {
url: 'ghost/settings/general',
selector: '.settings-content .settings-general'
selector: '.settings-menu-general.active'
},
'settings.users': {
url: 'ghost/settings/users',
linkSelector: '.settings-menu li.users a',
selector: '.settings-content .settings-users'
linkSelector: '.settings-menu-users a',
selector: '.settings-menu-users.active'
},
'settings.users.user': {
url: 'ghost/settings/users/test-user',
linkSelector: '#user-menu li.usermenu-profile a',
selector: '.settings-content .settings-user'
linkSelector: '.user-menu-profile',
selector: '.user-profile'
},
'signin': {
url: 'ghost/signin/',
selector: '.button-save'
selector: '.btn-blue'
},
'signin-authenticated': {
url: 'ghost/signin/',
//signin with authenticated user redirects to posts
selector: '#main-menu .content .active'
selector: '.nav-content.active'
},
'signout': {
url: 'ghost/signout/',
linkSelector: '#usermenu li.usermenu-signout a',
// When no user exists we get redirected to setup which has button-add
selector: '.button-save, .button-add'
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: '.button-save'
selector: '.btn-blue'
},
'setup': {
url: 'ghost/setup/',
selector: '.button-add'
selector: '.btn-green'
},
'setup-authenticated': {
url: 'ghost/setup/',
selector: '#main-menu .content a.active'
selector: '.nav-content.active'
}
};
@ -162,7 +162,7 @@ casper.waitForTransparent = function (classname, then, timeout) {
// ### Then Open And Wait For Page Load
// Always wait for the `#main` element as some indication that the ember app has loaded.
// 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);
@ -191,21 +191,21 @@ casper.failOnTimeout = function (test, 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
// 'button-save'. This method handles that smoothly.
// 'btn-blue'. This method handles that smoothly.
casper.fillAndSave = function (selector, data) {
casper.then(function doFill() {
casper.fill(selector, data, false);
casper.thenClick('.button-save');
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
// 'button-add'. This method handles that smoothly.
// 'btn-green'. This method handles that smoothly.
casper.fillAndAdd = function (selector, data) {
casper.then(function doFill() {
casper.fill(selector, data, false);
casper.thenClick('.button-add');
casper.thenClick('.btn-green');
});
};
@ -276,7 +276,7 @@ casper.captureScreenshot = function (filename, debugOnly) {
casper.test.on('fail', function captureFailure() {
casper.captureScreenshot(casper.test.filename || 'casper_test_fail.png', false);
casper.then(function () {
console.log(casper.getHTML());
// console.log(casper.getHTML());
casper.exit(1);
});
});
@ -432,7 +432,7 @@ CasperTest.Routines = (function () {
});
if (currentState !== state) {
casper.thenClick('#permalinks');
casper.thenClick('.button-save');
casper.thenClick('.btn-blue');
casper.captureScreenshot('saving.png');
@ -455,12 +455,12 @@ CasperTest.Routines = (function () {
if (publish) {
// Open the publish options menu;
casper.thenClick('.js-publish-splitbutton .options.up');
casper.thenClick('.js-publish-splitbutton .dropdown-toggle');
casper.waitForOpaque('.js-publish-splitbutton .open');
// Select the publish post button
casper.thenClick('.js-publish-splitbutton li:first-child a');
casper.thenClick('.post-save-publish a');
casper.waitForSelectorTextChange('.js-publish-button', function onSuccess() {
casper.thenClick('.js-publish-button');

View file

@ -3,68 +3,67 @@
/*globals CasperTest, casper */
CasperTest.begin('Admin navigation bar is correct', 29, function suite(test) {
CasperTest.begin('Admin navigation bar is correct', 28, function suite(test) {
casper.thenOpenAndWaitForPageLoad('root', function testTitleAndUrl() {
test.assertTitle('Ghost Admin', 'Ghost admin has no title');
test.assertUrlMatch(/ghost\/\d+\/$/, 'Landed on the correct URL');
});
casper.then(function testNavItems() {
var logoHref = this.getElementAttribute('.ghost-logo-link', 'href'),
contentHref = this.getElementAttribute('#main-menu li.content a', 'href'),
editorHref = this.getElementAttribute('#main-menu li.editor a', 'href'),
settingsHref = this.getElementAttribute('#main-menu li.settings a', 'href');
var logoHref = this.getElementAttribute('.ghost-logo', 'href'),
contentHref = this.getElementAttribute('.nav-content', 'href'),
editorHref = this.getElementAttribute('.nav-new', 'href'),
settingsHref = this.getElementAttribute('.nav-settings', 'href');
// Logo
test.assertExists('.ghost-logo-button', 'Ghost logo home page button exists');
test.assertExists('.ghost-logo-link', 'Ghost logo home page link exists');
test.assertExists('.ghost-logo', 'Ghost logo home page link exists');
test.assertEquals(logoHref, '/', 'Ghost logo link href is correct');
// Content
test.assertExists('#main-menu li.content a', 'Content nav item exists');
test.assertSelectorHasText('#main-menu li.content a', 'Content', 'Content nav item has correct text');
test.assertExists('.nav-content', 'Content nav item exists');
test.assertSelectorHasText('.nav-content', 'Content', 'Content nav item has correct text');
test.assertEquals(contentHref, '/ghost/', 'Content href is correct');
test.assertExists('#main-menu li.content.active', 'Content nav item is not marked active');
test.assertExists('.nav-content.active', 'Content nav item is not marked active');
// Editor
test.assertExists('#main-menu li.editor a', 'Editor nav item exists');
test.assertSelectorHasText('#main-menu li.editor a', 'New Post', 'Editor nav item has correct text');
test.assertExists('.nav-new', 'Editor nav item exists');
test.assertSelectorHasText('.nav-new', 'New Post', 'Editor nav item has correct text');
test.assertEquals(editorHref, '/ghost/editor/', 'Editor href is correct');
test.assertDoesntExist('#main-menu li.editor.active', 'Editor nav item is not marked active');
test.assertDoesntExist('.nav-new.active', 'Editor nav item is not marked active');
// Settings
test.assertExists('#main-menu li.settings a', 'Settings nav item exists');
test.assertSelectorHasText('#main-menu li.settings a', 'Settings', 'Settings nav item has correct text');
test.assertExists('.nav-settings', 'Settings nav item exists');
test.assertSelectorHasText('.nav-settings', 'Settings', 'Settings nav item has correct text');
test.assertEquals(settingsHref, '/ghost/settings/', 'Settings href is correct');
test.assertDoesntExist('#main-menu li.settings.active', 'Settings nav item is marked active');
test.assertDoesntExist('.nav-settings.active', 'Settings nav item is marked active');
});
casper.then(function testUserMenuNotVisible() {
test.assertExists('#usermenu', 'User menu nav item exists');
test.assertNotExists('#usermenu ul.overlay.open', 'User menu should not be visible');
test.assertExists('.user-menu', 'User menu nav item exists');
test.assertNotExists('.user-menu .dropdown.open', 'User menu should not be visible');
});
casper.thenClick('#usermenu button');
casper.waitForSelector('#usermenu ul.overlay.open', function then() {
var profileHref = this.getElementAttribute('#usermenu li.usermenu-profile a', 'href'),
helpHref = this.getElementAttribute('#usermenu li.usermenu-help a', 'href'),
signoutHref = this.getElementAttribute('#usermenu li.usermenu-signout a', 'href');
casper.thenClick('.user-menu .nav-label');
casper.waitForSelector('.user-menu .dropdown.open', function then() {
var profileHref = this.getElementAttribute('.user-menu-profile', 'href'),
helpHref = this.getElementAttribute('.user-menu-support', 'href'),
signoutHref = this.getElementAttribute('.user-menu-signout', 'href');
test.assertVisible('#usermenu ul.overlay', 'User menu should be visible');
test.assertVisible('.user-menu .dropdown-menu', 'User menu should be visible');
test.assertExists('#usermenu li.usermenu-profile a', 'Profile menu item exists');
test.assertSelectorHasText('#usermenu li.usermenu-profile a', 'Your Profile',
test.assertExists('.user-menu-profile', 'Profile menu item exists');
test.assertSelectorHasText('.user-menu-profile', 'Your Profile',
'Profile menu item has correct text');
test.assertEquals(profileHref, '/ghost/settings/users/' + newUser.slug + '/', 'Profile href is correct');
test.assertExists('#usermenu li.usermenu-help a', 'Help menu item exists');
test.assertSelectorHasText('#usermenu li.usermenu-help a', 'Help / Support', 'Help menu item has correct text');
test.assertExists('.user-menu-support', 'Help menu item exists');
test.assertSelectorHasText('.user-menu-support', 'Help / Support', 'Help menu item has correct text');
test.assertEquals(helpHref, 'http://support.ghost.org/', 'Help href is correct');
test.assertExists('#usermenu li.usermenu-signout a', 'Sign Out menu item exists');
test.assertSelectorHasText('#usermenu li.usermenu-signout a', 'Sign Out', 'Signout menu item has correct text');
test.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 #usermenu ul.overlay failed'));
}, casper.failOnTimeout(test, 'WaitForSelector .user-menu .dropdown failed'));
});
CasperTest.begin('Can transition to the editor and back', 6, function suite(test) {

View file

@ -3,7 +3,7 @@
/*globals CasperTest, casper, testPost, newUser */
CasperTest.begin('Content screen is correct', 21, function suite(test) {
CasperTest.begin('Content screen is correct', 17, function suite(test) {
// First, create a sample post for testing (this should probably be a routine)
CasperTest.Routines.createTestPost.run(false);
@ -16,9 +16,9 @@ CasperTest.begin('Content screen is correct', 21, function suite(test) {
casper.then(function testViews() {
test.assertExists('.content-view-container', 'Content main view is present');
test.assertExists('.content-list-content', 'Content list view is present');
test.assertExists('.content-list .floatingheader a.button.button-add', 'add new post button exists');
test.assertExists('.content-list .floatingheader a.btn.btn-green', 'add new post button exists');
test.assertEquals(
this.getElementAttribute('.content-list .floatingheader a.button.button-add', 'href'),
this.getElementAttribute('.content-list .floatingheader a.btn.btn-green', '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');
@ -41,20 +41,6 @@ CasperTest.begin('Content screen is correct', 21, function suite(test) {
test.assertExists('.content-preview a.post-edit', 'edit post button exists');
});
casper.then(function testPostSettingsMenu() {
test.assertExists('.content-preview button.post-settings', 'post settings button exists');
this.click('.content-preview button.post-settings');
});
casper.waitUntilVisible('.post-settings-menu', function onSuccess() {
test.assert(true, 'post settings menu should be visible after clicking post-settings icon');
});
casper.then(function postSettingsMenuItems() {
test.assertExists('.post-settings-menu .post-setting-static-page', 'post settings static page exists');
test.assertExists('.post-settings-menu button.delete', 'post settings delete this post 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');
@ -66,7 +52,7 @@ CasperTest.begin('Content screen is correct', 21, function suite(test) {
});
});
CasperTest.begin('Content list shows correct post status', 7, function testStaticPageStatus(test) {
CasperTest.begin('Content list shows correct post status', 5, function testStaticPageStatus(test) {
CasperTest.Routines.createTestPost.run(true);
// Begin test
@ -80,7 +66,7 @@ CasperTest.begin('Content list shows correct post status', 7, function testStati
// Test for status of 'Published'
casper.then(function checkStatus() {
test.assertSelectorHasText('.content-list-content li.active .entry-meta .status time', 'Published',
test.assertSelectorHasText('.content-list-content .active .published', 'Published',
'status is present and labeled as published');
});
@ -94,68 +80,26 @@ CasperTest.begin('Content list shows correct post status', 7, function testStati
);
});
// Change post to static page
casper.thenClick('button.post-settings');
casper.thenClick('.post-edit');
casper.waitForSelector('#entry-title');
casper.waitUntilVisible('.post-settings-menu', function onSuccess() {
test.assert(true, 'post settings menu should be visible after clicking post-settings icon');
});
// 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');
// });
// });
casper.thenClick('.post-settings-menu .post-setting-static-page + label');
casper.waitForSelector('.content-list-content li .entry-meta .status .page', function waitForSuccess() {
test.assertSelectorHasText('.content-list-content li .entry-meta .status .page', 'Page', 'status is Page');
}, function onTimeout() {
test.assert(false, 'status did not change');
});
});
CasperTest.begin('Delete post modal', 7, function testDeleteModal(test) {
// Create a post that can be deleted
CasperTest.Routines.createTestPost.run(false);
// Begin test
casper.thenOpenAndWaitForPageLoad('content', function testTitleAndUrl() {
test.assertTitle('Ghost Admin', 'Title is "Ghost Admin"');
test.assertUrlMatch(/ghost\/\d+\/$/, 'Landed on the correct URL');
});
// Open post settings menu
casper.thenClick('.content-preview button.post-settings');
casper.waitForOpaque('.content-preview .post-settings-menu.open');
casper.thenClick('.post-settings-menu button.delete');
casper.waitUntilVisible('#modal-container', function onSuccess() {
test.assertSelectorHasText(
'.modal-content .modal-header',
'Are you sure you want to delete this post?',
'delete modal has correct text');
});
casper.thenClick('.js-button-reject');
casper.waitWhileVisible('#modal-container', function onSuccess() {
test.assert(true, 'clicking cancel should close the delete post modal');
});
// Test delete
casper.thenClick('.content-preview button.post-settings');
casper.thenClick('.post-settings-menu button.delete');
casper.waitForSelector('#modal-container .modal-content', function onSuccess() {
test.assertExists('.modal-content .js-button-accept', 'delete button exists');
// Delete the post
this.click('.modal-content .js-button-accept');
casper.waitForSelector('.notification-success', function onSuccess() {
test.assert(true, 'Got success notification from delete post');
test.assertSelectorHasText('.notification-message', 'Your post has been deleted.');
}, function onTimeout() {
test.fail('No success notification from delete post');
});
});
});
// TODO: Implement this test... much needed!
//CasperTest.begin('Infinite scrolling', 2, function suite(test) {
@ -208,118 +152,4 @@ CasperTest.begin('Posts can be marked as featured', 8, function suite(test) {
}, function onTimeout() {
test.assert(false, 'Couldn\'t unfeature post.');
});
});
CasperTest.begin('Post url can be changed', 5, function suite(test) {
// Create a sample post
CasperTest.Routines.createTestPost.run(false);
// Begin test
casper.thenOpenAndWaitForPageLoad('content', function testTitleAndUrl() {
test.assertTitle('Ghost Admin', 'Title is "Ghost Admin"');
test.assertUrlMatch(/ghost\/\d+\/$/, 'Landed on the correct URL');
});
casper.thenClick('button.post-settings');
casper.waitUntilVisible('.post-settings-menu', function onSuccess() {
test.assert(true, 'post settings menu should be visible after clicking post-settings icon');
});
// Test change permalink
casper.then(function () {
this.fillSelectors('.post-settings-menu form', {
'#url': 'new-url'
}, false);
this.click('button.post-settings');
});
casper.waitForResource(/\/posts\/\d+\/\?include=tags/, function testGoodResponse(resource) {
test.assert(400 > resource.status);
});
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.assertEqual(slugVal, 'new-url');
});
});
CasperTest.begin('Post published date can be changed', 5, function suite(test) {
// Create a sample post
CasperTest.Routines.createTestPost.run(false);
// Begin test
casper.thenOpenAndWaitForPageLoad('content', function testTitleAndUrl() {
test.assertTitle('Ghost Admin', 'Title is "Ghost Admin"');
test.assertUrlMatch(/ghost\/\d+\/$/, 'Landed on the correct URL');
});
casper.thenClick('button.post-settings');
casper.waitUntilVisible('.post-settings-menu', function onSuccess() {
test.assert(true, 'post settings menu should be visible after clicking post-settings icon');
});
// Test change published date
casper.then(function () {
this.fillSelectors('.post-settings-menu form', {
'.post-setting-date': '22 May 14 @ 23:39'
}, false);
this.click('button.post-settings');
});
casper.waitForResource(/\/posts\/\d+\/\?include=tags/, function testGoodResponse(resource) {
test.assert(400 > resource.status);
});
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.assertEqual(dateVal, '22 May 14 @ 23:39');
});
});
CasperTest.begin('Post can be changed to static page', 7, function suite(test) {
// Create a sample post
CasperTest.Routines.createTestPost.run(false);
// Begin test
casper.thenOpenAndWaitForPageLoad('content', function testTitleAndUrl() {
test.assertTitle('Ghost Admin', 'Title is "Ghost Admin"');
test.assertUrlMatch(/ghost\/\d+\/$/, 'Landed on the correct URL');
});
casper.thenClick('.content-preview button.post-settings');
casper.waitForOpaque('.content-preview .post-settings-menu.open', function onSuccess() {
test.assert(true, 'post settings should be visible after clicking post-settings icon');
});
casper.thenClick('.post-settings-menu .post-setting-static-page + label');
casper.waitForResource(/\/posts\/\d+\/\?include=tags/, function waitForSuccess(resource) {
test.assert(400 > resource.status);
});
//Reload the page so the html can update to have the checked attribute
casper.thenOpenAndWaitForPageLoad('content', function testTitleAndUrl() {
test.assertExists('.post-setting-static-page[checked=checked]', 'can turn on static page');
});
casper.thenClick('.post-settings-menu .post-setting-static-page + label');
casper.waitForResource(/\/posts\/\d+\/\?include=tags/, function waitForSuccess(resource) {
test.assert(400 > resource.status);
});
//Reload so html can be updated to not have the checked attribute
casper.thenOpenAndWaitForPageLoad('content', function testTitleAndUrl() {
test.assertDoesntExist('.post-setting-static-page[checked=checked]', 'can turn off static page');
});
});

View file

@ -88,11 +88,11 @@ CasperTest.begin('Ghost editor functions correctly', 19, function suite(test) {
// Part 5: Editor global shortcuts
casper.then(function tryZenShortcut() {
casper.sendKeys('#main', 'z', {modifiers: 'alt+shift'});
casper.sendKeys('.page-content', 'z', {modifiers: 'alt+shift'});
});
casper.waitForSelector('.editor.zen', function then() {
casper.waitForTransparent('#global-header', function then() {
casper.waitForTransparent('.global-nav', function then() {
test.assert(true, 'header becomes transparent');
});
casper.waitForTransparent('#publish-bar', function then() {
@ -101,11 +101,11 @@ CasperTest.begin('Ghost editor functions correctly', 19, function suite(test) {
});
casper.then(function tryZenShortcut() {
casper.sendKeys('#main', 'z', {modifiers: 'alt+shift'});
casper.sendKeys('.page-content', 'z', {modifiers: 'alt+shift'});
});
casper.waitWhileSelector('.editor.zen', function then() {
casper.waitForOpaque('#global-header', function then() {
casper.waitForOpaque('.global-nav', function then() {
test.assert(true, 'header becomes opaque');
});
casper.waitForOpaque('#publish-bar', function then() {
@ -162,7 +162,7 @@ CasperTest.begin('Image Uploads', 17, function suite(test) {
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 .button-save.js-button-accept', 'Image URL accept button 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');
});
@ -206,7 +206,7 @@ CasperTest.begin('Image Uploads', 17, function suite(test) {
var imageURL = 'http://www.random.url';
casper.waitForSelector('.image-uploader-url', function onSuccess() {
casper.sendKeys('.image-uploader-url input.url.js-upload-url', imageURL);
casper.thenClick('.js-button-accept.button-save');
casper.thenClick('.js-button-accept.btn-blue');
});
casper.waitForSelector('.entry-preview .js-drop-zone.pre-image-uploader', function onSuccess() {
@ -243,168 +243,7 @@ casper.thenOpenAndWaitForPageLoad('editor', function testTitleAndUrl() {
});
});
CasperTest.begin('Post settings menu', 30, function suite(test) {
casper.thenOpenAndWaitForPageLoad('editor', function testTitleAndUrl() {
test.assertTitle('Ghost Admin', 'Ghost admin has no title');
test.assertUrlMatch(/ghost\/editor\/$/, 'Landed on the correct URL');
});
casper.then(function () {
test.assertExists('#publish-bar button.post-settings', 'icon toggle should exist');
test.assertNotVisible('#publish-bar .post-settings-menu', 'popup menu should not be visible at startup');
test.assertExists('.post-settings-menu input#url', 'url field exists');
test.assertExists('.post-settings-menu input.post-setting-date', 'publication date field exists');
test.assertExists('.post-settings-menu input.post-setting-static-page', 'static page checkbox field exists');
test.assertExists('.post-settings-menu button.delete', 'delete post button exists');
});
casper.thenClick('#publish-bar button.post-settings');
casper.waitUntilVisible('#publish-bar .post-settings-menu', function onSuccess() {
test.assert(true, 'popup menu should be visible after clicking post-settings icon');
test.assertNotVisible(
'.post-settings-menu button.delete', 'delete post button shouldn\'t be visible on unsaved drafts'
);
});
casper.thenClick('#publish-bar button.post-settings');
casper.waitWhileVisible('#publish-bar .post-settings-menu', function onSuccess() {
test.assert(true, 'popup menu should not be visible after clicking post-settings icon');
});
// 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.waitForSelector('.notification-success', function waitForSuccess() {
test.assert(true, 'got success notification');
test.assertSelectorHasText('.notification-success', 'Saved.');
casper.click('.notification-success .close');
}, function onTimeout() {
test.assert(false, 'No success notification');
});
casper.waitWhileSelector('.notification-success');
casper.thenClick('#publish-bar button.post-settings');
casper.waitUntilVisible('#publish-bar .post-settings-menu', function onSuccess() {
test.assert(true, 'post settings menu should be visible after clicking post-settings icon');
});
casper.waitUntilVisible('.post-settings-menu button.delete', function onSuccess() {
test.assert(true, 'delete post button should be visible for saved drafts');
});
// Test change permalink
casper.then(function () {
this.fillSelectors('.post-settings-menu form', {
'#url': 'new-url-editor'
}, false);
this.click('#publish-bar button.post-settings');
});
casper.waitForSelector('.notification-success', function waitForSuccess() {
test.assert(true, 'got success notification');
test.assertSelectorHasText('.notification-success', 'Permalink successfully changed to new-url-editor.');
casper.click('.notification-success .close');
}, function onTimeout() {
test.assert(false, 'No success notification');
});
casper.waitWhileSelector('.notification-success', function () {
test.assert(true, 'notification cleared.');
test.assertNotVisible('.notification-success', 'success notification should not still exist');
});
// Test change pub date
casper.thenClick('#publish-bar button.post-settings');
casper.waitUntilVisible('#publish-bar .post-settings-menu .post-setting-date', function onSuccess() {
test.assert(true, 'post settings menu should be visible after clicking post-settings icon');
});
casper.then(function () {
this.fillSelectors('.post-settings-menu form', {
'.post-setting-date': '10 May 14 @ 00:17'
}, false);
this.click('#publish-bar button.post-settings');
});
casper.waitForResource(/\/posts\/\d+\/\?include=tags/, function testGoodResponse(resource) {
test.assert(400 > resource.status);
});
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.assertEqual(dateVal, '10 May 14 @ 00:17');
});
// Test static page toggling
casper.thenClick('.post-settings-menu .post-setting-static-page + label');
casper.waitForResource(/\/posts\/\d+\/\?include=tags/, function testGoodResponse(resource) {
test.assert(400 > resource.status);
});
casper.then(function staticPageIsCheckedTest() {
var checked = casper.evaluate(function evalCheckedProp() {
return document.querySelector('.post-setting-static-page').checked
});
test.assert(checked, 'Turned post into static page.');
});
casper.thenClick('.post-settings-menu .post-setting-static-page + label');
casper.waitForResource(/\/posts\/\d+\/\?include=tags/, function testGoodResponse(resource) {
test.assert(400 > resource.status);
});
casper.then(function staticPageIsCheckedTest() {
var checked = casper.evaluate(function evalCheckedProp() {
return document.querySelector('.post-setting-static-page').checked
});
test.assert(!checked, 'Turned page into post.');
});
// Test Delete Post Modal
casper.thenClick('.post-settings-menu button.delete');
casper.waitUntilVisible('#modal-container', function onSuccess() {
test.assert(true, 'delete post modal is visible after clicking delete');
test.assertSelectorHasText(
'#modal-container .modal-header',
'Are you sure you want to delete this post?',
'delete post modal header has correct text');
});
casper.thenClick('#modal-container .js-button-reject');
casper.waitWhileVisible('#modal-container', function onSuccess() {
test.assert(true, 'clicking cancel should close the delete post modal');
});
casper.thenClick('#publish-bar button.post-settings');
casper.thenClick('.post-settings-menu button.delete');
casper.waitUntilVisible('#modal-container', function onSuccess() {
casper.thenClick('#modal-container .js-button-accept');
});
casper.waitForUrl(/ghost\/\d+\/$/, function onSuccess() {
test.assert(true, 'clicking the delete post button should bring us to the content page');
});
});
CasperTest.begin('Publish menu - new post', 11, function suite(test) {
CasperTest.begin('Publish menu - new post', 10, function suite(test) {
casper.thenOpenAndWaitForPageLoad('editor', function testTitleAndUrl() {
test.assertTitle('Ghost Admin', 'Ghost admin has no title');
test.assertUrlMatch(/ghost\/editor\/$/, 'Landed on the correct URL');
@ -413,9 +252,8 @@ CasperTest.begin('Publish menu - new post', 11, function suite(test) {
// ... check default option status, label, class
casper.then(function () {
test.assertExists('.js-publish-splitbutton');
test.assertExists('.js-publish-splitbutton.splitbutton-save');
test.assertExists('.js-publish-button');
test.assertExists('.js-publish-button.button-save');
test.assertExists('.js-publish-button.btn-blue');
test.assertSelectorHasText('.js-publish-button', 'Save Draft');
});
@ -423,11 +261,11 @@ CasperTest.begin('Publish menu - new post', 11, function suite(test) {
casper.then(function fillContent() {
casper.sendKeys('#entry-title', 'Headline');
casper.writeContentToCodeMirror('Just a bit of testtext');
})
});
casper.then(function switchMenuToPublish() {
// Open the publish options menu;
casper.thenClick('.js-publish-splitbutton .options.up');
casper.thenClick('.js-publish-splitbutton .dropdown-toggle');
casper.waitForOpaque('.js-publish-splitbutton .open');
@ -435,11 +273,11 @@ CasperTest.begin('Publish menu - new post', 11, function suite(test) {
casper.thenClick('.js-publish-splitbutton li:first-child a');
// ... check status, label, class
casper.waitForSelector('.js-publish-splitbutton.splitbutton-delete', function onSuccess() {
test.assertExists('.js-publish-button.button-delete', 'Publish button should have .button-delete');
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');
}, function onTimeout() {
test.assert(false, 'Publish split button should have .splitbutton-delete');
test.assert(false, 'Publish split button works');
});
});
@ -447,15 +285,15 @@ CasperTest.begin('Publish menu - new post', 11, function suite(test) {
casper.thenClick('.js-publish-button');
// ... check status, label, class
casper.waitForSelector('.js-publish-splitbutton.splitbutton-save', function onSuccess() {
test.assertExists('.js-publish-button.button-save', 'Update button should have .button-save');
casper.waitForSelector('.js-publish-splitbutton', function onSuccess() {
test.assertExists('.js-publish-button.btn-blue', 'Update button should have .btn-blue');
test.assertSelectorHasText('.js-publish-button', 'Update Post');
}, function onTimeout() {
test.assert(false, 'Publish split button should have .splitbutton-save');
test.assert(false, 'Publish split button works');
});
});
CasperTest.begin('Publish menu - existing post', 21, function suite(test) {
CasperTest.begin('Publish menu - existing post', 19, function suite(test) {
// Create a post, save it and test refreshed editor
casper.thenOpenAndWaitForPageLoad('editor', function testTitleAndUrl() {
test.assertTitle('Ghost Admin', 'Ghost admin has no title');
@ -481,15 +319,14 @@ CasperTest.begin('Publish menu - existing post', 21, function suite(test) {
// ... check option status, label, class now that we're *saved* as 'draft'
casper.then(function () {
test.assertExists('.js-publish-splitbutton');
test.assertExists('.js-publish-splitbutton.splitbutton-save');
test.assertExists('.js-publish-button');
test.assertExists('.js-publish-button.button-save');
test.assertExists('.js-publish-button.btn-blue');
test.assertSelectorHasText('.js-publish-button', 'Save Draft');
});
casper.then(function switchMenuToPublish() {
// Open the publish options menu;
casper.thenClick('.js-publish-splitbutton .options.up');
casper.thenClick('.js-publish-splitbutton .dropdown-toggle');
casper.waitForOpaque('.js-publish-splitbutton .open');
@ -497,11 +334,11 @@ CasperTest.begin('Publish menu - existing post', 21, function suite(test) {
casper.thenClick('.js-publish-splitbutton li:first-child a');
// ... check status, label, class
casper.waitForSelector('.js-publish-splitbutton.splitbutton-delete', function onSuccess() {
test.assertExists('.js-publish-button.button-delete', 'Publish button should have .button-delete');
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');
}, function onTimeout() {
test.assert(false, 'Publish split button should have .splitbutton-delete');
test.assert(false, 'Publish split button works');
});
});
@ -515,15 +352,14 @@ CasperTest.begin('Publish menu - existing post', 21, function suite(test) {
// ... check option status, label, class for saved as 'published'
casper.then(function () {
test.assertExists('.js-publish-splitbutton');
test.assertExists('.js-publish-splitbutton.splitbutton-save');
test.assertExists('.js-publish-button');
test.assertExists('.js-publish-button.button-save');
test.assertExists('.js-publish-button.btn-blue');
test.assertSelectorHasText('.js-publish-button', 'Update Post');
});
casper.then(function switchMenuToUnpublish() {
// Open the publish options menu;
casper.thenClick('.js-publish-splitbutton .options.up');
casper.thenClick('.js-publish-splitbutton .dropdown-toggle');
casper.waitForOpaque('.js-publish-splitbutton .open');
@ -531,11 +367,11 @@ CasperTest.begin('Publish menu - existing post', 21, function suite(test) {
casper.thenClick('.js-publish-splitbutton li:nth-child(2) a');
// ... check status, label, class
casper.waitForSelector('.js-publish-splitbutton.splitbutton-delete', function onSuccess() {
test.assertExists('.js-publish-button.button-delete', 'Publish button should have .button-delete');
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');
}, function onTimeout() {
test.assert(false, 'Publish split button should have .splitbutton-delete');
test.assert(false, 'Publish split button works');
});
});
// Do unpublish
@ -543,11 +379,11 @@ CasperTest.begin('Publish menu - existing post', 21, function suite(test) {
casper.waitForSelector('.notification-success', function checkPostWasCreated() {
// ... check status, label, class
casper.waitForSelector('.js-publish-splitbutton.splitbutton-save', function onSuccess() {
test.assertExists('.js-publish-button.button-save', 'Publish button should have .button-save');
casper.waitForSelector('.js-publish-splitbutton', function onSuccess() {
test.assertExists('.js-publish-button.btn-blue', 'Publish button should have .btn-blue');
test.assertSelectorHasText('.js-publish-button', 'Save Draft');
}, function onTimeout() {
test.assert(false, 'Publish split button should have .splitbutton-save');
test.assert(false, 'Publish split button works');
});
});
});
@ -566,7 +402,7 @@ CasperTest.begin('Publish menu - new post status is correct after failed save',
casper.then(function switchMenuToPublish() {
// Open the publish options menu;
casper.thenClick('.js-publish-splitbutton .options.up');
casper.thenClick('.js-publish-splitbutton .dropdown-toggle');
casper.waitForOpaque('.js-publish-splitbutton .open');
@ -579,7 +415,7 @@ CasperTest.begin('Publish menu - new post status is correct after failed save',
// ... check status, label, class
casper.waitForSelector('.notification-error', function onSuccess() {
test.assertExists('.js-publish-button.button-save', 'Update button should have .button-save');
test.assertExists('.js-publish-button.btn-blue', 'Update button should have .btn-blue');
// wait for button to settle
casper.wait(500);
test.assertSelectorHasText('.js-publish-button', 'Save Draft');
@ -587,10 +423,12 @@ CasperTest.begin('Publish menu - new post status is correct after failed save',
test.assert(false, 'Saving post with invalid title should trigger an error');
});
casper.thenClick('li.content a');
// Click on "Content" in the main nav
casper.thenClick('.nav-content');
// The "Are you sure?" modal appears
casper.waitUntilVisible('.modal-content', function onSuccess() {
casper.thenClick('.button-delete');
casper.thenClick('.btn-red');
}, function onTimeout() {
test.assert(false, 'Are you sure you want to leave modal did not appear.');
});
@ -619,7 +457,7 @@ CasperTest.begin('Publish menu - existing post status is correct after failed sa
casper.then(function switchMenuToPublish() {
// Open the publish options menu;
casper.thenClick('.js-publish-splitbutton .options.up');
casper.thenClick('.js-publish-splitbutton .dropdown-toggle');
casper.waitForOpaque('.js-publish-splitbutton .open');
@ -627,11 +465,11 @@ CasperTest.begin('Publish menu - existing post status is correct after failed sa
casper.thenClick('.js-publish-splitbutton li:first-child a');
// ... check status, label, class
casper.waitForSelector('.js-publish-splitbutton.splitbutton-delete', function onSuccess() {
test.assertExists('.js-publish-button.button-delete', 'Publish button should have .button-delete');
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');
}, function onTimeout() {
test.assert(false, 'Publish split button should have .splitbutton-delete');
test.assert(false, 'Publish split button works');
});
});
@ -640,7 +478,7 @@ CasperTest.begin('Publish menu - existing post status is correct after failed sa
// ... check status, label, class
casper.waitForSelector('.notification-error', function onSuccess() {
test.assertExists('.js-publish-button.button-save', 'Update button should have .button-save');
test.assertExists('.js-publish-button.btn-blue', 'Update button should have .btn-blue');
// wait for button to settle
casper.wait(500);
test.assertSelectorHasText('.js-publish-button', 'Save Draft');
@ -649,6 +487,7 @@ CasperTest.begin('Publish menu - existing post status is correct after failed sa
});
});
// test the markdown help modal
CasperTest.begin('Markdown help modal', 5, function suite(test) {
casper.thenOpenAndWaitForPageLoad('editor', function testTitleAndUrl() {

View file

@ -0,0 +1,228 @@
// # Post Settings Menu Tests
// Test the post settings menu on the editor screen works as expected
/*globals CasperTest, casper */
CasperTest.begin('Post settings menu', 15, function suite(test) {
casper.thenOpenAndWaitForPageLoad('editor', function testTitleAndUrl() {
test.assertTitle('Ghost Admin', 'Ghost admin has no title');
test.assertUrlMatch(/ghost\/editor\/$/, 'Landed on the correct URL');
});
casper.then(function () {
test.assertExists('.post-settings', 'icon toggle should exist');
test.assertNotVisible('.post-settings-menu', 'popup menu should not be visible at startup');
test.assertExists('.post-settings-menu #url', 'url field exists');
test.assertExists('.post-settings-menu .post-setting-date', 'publication date field exists');
test.assertExists('.post-settings-menu .post-setting-static-page', 'static page checkbox field exists');
test.assertExists('.post-settings-menu button.delete', 'delete post button exists');
});
casper.thenClick('.post-settings');
casper.waitForOpaque('.post-settings-menu', function onSuccess() {
test.assert(true, 'popup menu should be visible after clicking post-settings icon');
test.assertNotVisible(
'.post-settings-menu button.delete', 'delete post button shouldn\'t be visible on unsaved drafts'
);
});
casper.thenClick('.post-settings');
casper.waitWhileVisible('.post-settings-menu', function onSuccess() {
test.assert(true, 'popup menu should not be visible after clicking post-settings icon');
});
// 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.waitForSelector('.notification-success', function waitForSuccess() {
test.assert(true, 'got success notification');
test.assertSelectorHasText('.notification-success', 'Saved.');
casper.click('.notification-success .close');
}, function onTimeout() {
test.assert(false, 'No success notification');
});
casper.waitWhileSelector('.notification-success');
casper.thenClick('.post-settings');
casper.waitForOpaque('.post-settings-menu', function onSuccess() {
test.assert(true, 'post settings menu should be visible after clicking post-settings icon');
});
casper.waitUntilVisible('.post-settings-menu button.delete', function onSuccess() {
test.assert(true, 'delete post button should be visible for saved drafts');
});
});
CasperTest.begin('Delete post modal', 7, function testDeleteModal(test) {
// Create a post that can be deleted
CasperTest.Routines.createTestPost.run(false);
// Begin test
casper.thenOpenAndWaitForPageLoad('content', function testTitleAndUrl() {
test.assertTitle('Ghost Admin', 'Title is "Ghost Admin"');
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('.post-settings');
casper.waitForOpaque('.post-settings-menu.open');
casper.thenClick('.post-settings-menu button.delete');
casper.waitUntilVisible('#modal-container', function onSuccess() {
test.assertSelectorHasText(
'.modal-content .modal-header',
'Are you sure you want to delete this post?',
'delete modal has correct text');
});
casper.thenClick('.js-button-reject');
casper.waitWhileVisible('#modal-container', function onSuccess() {
test.assert(true, 'clicking cancel should close the delete post modal');
});
// Test delete
casper.thenClick('.post-settings');
casper.waitForOpaque('.post-settings-menu.open');
casper.thenClick('.post-settings-menu button.delete');
casper.waitForSelector('#modal-container .modal-content', function onSuccess() {
test.assertExists('.modal-content .js-button-accept', 'delete button exists');
// Delete the post
this.click('.modal-content .js-button-accept');
casper.waitForSelector('.notification-success', function onSuccess() {
test.assert(true, 'Got success notification from delete post');
test.assertSelectorHasText('.notification-message', 'Your post has been deleted.');
}, function onTimeout() {
test.fail('No success notification from delete post');
});
});
});
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('Ghost Admin', 'Title is "Ghost Admin"');
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.waitForOpaque('.post-settings-menu.open');
// Test change permalink
casper.then(function () {
this.fillSelectors('.post-settings-menu form', {
'#url': 'new-url'
}, false);
this.click('.post-settings');
});
casper.waitForResource(/\/posts\/\d+\/\?include=tags/, function testGoodResponse(resource) {
test.assert(400 > resource.status);
});
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.assertEqual(slugVal, 'new-url');
});
});
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('Ghost Admin', 'Title is "Ghost Admin"');
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.waitForOpaque('.post-settings-menu.open');
// Test change published date
casper.then(function () {
this.fillSelectors('.post-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(400 > resource.status);
});
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.assertEqual(dateVal, '22 May 14 @ 23:39');
});
});
CasperTest.begin('Post can be changed to static page', 6, function suite(test) {
// Create a sample post
CasperTest.Routines.createTestPost.run(false);
// Begin test
casper.thenOpenAndWaitForPageLoad('content', function testTitleAndUrl() {
test.assertTitle('Ghost Admin', 'Title is "Ghost Admin"');
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.waitForOpaque('.post-settings-menu.open');
casper.thenClick('label[for=static-page]');
casper.waitForResource(/\/posts\/\d+\/\?include=tags/, function waitForSuccess(resource) {
test.assert(400 > resource.status);
test.assertExists('.post-setting-static-page:checked', 'can turn on static page');
});
casper.thenClick('label[for=static-page]');
casper.waitForResource(/\/posts\/\d+\/\?include=tags/, function waitForSuccess(resource) {
test.assert(400 > resource.status);
test.assertDoesntExist('.post-setting-static-page:checked', 'can turn off static page');
});
});

View file

@ -8,38 +8,37 @@
var generalTabDetector = '.settings-content form#settings-general',
usersTabDetector = '.settings-content .settings-users';
CasperTest.begin('Settings screen is correct', 16, function suite(test) {
CasperTest.begin('Settings screen is correct', 15, function suite(test) {
casper.thenOpenAndWaitForPageLoad('settings', function testTitleAndUrl() {
test.assertTitle('Ghost Admin', 'Ghost admin has no title');
test.assertUrlMatch(/ghost\/settings\/general\/$/, 'Landed on the correct URL');
});
casper.then(function testViews() {
test.assertExists('.wrapper', 'Settings main view is present');
test.assertExists('.settings-sidebar', 'Settings sidebar view is present');
test.assertExists('.settings', 'Settings main view is present');
test.assertExists('.settings-menu', 'Settings menu is present');
test.assertExists('.settings-menu .general a', 'General link is present');
test.assertExists('.settings-menu .users a', 'Users link is present');
test.assertNotExists('.settings-menu .apps a', 'Apps link is present');
test.assertExists('.wrapper', 'Settings main view is present');
test.assertExists('.settings-menu-general a', 'General link is present');
test.assertExists('.settings-menu-users a', 'Users link is present');
test.assertNotExists('.settings-menu-apps a', 'Apps link is present');
test.assertExists('.settings', 'Settings main view is present');
test.assertExists('.settings-content', 'Settings content view is present');
test.assertExists(generalTabDetector, 'Form is present');
test.assertSelectorHasText('.settings-content h2.title', 'General', 'Title is "General"');
test.assertSelectorHasText('.page-title', 'General', 'Title is "General"');
});
casper.then(function testSwitchingTabs() {
casper.thenClick('.settings-menu .users a');
casper.thenClick('.settings-menu-users a');
casper.waitForSelector(usersTabDetector, function then () {
// assert that the right menu item is active
test.assertExists('.settings-menu .users.active a', 'Users link is active');
test.assertDoesntExist('.settings-menu .general.active a', 'General link is not active');
test.assertExists('.settings-menu-users.active a', 'Users link is active');
test.assertDoesntExist('.settings-menu-general.active a', 'General link is not active');
}, casper.failOnTimeout(test, 'waitForSelector `usersTabDetector` timed out'));
casper.thenClick('.settings-menu .general a');
casper.thenClick('.settings-menu-general a');
casper.waitForSelector(generalTabDetector, function then () {
// assert that the right menu item is active
test.assertExists('.settings-menu .general.active a', 'General link is active');
test.assertDoesntExist('.settings-menu .users.active a', 'User link is not active');
test.assertExists('.settings-menu-general.active a', 'General link is active');
test.assertDoesntExist('.settings-menu-users.active a', 'User link is not active');
}, casper.failOnTimeout(test, 'waitForSelector `generalTabDetector` timed out'));
});
});
@ -89,8 +88,8 @@ CasperTest.begin('General settings pane is correct', 8, function suite(test) {
});
// Ensure can save
casper.waitForSelector('header .button-save').then(function () {
casper.thenClick('header .button-save').waitFor(function successNotification() {
casper.waitForSelector('header .btn-blue').then(function () {
casper.thenClick('header .btn-blue').waitFor(function successNotification() {
return this.evaluate(function () {
return document.querySelectorAll('.js-bb-notification section').length > 0;
});
@ -143,7 +142,7 @@ CasperTest.begin('General settings validation is correct', 7, function suite(tes
});
casper.waitForSelectorTextChange('.notification-error', function onSuccess() {
test.assertSelectorHasText('.notification-error', 'must be a number');
test.assertSelectorHasText('.notification-error', 'be a number');
}, casper.failOnTimeout(test, 'postsPerPage error did not appear'), 2000);
casper.thenClick('.js-bb-notification .close');
@ -181,9 +180,9 @@ CasperTest.begin('Users screen is correct', 9, function suite(test) {
test.assertSelectorHasText('.settings-users .object-list-item .name', 'Test User');
test.assertExists('.settings-users .object-list-item .role-label.owner', 'First user has owner role displayed');
test.assertExists('.page-actions .button-add', 'Add user button is on page.');
test.assertExists('.page-actions .btn-green', 'Add user button is on page.');
});
casper.thenClick('.page-actions .button-add');
casper.thenClick('.page-actions .btn-green');
casper.waitForOpaque('.invite-new-user .modal-content', function then() {
test.assertEval(function testOwnerRoleNotAnOption() {
var options = document.querySelectorAll('.invite-new-user select#new-user-role option'),
@ -203,217 +202,209 @@ CasperTest.begin('Users screen is correct', 9, function suite(test) {
i = 0;
for (; i < options.length; i++) {
if (options[i].selected) {
return options[i].text === "Author";
return options[i].text === "Author"
}
}
return false;
}, 'The "Author" role is selected by default when adding a new user');
});
});
CasperTest.begin('User profile screen is correct', 1, function suite(test) {
casper.thenOpenAndWaitForPageLoad('settings.users');
casper.thenClick('.active-users .object-list-item-body');
casper.waitForSelector('.user-details-bottom', function then() {
test.assertSelectorHasText('.user-details-bottom .form-group p', 'http://127.0.0.1:2369/author/test-user');
});
});
// ### User settings tests
CasperTest.begin('Can save settings', 7, function suite(test) {
casper.thenOpenAndWaitForPageLoad('settings.users.user', function testTitleAndUrl() {
test.assertTitle('Ghost Admin', 'Ghost Admin title is GhostAdmin');
test.assertUrlMatch(/ghost\/settings\/users\/test-user\/$/, 'settings.users.user has correct URL');
});
// Please uncomment and fix these as the functionality is implemented
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');
}
}
//CasperTest.begin('Can save settings', 6, function suite(test) {
// casper.thenOpenAndWaitForPageLoad('settings.users.user', function testTitleAndUrl() {
// test.assertTitle('Ghost Admin', 'Ghost Admin title is GhostAdmin');
// test.assertUrlMatch(/ghost\/settings\/users\/test-user\/$/, 'settings.users.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('users/') !== -1) {
// test.fail('Saving a settings pane triggered the user pane to save');
// }
// }
//
// casper.then(function listenForRequests() {
// casper.on('resource.requested', handleUserRequest);
// });
//
// casper.thenClick('#user .btn-blue');
// casper.waitFor(function successNotification() {
// return this.evaluate(function () {
// return document.querySelectorAll('.js-bb-notification section').length > 0;
// });
// }, function doneWaiting() {
// test.pass('Waited for notification');
// }, casper.failOnTimeout(test, 'Saving the user pane did not result in a notification'));
//
// casper.then(function checkUserWasSaved() {
// casper.removeListener('resource.requested', handleUserRequest);
// });
//
// casper.waitForSelector('.notification-success', function onSuccess() {
// test.assert(true, 'Got success notification');
// }, casper.failOnTimeout(test, 'No success notification :('));
//
// casper.thenClick('.global-nav .settings a').then(function testOpeningSettingsTwice() {
// casper.on('resource.requested', handleSettingsRequest);
// test.assertEval(function testUserIsActive() {
// return document.querySelector('.settings-menu .general').classList.contains('active');
// }, 'general tab is marked active');
// });
//
// casper.thenClick('#general .btn-blue').waitFor(function successNotification() {
// return this.evaluate(function () {
// return document.querySelectorAll('.js-bb-notification section').length > 0;
// });
// }, function doneWaiting() {
// test.pass('Waited for notification');
// }, casper.failOnTimeout(test, 'Saving the general pane did not result in a notification'));
//
// casper.then(function checkSettingsWereSaved() {
// casper.removeListener('resource.requested', handleSettingsRequest);
// });
//
// casper.waitForSelector('.notification-success', function onSuccess() {
// test.assert(true, 'Got success notification');
// }, casper.failOnTimeout(test, 'No success notification :('));
//
// CasperTest.beforeDone(function () {
// casper.removeListener('resource.requested', handleUserRequest);
// casper.removeListener('resource.requested', handleSettingsRequest);
// });
function handleSettingsRequest(requestData) {
// make sure we only get requests from the user pane
if (requestData.url.indexOf('users/') !== -1) {
test.fail('Saving a settings pane triggered the user pane to save');
}
}
casper.then(function listenForRequests() {
casper.on('resource.requested', handleUserRequest);
});
casper.thenClick('.button-save');
casper.waitFor(function successNotification() {
return this.evaluate(function () {
return document.querySelectorAll('.js-bb-notification section').length > 0;
});
}, function doneWaiting() {
test.pass('Waited for notification');
}, casper.failOnTimeout(test, 'Saving the user pane did not result in a notification'));
casper.then(function checkUserWasSaved() {
casper.removeListener('resource.requested', handleUserRequest);
});
casper.waitForSelector('.notification-success', function onSuccess() {
test.assert(true, 'Got success notification');
}, casper.failOnTimeout(test, 'No success notification :('));
casper.thenClick('#main-menu .settings a').then(function testTransitionToGeneral() {
casper.waitForSelector(generalTabDetector, function then() {
casper.on('resource.requested', handleSettingsRequest);
test.assertEval(function testGeneralIsActive() {
return document.querySelector('.settings-menu .general').classList.contains('active');
}, 'general tab is marked active');
},
casper.failOnTimeout(test, 'waitForSelector `usersTabDetector` timed out'));
});
casper.thenClick('.button-save').waitFor(function successNotification() {
return this.evaluate(function () {
return document.querySelectorAll('.js-bb-notification section').length > 0;
});
}, function doneWaiting() {
test.pass('Waited for notification');
}, casper.failOnTimeout(test, 'Saving the general pane did not result in a notification'));
casper.then(function checkSettingsWereSaved() {
casper.removeListener('resource.requested', handleSettingsRequest);
});
casper.waitForSelector('.notification-success', function onSuccess() {
test.assert(true, 'Got success notification');
}, casper.failOnTimeout(test, 'No success notification :('));
CasperTest.beforeDone(function () {
casper.removeListener('resource.requested', handleUserRequest);
casper.removeListener('resource.requested', handleSettingsRequest);
});
});
CasperTest.begin('User settings screen validates email', 6, function suite(test) {
var email, brokenEmail;
casper.thenOpenAndWaitForPageLoad('settings.users.user', function testTitleAndUrl() {
test.assertTitle('Ghost Admin', 'Ghost admin has no title');
test.assertUrlMatch(/ghost\/settings\/users\/test-user\/$/, 'Ghost doesn\'t require login this time');
});
casper.then(function setEmailToInvalid() {
email = casper.getElementInfo('#user-email').attributes.value;
brokenEmail = email.replace('.', '-');
casper.fillSelectors('.user-profile', {
'#user-email': brokenEmail
}, false);
});
casper.thenClick('.button-save');
casper.waitForResource('/users/');
casper.waitForSelector('.notification-error', function onSuccess() {
test.assert(true, 'Got error notification');
test.assertSelectorDoesntHaveText('.notification-error', '[object Object]');
}, casper.failOnTimeout(test, 'No error notification :('));
casper.then(function resetEmailToValid() {
casper.fillSelectors('.user-profile', {
'#user-email': email
}, false);
});
casper.thenClick('.button-save');
casper.waitForResource(/users/);
casper.waitForSelector('.notification-success', function onSuccess() {
test.assert(true, 'Got success notification');
test.assertSelectorDoesntHaveText('.notification-success', '[object Object]');
}, casper.failOnTimeout(test, 'No success notification :('));
});
//
//CasperTest.begin('User settings screen validates email', 6, function suite(test) {
// var email, brokenEmail;
//
// casper.thenOpenAndWaitForPageLoad('settings.user', function testTitleAndUrl() {
// test.assertTitle('Ghost Admin', 'Ghost admin has no title');
// test.assertUrlMatch(/ghost\/settings\/user\/$/, 'Ghost doesn\'t require login this time');
// });
//
// casper.then(function setEmailToInvalid() {
// email = casper.getElementInfo('#user-email').attributes.value;
// brokenEmail = email.replace('.', '-');
//
// casper.fillSelectors('.user-profile', {
// '#user-email': brokenEmail
// }, false);
// });
//
// casper.thenClick('#user .btn-blue');
//
// casper.waitForResource('/users/');
//
// casper.waitForSelector('.notification-error', function onSuccess() {
// test.assert(true, 'Got error notification');
// test.assertSelectorDoesntHaveText('.notification-error', '[object Object]');
// }, casper.failOnTimeout(test, 'No error notification :('));
//
// casper.then(function resetEmailToValid() {
// casper.fillSelectors('.user-profile', {
// '#user-email': email
// }, false);
// });
//
// casper.thenClick('#user .btn-blue');
//
// casper.waitForResource(/users/);
//
// casper.waitForSelector('.notification-success', function onSuccess() {
// test.assert(true, 'Got success notification');
// test.assertSelectorDoesntHaveText('.notification-success', '[object Object]');
// }, casper.failOnTimeout(test, 'No success notification :('));
//});
//
//
// 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('settings.users.user', function testTitleAndUrl() {
test.assertTitle('Ghost Admin', 'Ghost admin has no title');
test.assertUrlMatch(/ghost\/settings\/users\/test-user\/$/, 'Ghost doesn\'t require login this time');
});
// CasperTest.begin('User settings screen shows remaining characters for Bio properly', 4, function suite(test) {
// casper.thenOpenAndWaitForPageLoad('settings.user', function testTitleAndUrl() {
// test.assertTitle('Ghost Admin', 'Ghost admin has no title');
// test.assertUrlMatch(/ghost\/settings\/user\/$/, 'Ghost doesn\'t require login this time');
// });
function getRemainingBioCharacterCount() {
return casper.getHTML('.word-count');
}
// function getRemainingBioCharacterCount() {
// return casper.getHTML('.word-count');
// }
casper.then(function checkCharacterCount() {
test.assert(getRemainingBioCharacterCount() === '200', 'Bio remaining characters is 200');
});
// 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 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');
});
});
// 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('settings.users.user', function testTitleAndUrl() {
test.assertTitle('Ghost Admin', 'Ghost admin has no title');
test.assertUrlMatch(/ghost\/settings\/users\/test-user\/$/, 'Ghost doesn\'t require login this time');
});
casper.waitForSelector('.settings-content .settings-user', function then() {
this.fillSelectors('form.user-profile', {
'#user-bio': new Array(202).join('a')
});
}, casper.failOnTimeout(test, 'waitForSelector .settings-content .settings-user timed out'));
casper.thenClick('.button-save');
casper.waitForSelectorTextChange('.notification-error', function onSuccess() {
test.assertSelectorHasText('.notification-error', 'is too long');
}, casper.failOnTimeout(test, 'Bio field length error did not appear', 2000));
});
CasperTest.begin('Ensure user url field validation', 3, function suite(test) {
casper.thenOpenAndWaitForPageLoad('settings.users.user', function testTitleAndUrl() {
test.assertTitle('Ghost Admin', 'Ghost admin has no title');
test.assertUrlMatch(/ghost\/settings\/users\/test-user\/$/, 'Ghost doesn\'t require login this time');
});
casper.waitForSelector('.settings-content .settings-user', function then() {
this.fillSelectors('form.user-profile', {
'#user-website': 'notaurl'
});
}, casper.failOnTimeout(test, 'waitForSelector .settings-content .settings-user timed out'));
casper.thenClick('.button-save');
casper.waitForSelectorTextChange('.notification-error', function onSuccess() {
test.assertSelectorHasText('.notification-error', 'not a valid url');
}, casper.failOnTimeout(test, 'Url validation error did not appear', 2000));
});
CasperTest.begin('Ensure user location field length validation', 3, function suite(test) {
casper.thenOpenAndWaitForPageLoad('settings.users.user', function testTitleAndUrl() {
test.assertTitle('Ghost Admin', 'Ghost admin has no title');
test.assertUrlMatch(/ghost\/settings\/users\/test-user\/$/, 'Ghost doesn\'t require login this time');
});
casper.waitForSelector('.settings-content .settings-user', function then() {
this.fillSelectors('form.user-profile', {
'#user-location': new Array(1002).join('a')
});
}, casper.failOnTimeout(test, 'waitForSelector .settings-content .settings-user timed out'));
casper.thenClick('.button-save');
casper.waitForSelectorTextChange('.notification-error', function onSuccess() {
test.assertSelectorHasText('.notification-error', 'is too long');
}, casper.failOnTimeout(test, 'Location field length error did not appear', 2000));
});
//CasperTest.begin('Ensure user bio field length validation', 3, function suite(test) {
// casper.thenOpenAndWaitForPageLoad('settings.user', function testTitleAndUrl() {
// test.assertTitle('Ghost Admin', 'Ghost admin has no title');
// test.assertUrlMatch(/ghost\/settings\/user\/$/, 'Ghost doesn\'t require login this time');
// });
//
// casper.waitForSelector('#user', function then() {
// this.fillSelectors('form.user-profile', {
// '#user-bio': new Array(202).join('a')
// });
// }, casper.failOnTimeout(test, 'waitForSelector #user timed out'));
//
// casper.thenClick('#user .btn-blue');
//
// casper.waitForSelectorTextChange('.notification-error', function onSuccess() {
// test.assertSelectorHasText('.notification-error', 'is too long');
// }, casper.failOnTimeout(test, 'Bio field length error did not appear', 2000));
//});
//
//CasperTest.begin('Ensure user url field validation', 3, function suite(test) {
// casper.thenOpenAndWaitForPageLoad('settings.user', function testTitleAndUrl() {
// test.assertTitle('Ghost Admin', 'Ghost admin has no title');
// test.assertUrlMatch(/ghost\/settings\/user\/$/, 'Ghost doesn\'t require login this time');
// });
//
// casper.waitForSelector('#user', function then() {
// this.fillSelectors('form.user-profile', {
// '#user-website': 'notaurl'
// });
// }, casper.failOnTimeout(test, 'waitForSelector #user timed out'));
//
// casper.thenClick('#user .btn-blue');
//
// casper.waitForSelectorTextChange('.notification-error', function onSuccess() {
// test.assertSelectorHasText('.notification-error', 'use a valid url');
// }, casper.failOnTimeout(test, 'Url validation error did not appear', 2000));
//});
//
//CasperTest.begin('Ensure user location field length validation', 3, function suite(test) {
// casper.thenOpenAndWaitForPageLoad('settings.user', function testTitleAndUrl() {
// test.assertTitle('Ghost Admin', 'Ghost admin has no title');
// test.assertUrlMatch(/ghost\/settings\/user\/$/, 'Ghost doesn\'t require login this time');
// });
//
// casper.waitForSelector('#user', function then() {
// this.fillSelectors('form.user-profile', {
// '#user-location': new Array(1002).join('a')
// });
// }, casper.failOnTimeout(test, 'waitForSelector #user timed out'));
//
// casper.thenClick('#user .btn-blue');
//
// casper.waitForSelectorTextChange('.notification-error', function onSuccess() {
// test.assertSelectorHasText('.notification-error', 'is too long');
// }, casper.failOnTimeout(test, 'Location field length error did not appear', 2000));
//});

View file

@ -74,7 +74,7 @@ CasperTest.begin('Can login to Ghost', 5, function suite(test) {
casper.waitForResource(/posts/, function testForDashboard() {
test.assertUrlMatch(/ghost\/\d+\/$/, 'Landed on the correct URL');
test.assertExists('#global-header', 'Global admin header is present');
test.assertExists('.global-nav', 'Global admin header is present');
test.assertExists('.manage', 'We\'re now on content');
}, function onTimeOut() {
test.fail('Failed to signin');
@ -97,7 +97,7 @@ CasperTest.begin('Authenticated user is redirected', 8, function suite(test) {
casper.waitForResource(/posts/, function testForDashboard() {
test.assertUrlMatch(/ghost\/\d+\/$/, 'Landed on the correct URL');
test.assertExists('#global-header', 'Global admin header is present');
test.assertExists('.global-nav', 'Global admin header is present');
test.assertExists('.manage', 'We\'re now on content');
}, function onTimeOut() {
test.fail('Failed to signin');
@ -105,7 +105,7 @@ CasperTest.begin('Authenticated user is redirected', 8, function suite(test) {
casper.thenOpenAndWaitForPageLoad('signin-authenticated', function testTitleAndUrl() {
test.assertUrlMatch(/ghost\/\d+\/$/, 'Landed on the correct URL');
test.assertExists('#global-header', 'Global admin header is present');
test.assertExists('.global-nav', 'Global admin header is present');
test.assertExists('.manage', 'We\'re now on content');
}, function onTimeOut() {
test.fail('Failed to redirect');

View file

@ -11,9 +11,9 @@ CasperTest.begin('Ghost signout works correctly', 3, function suite(test) {
test.assertUrlMatch(/ghost\/\d+\/$/, 'Landed on the correct URL without signing in');
});
casper.thenClick('#usermenu button').waitFor(function checkOpaque() {
casper.thenClick('.user-menu .nav-label').waitFor(function checkOpaque() {
return this.evaluate(function () {
var menu = document.querySelector('#usermenu .overlay.open');
var menu = document.querySelector('.user-menu .dropdown.open');
return window.getComputedStyle(menu).getPropertyValue('display') === 'block' &&
window.getComputedStyle(menu).getPropertyValue('opacity') === '1';
});
@ -21,8 +21,8 @@ CasperTest.begin('Ghost signout works correctly', 3, function suite(test) {
casper.captureScreenshot('user-menu-open.png');
casper.waitForSelector('.usermenu-signout a');
casper.thenClick('.usermenu-signout a');
casper.waitForSelector('.user-menu-signout');
casper.thenClick('.user-menu-signout');
casper.waitForSelector('#login').then(function assertSuccess() {
test.assert(true, 'Got login screen');

View file

@ -29,7 +29,7 @@ CasperTest.begin('Ghost setup fails properly', 6, function suite(test) {
casper.waitForResource(/\d+/, function testForDashboard() {
test.assertUrlMatch(/ghost\/\d+\/$/, 'Landed on the correct URL');
test.assertExists('#global-header', 'Global admin header is present');
test.assertExists('.global-nav', 'Global admin header is present');
test.assertExists('.manage', 'We\'re now on content');
}, function onTimeOut() {
test.fail('Failed to signin');
@ -50,7 +50,7 @@ CasperTest.begin('Authenticated user is redirected', 8, function suite(test) {
casper.waitForResource(/\d+/, function testForDashboard() {
test.assertUrlMatch(/ghost\/\d+\/$/, 'Landed on the correct URL');
test.assertExists('#global-header', 'Global admin header is present');
test.assertExists('.global-nav', 'Global admin header is present');
test.assertExists('.manage', 'We\'re now on content');
}, function onTimeOut() {
test.fail('Failed to signin');
@ -58,7 +58,7 @@ CasperTest.begin('Authenticated user is redirected', 8, function suite(test) {
casper.thenOpenAndWaitForPageLoad('setup-authenticated', function testTitleAndUrl() {
test.assertUrlMatch(/ghost\/\d+\/$/, 'Landed on the correct URL');
test.assertExists('#global-header', 'Global admin header is present');
test.assertExists('.global-nav', 'Global admin header is present');
test.assertExists('.manage', 'We\'re now on content');
}, function onTimeOut() {
test.fail('Failed to redirect');