mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-11-28 14:03:48 +03:00
Fix blank signup screen (#135)
closes https://github.com/TryGhost/Ghost/issues/7117 - adds guard to `sanitizeInput` method of `gh-trim-focus-input` for null/undefined values - adds acceptance test for successful signup screen flow - removes unneeded validation/update handling for a non-editable email field - adds "At least 8 characters" placeholder to password field - fixes enter key not submitting the form when name or password field has focus
This commit is contained in:
parent
899ccaea38
commit
8d803d9862
@ -32,7 +32,11 @@ const TrimFocusInputComponent = GhostInput.extend({
|
||||
},
|
||||
|
||||
sanitizeInput(input) {
|
||||
return input.trim();
|
||||
if (input && typeof input.trim === 'function') {
|
||||
return input.trim();
|
||||
} else {
|
||||
return input;
|
||||
}
|
||||
},
|
||||
|
||||
_focus() {
|
||||
|
@ -155,6 +155,7 @@ export function testConfig() {
|
||||
// this.urlPrefix = ''; // make this `http://localhost:8080`, for example, if your API is on a different server
|
||||
this.namespace = 'ghost/api/v0.1'; // make this `api`, for example, if your API is namespaced
|
||||
// this.timing = 400; // delay for each request, automatically set to 0 during testing
|
||||
// this.logging = true;
|
||||
|
||||
/* Authentication ------------------------------------------------------- */
|
||||
|
||||
|
@ -12,24 +12,26 @@
|
||||
<input style="display:none;" type="password" name="fakepasswordremembered"/>
|
||||
|
||||
{{gh-profile-image fileStorage=config.fileStorage email=model.email setImage="setImage"}}
|
||||
{{#gh-form-group errors=model.errors hasValidated=hasValidated property="email"}}
|
||||
|
||||
{{#gh-form-group}}
|
||||
<label for="email-address">Email address</label>
|
||||
<span class="input-icon icon-mail">
|
||||
{{gh-input model.email type="email" name="email" placeholder="Eg. john@example.com" onenter=(action "signup") disabled="disabled" autocorrect="off" focusOut=(action "validate" "email") update=(action (mut model.email))}}
|
||||
{{gh-input model.email type="email" name="email" placeholder="Eg. john@example.com" disabled="disabled" autocorrect="off"}}
|
||||
</span>
|
||||
{{gh-error-message errors=model.errors property="email"}}
|
||||
{{/gh-form-group}}
|
||||
|
||||
{{#gh-form-group errors=model.errors hasValidated=hasValidated property="name"}}
|
||||
<label for="full-name">Full name</label>
|
||||
<span class="input-icon icon-user">
|
||||
{{gh-trim-focus-input model.name tabindex="1" type="text" name="name" placeholder="Eg. John H. Watson" enter=(action "signup") autocorrect="off" focusOut=(action "validate" "name") update=(action (mut model.name))}}
|
||||
{{gh-trim-focus-input model.name tabindex="1" type="text" name="name" placeholder="Eg. John H. Watson" onenter=(action "signup") autocorrect="off" focusOut=(action "validate" "name") update=(action (mut model.name))}}
|
||||
</span>
|
||||
{{gh-error-message errors=model.errors property="name"}}
|
||||
{{/gh-form-group}}
|
||||
|
||||
{{#gh-form-group errors=model.errors hasValidated=hasValidated property="password"}}
|
||||
<label for="password">Password</label>
|
||||
<span class="input-icon icon-lock">
|
||||
{{gh-input model.password tabindex="2" type="password" name="password" enter=(action "signup") autocorrect="off" focusOut=(action "validate" "password") update=(action (mut model.password))}}
|
||||
{{gh-input model.password tabindex="2" type="password" name="password" placeholder="At least 8 characters" onenter=(action "signup") autocorrect="off" focusOut=(action "validate" "password") update=(action (mut model.password))}}
|
||||
</span>
|
||||
{{gh-error-message errors=model.errors property="password"}}
|
||||
{{/gh-form-group}}
|
||||
|
142
ghost/admin/tests/acceptance/signup-test.js
Normal file
142
ghost/admin/tests/acceptance/signup-test.js
Normal file
@ -0,0 +1,142 @@
|
||||
/* jshint expr:true */
|
||||
import {
|
||||
describe,
|
||||
it,
|
||||
beforeEach,
|
||||
afterEach
|
||||
} from 'mocha';
|
||||
import { expect } from 'chai';
|
||||
import startApp from '../helpers/start-app';
|
||||
import destroyApp from '../helpers/destroy-app';
|
||||
import $ from 'jquery';
|
||||
|
||||
describe('Acceptance: Signup', function() {
|
||||
let application;
|
||||
|
||||
beforeEach(function() {
|
||||
application = startApp();
|
||||
|
||||
server.loadFixtures();
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
destroyApp(application);
|
||||
});
|
||||
|
||||
it('can signup successfully', function() {
|
||||
// token details:
|
||||
// "1470346017929|kevin+test2@ghost.org|2cDnQc3g7fQTj9nNK4iGPSGfvomkLdXf68FuWgS66Ug="
|
||||
visit('/signup/MTQ3MDM0NjAxNzkyOXxrZXZpbit0ZXN0MkBnaG9zdC5vcmd8MmNEblFjM2c3ZlFUajluTks0aUdQU0dmdm9ta0xkWGY2OEZ1V2dTNjZVZz0');
|
||||
|
||||
andThen(function () {
|
||||
expect(currentPath()).to.equal('signup');
|
||||
|
||||
// email address should be pre-filled and disabled
|
||||
expect(
|
||||
find('input[name="email"]').val(),
|
||||
'email field value'
|
||||
).to.equal('kevin+test2@ghost.org');
|
||||
|
||||
expect(
|
||||
find('input[name="email"]').is(':disabled'),
|
||||
'email field is disabled'
|
||||
).to.be.true;
|
||||
});
|
||||
|
||||
// focus out in Name field triggers inline error
|
||||
triggerEvent('input[name="name"]', 'blur');
|
||||
|
||||
andThen(function () {
|
||||
expect(
|
||||
find('input[name="name"]').closest('.form-group').hasClass('error'),
|
||||
'name field group has error class when empty'
|
||||
).to.be.true;
|
||||
|
||||
expect(
|
||||
find('input[name="name"]').closest('.form-group').find('.response').text().trim(),
|
||||
'name inline-error text'
|
||||
).to.match(/Please enter a name/);
|
||||
});
|
||||
|
||||
// entering text in Name field clears error
|
||||
fillIn('input[name="name"]', 'Test User');
|
||||
triggerEvent('input[name="name"]', 'blur');
|
||||
|
||||
andThen(function () {
|
||||
expect(
|
||||
find('input[name="name"]').closest('.form-group').hasClass('error'),
|
||||
'name field loses error class after text input'
|
||||
).to.be.false;
|
||||
|
||||
expect(
|
||||
find('input[name="name"]').closest('.form-group').find('.response').text().trim(),
|
||||
'name field error is removed after text input'
|
||||
).to.equal('');
|
||||
});
|
||||
|
||||
// focus out in Name field triggers inline error
|
||||
triggerEvent('input[name="password"]', 'blur');
|
||||
|
||||
andThen(function () {
|
||||
expect(
|
||||
find('input[name="password"]').closest('.form-group').hasClass('error'),
|
||||
'password field group has error class when empty'
|
||||
).to.be.true;
|
||||
|
||||
expect(
|
||||
find('input[name="password"]').closest('.form-group').find('.response').text().trim(),
|
||||
'password field error text'
|
||||
).to.match(/must be at least 8 characters/);
|
||||
});
|
||||
|
||||
// entering valid text in Password field clears error
|
||||
fillIn('input[name="password"]', 'ValidPassword');
|
||||
triggerEvent('input[name="password"]', 'blur');
|
||||
|
||||
andThen(function () {
|
||||
expect(
|
||||
find('input[name="password"]').closest('.form-group').hasClass('error'),
|
||||
'password field loses error class after text input'
|
||||
).to.be.false;
|
||||
|
||||
expect(
|
||||
find('input[name="password"]').closest('.form-group').find('.response').text().trim(),
|
||||
'password field error is removed after text input'
|
||||
).to.equal('');
|
||||
});
|
||||
|
||||
// submitting sends correct details and redirects to content screen
|
||||
click('.btn-green');
|
||||
|
||||
server.get('/authentication/invitation', function (db, request) {
|
||||
return {
|
||||
invitation: [{valid: true}]
|
||||
};
|
||||
});
|
||||
|
||||
server.post('/authentication/invitation/', function (db, request) {
|
||||
let params = $.deparam(request.requestBody);
|
||||
expect(params.invitation[0].name).to.equal('Test User');
|
||||
expect(params.invitation[0].email).to.equal('kevin+test2@ghost.org');
|
||||
expect(params.invitation[0].password).to.equal('ValidPassword');
|
||||
expect(params.invitation[0].token).to.equal('MTQ3MDM0NjAxNzkyOXxrZXZpbit0ZXN0MkBnaG9zdC5vcmd8MmNEblFjM2c3ZlFUajluTks0aUdQU0dmdm9ta0xkWGY2OEZ1V2dTNjZVZz0');
|
||||
|
||||
// ensure that `/users/me/` request returns a user
|
||||
server.create('user', {email: 'kevin@test2@ghost.org'});
|
||||
|
||||
return {
|
||||
invitation: [{
|
||||
message: 'Invitation accepted.'
|
||||
}]
|
||||
};
|
||||
});
|
||||
|
||||
andThen(function () {
|
||||
expect(currentPath()).to.equal('posts.index');
|
||||
});
|
||||
});
|
||||
|
||||
it('redirects if already logged in');
|
||||
it('redirects with alert on invalid token');
|
||||
it('redirects with alert on non-existant or expired token');
|
||||
});
|
@ -35,5 +35,17 @@ describeComponent(
|
||||
this.render(hbs`{{gh-trim-focus-input text shouldFocus=true}}`);
|
||||
expect(this.$('.gh-input').attr('autofocus')).to.be.ok;
|
||||
});
|
||||
|
||||
it('handles undefined values', function () {
|
||||
this.set('text', undefined);
|
||||
this.render(hbs`{{gh-trim-focus-input text shouldFocus=true}}`);
|
||||
expect(this.$('.gh-input').attr('autofocus')).to.be.ok;
|
||||
});
|
||||
|
||||
it('handles non-string values', function () {
|
||||
this.set('text', 10);
|
||||
this.render(hbs`{{gh-trim-focus-input text shouldFocus=true}}`);
|
||||
expect(this.$('.gh-input').val()).to.equal('10');
|
||||
});
|
||||
}
|
||||
);
|
||||
|
Loading…
Reference in New Issue
Block a user