Merge pull request #206 from Turbo87/new-mocha-api

Use new Mocha testing API
This commit is contained in:
Austin Burdine 2016-11-27 23:21:20 -06:00 committed by GitHub
commit 5473e8ad09
82 changed files with 4900 additions and 5258 deletions

View File

@ -48,7 +48,7 @@
"ember-cli-htmlbars": "1.1.0",
"ember-cli-htmlbars-inline-precompile": "0.3.6",
"ember-cli-mirage": "0.1.14",
"ember-cli-mocha": "0.11.0",
"ember-cli-mocha": "0.12.1",
"ember-cli-node-assets": "0.1.6",
"ember-cli-pretender": "0.7.0",
"ember-cli-selectize": "0.5.11",

View File

@ -1,67 +1,62 @@
/* jshint expr:true */
import {expect} from 'chai';
import {
describeModule,
it
} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupTest} from 'ember-mocha';
import Pretender from 'pretender';
describeModule(
'adapter:tag',
'Integration: Adapter: tag',
{
describe('Integration: Adapter: tag', function () {
setupTest('adapter:tag', {
integration: true
},
function () {
let server, store;
});
beforeEach(function () {
store = this.container.lookup('service:store');
server = new Pretender();
let server, store;
beforeEach(function () {
store = this.container.lookup('service:store');
server = new Pretender();
});
afterEach(function () {
server.shutdown();
});
it('loads tags from regular endpoint when all are fetched', function (done) {
server.get('/ghost/api/v0.1/tags/', function () {
return [200, {'Content-Type': 'application/json'}, JSON.stringify({tags: [
{
id: 1,
name: 'Tag 1',
slug: 'tag-1'
}, {
id: 2,
name: 'Tag 2',
slug: 'tag-2'
}
]})];
});
afterEach(function () {
server.shutdown();
store.findAll('tag', {reload: true}).then((tags) => {
expect(tags).to.be.ok;
expect(tags.objectAtContent(0).get('name')).to.equal('Tag 1');
done();
});
});
it('loads tag from slug endpoint when single tag is queried and slug is passed in', function (done) {
server.get('/ghost/api/v0.1/tags/slug/tag-1/', function () {
return [200, {'Content-Type': 'application/json'}, JSON.stringify({tags: [
{
id: 1,
slug: 'tag-1',
name: 'Tag 1'
}
]})];
});
it('loads tags from regular endpoint when all are fetched', function (done) {
server.get('/ghost/api/v0.1/tags/', function () {
return [200, {'Content-Type': 'application/json'}, JSON.stringify({tags: [
{
id: 1,
name: 'Tag 1',
slug: 'tag-1'
}, {
id: 2,
name: 'Tag 2',
slug: 'tag-2'
}
]})];
});
store.findAll('tag', {reload: true}).then((tags) => {
expect(tags).to.be.ok;
expect(tags.objectAtContent(0).get('name')).to.equal('Tag 1');
done();
});
store.queryRecord('tag', {slug: 'tag-1'}).then((tag) => {
expect(tag).to.be.ok;
expect(tag.get('name')).to.equal('Tag 1');
done();
});
it('loads tag from slug endpoint when single tag is queried and slug is passed in', function (done) {
server.get('/ghost/api/v0.1/tags/slug/tag-1/', function () {
return [200, {'Content-Type': 'application/json'}, JSON.stringify({tags: [
{
id: 1,
slug: 'tag-1',
name: 'Tag 1'
}
]})];
});
store.queryRecord('tag', {slug: 'tag-1'}).then((tag) => {
expect(tag).to.be.ok;
expect(tag.get('name')).to.equal('Tag 1');
done();
});
});
}
);
});
});

View File

@ -1,92 +1,87 @@
/* jshint expr:true */
import {expect} from 'chai';
import {
describeModule,
it
} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupTest} from 'ember-mocha';
import Pretender from 'pretender';
describeModule(
'adapter:user',
'Integration: Adapter: user',
{
describe('Integration: Adapter: user', function () {
setupTest('adapter:user', {
integration: true
},
function () {
let server, store;
});
beforeEach(function () {
store = this.container.lookup('service:store');
server = new Pretender();
let server, store;
beforeEach(function () {
store = this.container.lookup('service:store');
server = new Pretender();
});
afterEach(function () {
server.shutdown();
});
it('loads users from regular endpoint when all are fetched', function (done) {
server.get('/ghost/api/v0.1/users/', function () {
return [200, {'Content-Type': 'application/json'}, JSON.stringify({users: [
{
id: 1,
name: 'User 1',
slug: 'user-1'
}, {
id: 2,
name: 'User 2',
slug: 'user-2'
}
]})];
});
afterEach(function () {
server.shutdown();
store.findAll('user', {reload: true}).then((users) => {
expect(users).to.be.ok;
expect(users.objectAtContent(0).get('name')).to.equal('User 1');
done();
});
});
it('loads user from slug endpoint when single user is queried and slug is passed in', function (done) {
server.get('/ghost/api/v0.1/users/slug/user-1/', function () {
return [200, {'Content-Type': 'application/json'}, JSON.stringify({users: [
{
id: 1,
slug: 'user-1',
name: 'User 1'
}
]})];
});
it('loads users from regular endpoint when all are fetched', function (done) {
server.get('/ghost/api/v0.1/users/', function () {
return [200, {'Content-Type': 'application/json'}, JSON.stringify({users: [
{
id: 1,
name: 'User 1',
slug: 'user-1'
}, {
id: 2,
name: 'User 2',
slug: 'user-2'
store.queryRecord('user', {slug: 'user-1'}).then((user) => {
expect(user).to.be.ok;
expect(user.get('name')).to.equal('User 1');
done();
});
});
it('handles "include" parameter when querying single user via slug', function (done) {
server.get('/ghost/api/v0.1/users/slug/user-1/', (request) => {
let params = request.queryParams;
expect(params.include, 'include query').to.equal('roles,count.posts');
return [200, {'Content-Type': 'application/json'}, JSON.stringify({users: [
{
id: 1,
slug: 'user-1',
name: 'User 1',
count: {
posts: 5
}
]})];
});
store.findAll('user', {reload: true}).then((users) => {
expect(users).to.be.ok;
expect(users.objectAtContent(0).get('name')).to.equal('User 1');
done();
});
}
]})];
});
it('loads user from slug endpoint when single user is queried and slug is passed in', function (done) {
server.get('/ghost/api/v0.1/users/slug/user-1/', function () {
return [200, {'Content-Type': 'application/json'}, JSON.stringify({users: [
{
id: 1,
slug: 'user-1',
name: 'User 1'
}
]})];
});
store.queryRecord('user', {slug: 'user-1'}).then((user) => {
expect(user).to.be.ok;
expect(user.get('name')).to.equal('User 1');
done();
});
store.queryRecord('user', {slug: 'user-1', include: 'count.posts'}).then((user) => {
expect(user).to.be.ok;
expect(user.get('name')).to.equal('User 1');
expect(user.get('count.posts')).to.equal(5);
done();
});
it('handles "include" parameter when querying single user via slug', function (done) {
server.get('/ghost/api/v0.1/users/slug/user-1/', (request) => {
let params = request.queryParams;
expect(params.include, 'include query').to.equal('roles,count.posts');
return [200, {'Content-Type': 'application/json'}, JSON.stringify({users: [
{
id: 1,
slug: 'user-1',
name: 'User 1',
count: {
posts: 5
}
}
]})];
});
store.queryRecord('user', {slug: 'user-1', include: 'count.posts'}).then((user) => {
expect(user).to.be.ok;
expect(user.get('name')).to.equal('User 1');
expect(user.get('count.posts')).to.equal(5);
done();
});
});
}
);
});
});

View File

@ -1,46 +1,41 @@
/* jshint expr:true */
import {expect} from 'chai';
import {
describeComponent,
it
} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupComponentTest} from 'ember-mocha';
import hbs from 'htmlbars-inline-precompile';
describeComponent(
'gh-alert',
'Integration: Component: gh-alert',
{
describe('Integration: Component: gh-alert', function () {
setupComponentTest('gh-alert', {
integration: true
},
function () {
it('renders', function () {
this.set('message', {message: 'Test message', type: 'success'});
});
this.render(hbs`{{gh-alert message=message}}`);
it('renders', function () {
this.set('message', {message: 'Test message', type: 'success'});
expect(this.$('article.gh-alert')).to.have.length(1);
let $alert = this.$('.gh-alert');
this.render(hbs`{{gh-alert message=message}}`);
expect($alert.text()).to.match(/Test message/);
});
expect(this.$('article.gh-alert')).to.have.length(1);
let $alert = this.$('.gh-alert');
it('maps message types to CSS classes', function () {
this.set('message', {message: 'Test message', type: 'success'});
expect($alert.text()).to.match(/Test message/);
});
this.render(hbs`{{gh-alert message=message}}`);
let $alert = this.$('.gh-alert');
it('maps message types to CSS classes', function () {
this.set('message', {message: 'Test message', type: 'success'});
this.set('message.type', 'success');
expect($alert.hasClass('gh-alert-green'), 'success class isn\'t green').to.be.true;
this.render(hbs`{{gh-alert message=message}}`);
let $alert = this.$('.gh-alert');
this.set('message.type', 'error');
expect($alert.hasClass('gh-alert-red'), 'success class isn\'t red').to.be.true;
this.set('message.type', 'success');
expect($alert.hasClass('gh-alert-green'), 'success class isn\'t green').to.be.true;
this.set('message.type', 'warn');
expect($alert.hasClass('gh-alert-yellow'), 'success class isn\'t yellow').to.be.true;
this.set('message.type', 'error');
expect($alert.hasClass('gh-alert-red'), 'success class isn\'t red').to.be.true;
this.set('message.type', 'info');
expect($alert.hasClass('gh-alert-blue'), 'success class isn\'t blue').to.be.true;
});
}
);
this.set('message.type', 'warn');
expect($alert.hasClass('gh-alert-yellow'), 'success class isn\'t yellow').to.be.true;
this.set('message.type', 'info');
expect($alert.hasClass('gh-alert-blue'), 'success class isn\'t blue').to.be.true;
});
});

View File

@ -1,9 +1,7 @@
/* jshint expr:true */
import {expect} from 'chai';
import {
describeComponent,
it
} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupComponentTest} from 'ember-mocha';
import hbs from 'htmlbars-inline-precompile';
import Service from 'ember-service';
import {A as emberA} from 'ember-array/utils';
@ -12,45 +10,42 @@ let notificationsStub = Service.extend({
alerts: emberA()
});
describeComponent(
'gh-alerts',
'Integration: Component: gh-alerts',
{
describe('Integration: Component: gh-alerts', function () {
setupComponentTest('gh-alerts', {
integration: true
},
function () {
beforeEach(function () {
this.register('service:notifications', notificationsStub);
this.inject.service('notifications', {as: 'notifications'});
});
this.set('notifications.alerts', [
{message: 'First', type: 'error'},
{message: 'Second', type: 'warn'}
]);
});
beforeEach(function () {
this.register('service:notifications', notificationsStub);
this.inject.service('notifications', {as: 'notifications'});
it('renders', function () {
this.render(hbs`{{gh-alerts}}`);
expect(this.$('.gh-alerts').length).to.equal(1);
expect(this.$('.gh-alerts').children().length).to.equal(2);
this.set('notifications.alerts', [
{message: 'First', type: 'error'},
{message: 'Second', type: 'warn'}
]);
});
this.set('notifications.alerts', emberA());
expect(this.$('.gh-alerts').children().length).to.equal(0);
});
it('renders', function () {
this.render(hbs`{{gh-alerts}}`);
expect(this.$('.gh-alerts').length).to.equal(1);
expect(this.$('.gh-alerts').children().length).to.equal(2);
it('triggers "notify" action when message count changes', function () {
let expectedCount = 0;
this.set('notifications.alerts', emberA());
expect(this.$('.gh-alerts').children().length).to.equal(0);
});
// test double for notify action
this.set('notify', (count) => expect(count).to.equal(expectedCount));
it('triggers "notify" action when message count changes', function () {
let expectedCount = 0;
this.render(hbs`{{gh-alerts notify=(action notify)}}`);
// test double for notify action
this.set('notify', (count) => expect(count).to.equal(expectedCount));
expectedCount = 3;
this.get('notifications.alerts').pushObject({message: 'Third', type: 'success'});
this.render(hbs`{{gh-alerts notify=(action notify)}}`);
expectedCount = 0;
this.set('notifications.alerts', emberA());
});
}
);
expectedCount = 3;
this.get('notifications.alerts').pushObject({message: 'Third', type: 'success'});
expectedCount = 0;
this.set('notifications.alerts', emberA());
});
});

View File

@ -1,51 +1,46 @@
/* jshint expr:true */
import {expect} from 'chai';
import {
describeComponent,
it
} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupComponentTest} from 'ember-mocha';
import hbs from 'htmlbars-inline-precompile';
import run from 'ember-runloop';
describeComponent(
'gh-cm-editor',
'Integration: Component: gh-cm-editor',
{
describe('Integration: Component: gh-cm-editor', function () {
setupComponentTest('gh-cm-editor', {
integration: true
},
function () {
it('handles editor events', function () {
this.set('text', '');
});
this.render(hbs`{{gh-cm-editor text class="gh-input" update=(action (mut text))}}`);
let input = this.$('.gh-input');
it('handles editor events', function () {
this.set('text', '');
expect(input.hasClass('focused'), 'has focused class on first render')
.to.be.false;
this.render(hbs`{{gh-cm-editor text class="gh-input" update=(action (mut text))}}`);
let input = this.$('.gh-input');
run(() => {
input.find('textarea').trigger('focus');
});
expect(input.hasClass('focused'), 'has focused class on first render')
.to.be.false;
expect(input.hasClass('focused'), 'has focused class after focus')
.to.be.true;
run(() => {
input.find('textarea').trigger('blur');
});
expect(input.hasClass('focused'), 'loses focused class on blur')
.to.be.false;
run(() => {
// access CodeMirror directly as it doesn't pick up changes
// to the textarea
let cm = input.find('.CodeMirror').get(0).CodeMirror;
cm.setValue('Testing');
});
expect(this.get('text'), 'text value after CM editor change')
.to.equal('Testing');
run(() => {
input.find('textarea').trigger('focus');
});
}
);
expect(input.hasClass('focused'), 'has focused class after focus')
.to.be.true;
run(() => {
input.find('textarea').trigger('blur');
});
expect(input.hasClass('focused'), 'loses focused class on blur')
.to.be.false;
run(() => {
// access CodeMirror directly as it doesn't pick up changes
// to the textarea
let cm = input.find('.CodeMirror').get(0).CodeMirror;
cm.setValue('Testing');
});
expect(this.get('text'), 'text value after CM editor change')
.to.equal('Testing');
});
});

View File

@ -1,8 +1,6 @@
import {expect} from 'chai';
import {
describeComponent,
it
} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupComponentTest} from 'ember-mocha';
import hbs from 'htmlbars-inline-precompile';
import Service from 'ember-service';
@ -10,48 +8,45 @@ const featureStub = Service.extend({
testFlag: true
});
describeComponent(
'gh-feature-flag',
'Integration: Component: gh-feature-flag',
{
describe('Integration: Component: gh-feature-flag', function() {
setupComponentTest('gh-feature-flag', {
integration: true
},
function() {
beforeEach(function () {
this.register('service:feature', featureStub);
this.inject.service('feature', {as: 'feature'});
});
});
it('renders properties correctly', function () {
this.render(hbs`{{gh-feature-flag "testFlag"}}`);
expect(this.$()).to.have.length(1);
expect(this.$('label').attr('for')).to.equal(this.$('input[type="checkbox"]').attr('id'));
});
beforeEach(function () {
this.register('service:feature', featureStub);
this.inject.service('feature', {as: 'feature'});
});
it('renders correctly when flag is set to true', function () {
this.render(hbs`{{gh-feature-flag "testFlag"}}`);
expect(this.$()).to.have.length(1);
expect(this.$('label input[type="checkbox"]').prop('checked')).to.be.true;
});
it('renders properties correctly', function () {
this.render(hbs`{{gh-feature-flag "testFlag"}}`);
expect(this.$()).to.have.length(1);
expect(this.$('label').attr('for')).to.equal(this.$('input[type="checkbox"]').attr('id'));
});
it('renders correctly when flag is set to false', function () {
this.set('feature.testFlag', false);
it('renders correctly when flag is set to true', function () {
this.render(hbs`{{gh-feature-flag "testFlag"}}`);
expect(this.$()).to.have.length(1);
expect(this.$('label input[type="checkbox"]').prop('checked')).to.be.true;
});
this.render(hbs`{{gh-feature-flag "testFlag"}}`);
expect(this.$()).to.have.length(1);
it('renders correctly when flag is set to false', function () {
this.set('feature.testFlag', false);
expect(this.$('label input[type="checkbox"]').prop('checked')).to.be.false;
});
this.render(hbs`{{gh-feature-flag "testFlag"}}`);
expect(this.$()).to.have.length(1);
it('updates to reflect changes in flag property', function () {
this.render(hbs`{{gh-feature-flag "testFlag"}}`);
expect(this.$()).to.have.length(1);
expect(this.$('label input[type="checkbox"]').prop('checked')).to.be.false;
});
expect(this.$('label input[type="checkbox"]').prop('checked')).to.be.true;
it('updates to reflect changes in flag property', function () {
this.render(hbs`{{gh-feature-flag "testFlag"}}`);
expect(this.$()).to.have.length(1);
this.$('label').click();
expect(this.$('label input[type="checkbox"]').prop('checked')).to.be.true;
expect(this.$('label input[type="checkbox"]').prop('checked')).to.be.false;
});
}
);
this.$('label').click();
expect(this.$('label input[type="checkbox"]').prop('checked')).to.be.false;
});
});

View File

@ -1,9 +1,7 @@
/* jshint expr:true */
import {expect} from 'chai';
import {
describeComponent,
it
} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupComponentTest} from 'ember-mocha';
import hbs from 'htmlbars-inline-precompile';
import $ from 'jquery';
import run from 'ember-runloop';
@ -37,413 +35,410 @@ const stubFailedUpload = function (server, code, error, delay = 0) {
}, delay);
};
describeComponent(
'gh-file-uploader',
'Integration: Component: gh-file-uploader',
{
describe('Integration: Component: gh-file-uploader', function() {
setupComponentTest('gh-file-uploader', {
integration: true
},
function() {
let server;
});
beforeEach(function () {
server = new Pretender();
this.set('uploadUrl', '/ghost/api/v0.1/uploads/');
let server;
this.register('service:notifications', notificationsStub);
this.inject.service('notifications', {as: 'notifications'});
beforeEach(function () {
server = new Pretender();
this.set('uploadUrl', '/ghost/api/v0.1/uploads/');
this.register('service:notifications', notificationsStub);
this.inject.service('notifications', {as: 'notifications'});
});
afterEach(function () {
server.shutdown();
});
it('renders', function() {
this.render(hbs`{{gh-file-uploader}}`);
expect(this.$('label').text().trim(), 'default label')
.to.equal('Select or drag-and-drop a file');
});
it('allows file input "accept" attribute to be changed', function () {
this.render(hbs`{{gh-file-uploader}}`);
expect(
this.$('input[type="file"]').attr('accept'),
'default "accept" attribute'
).to.equal('text/csv');
this.render(hbs`{{gh-file-uploader accept="application/zip"}}`);
expect(
this.$('input[type="file"]').attr('accept'),
'specified "accept" attribute'
).to.equal('application/zip');
});
it('renders form with supplied label text', function () {
this.set('labelText', 'My label');
this.render(hbs`{{gh-file-uploader labelText=labelText}}`);
expect(this.$('label').text().trim(), 'label')
.to.equal('My label');
});
it('generates request to supplied endpoint', function (done) {
stubSuccessfulUpload(server);
this.render(hbs`{{gh-file-uploader url=uploadUrl}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.csv'});
wait().then(() => {
expect(server.handledRequests.length).to.equal(1);
expect(server.handledRequests[0].url).to.equal('/ghost/api/v0.1/uploads/');
done();
});
});
afterEach(function () {
server.shutdown();
it('fires uploadSuccess action on successful upload', function (done) {
let uploadSuccess = sinon.spy();
this.set('uploadSuccess', uploadSuccess);
stubSuccessfulUpload(server);
this.render(hbs`{{gh-file-uploader url=uploadUrl uploadSuccess=(action uploadSuccess)}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.csv'});
wait().then(() => {
expect(uploadSuccess.calledOnce).to.be.true;
expect(uploadSuccess.firstCall.args[0]).to.equal('/content/images/test.png');
done();
});
});
it('renders', function() {
this.render(hbs`{{gh-file-uploader}}`);
it('doesn\'t fire uploadSuccess action on failed upload', function (done) {
let uploadSuccess = sinon.spy();
this.set('uploadSuccess', uploadSuccess);
expect(this.$('label').text().trim(), 'default label')
.to.equal('Select or drag-and-drop a file');
stubFailedUpload(server, 500);
this.render(hbs`{{gh-file-uploader url=uploadUrl uploadSuccess=(action uploadSuccess)}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.csv'});
wait().then(() => {
expect(uploadSuccess.calledOnce).to.be.false;
done();
});
});
it('allows file input "accept" attribute to be changed', function () {
this.render(hbs`{{gh-file-uploader}}`);
expect(
this.$('input[type="file"]').attr('accept'),
'default "accept" attribute'
).to.equal('text/csv');
it('fires fileSelected action on file selection', function (done) {
let fileSelected = sinon.spy();
this.set('fileSelected', fileSelected);
this.render(hbs`{{gh-file-uploader accept="application/zip"}}`);
expect(
this.$('input[type="file"]').attr('accept'),
'specified "accept" attribute'
).to.equal('application/zip');
stubSuccessfulUpload(server);
this.render(hbs`{{gh-file-uploader url=uploadUrl fileSelected=(action fileSelected)}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.csv'});
wait().then(() => {
expect(fileSelected.calledOnce).to.be.true;
expect(fileSelected.args[0]).to.not.be.blank;
done();
});
});
it('renders form with supplied label text', function () {
this.set('labelText', 'My label');
this.render(hbs`{{gh-file-uploader labelText=labelText}}`);
it('fires uploadStarted action on upload start', function (done) {
let uploadStarted = sinon.spy();
this.set('uploadStarted', uploadStarted);
expect(this.$('label').text().trim(), 'label')
.to.equal('My label');
stubSuccessfulUpload(server);
this.render(hbs`{{gh-file-uploader url=uploadUrl uploadStarted=(action uploadStarted)}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.csv'});
wait().then(() => {
expect(uploadStarted.calledOnce).to.be.true;
done();
});
});
it('generates request to supplied endpoint', function (done) {
stubSuccessfulUpload(server);
it('fires uploadFinished action on successful upload', function (done) {
let uploadFinished = sinon.spy();
this.set('uploadFinished', uploadFinished);
this.render(hbs`{{gh-file-uploader url=uploadUrl}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.csv'});
stubSuccessfulUpload(server);
wait().then(() => {
expect(server.handledRequests.length).to.equal(1);
expect(server.handledRequests[0].url).to.equal('/ghost/api/v0.1/uploads/');
done();
});
this.render(hbs`{{gh-file-uploader url=uploadUrl uploadFinished=(action uploadFinished)}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.csv'});
wait().then(() => {
expect(uploadFinished.calledOnce).to.be.true;
done();
});
});
it('fires uploadSuccess action on successful upload', function (done) {
let uploadSuccess = sinon.spy();
this.set('uploadSuccess', uploadSuccess);
it('fires uploadFinished action on failed upload', function (done) {
let uploadFinished = sinon.spy();
this.set('uploadFinished', uploadFinished);
stubSuccessfulUpload(server);
stubFailedUpload(server);
this.render(hbs`{{gh-file-uploader url=uploadUrl uploadSuccess=(action uploadSuccess)}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.csv'});
this.render(hbs`{{gh-file-uploader url=uploadUrl uploadFinished=(action uploadFinished)}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.csv'});
wait().then(() => {
expect(uploadSuccess.calledOnce).to.be.true;
expect(uploadSuccess.firstCall.args[0]).to.equal('/content/images/test.png');
done();
});
wait().then(() => {
expect(uploadFinished.calledOnce).to.be.true;
done();
});
});
it('doesn\'t fire uploadSuccess action on failed upload', function (done) {
let uploadSuccess = sinon.spy();
this.set('uploadSuccess', uploadSuccess);
it('displays invalid file type error', function (done) {
stubFailedUpload(server, 415, 'UnsupportedMediaTypeError');
this.render(hbs`{{gh-file-uploader url=uploadUrl}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.csv'});
stubFailedUpload(server, 500);
this.render(hbs`{{gh-file-uploader url=uploadUrl uploadSuccess=(action uploadSuccess)}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.csv'});
wait().then(() => {
expect(uploadSuccess.calledOnce).to.be.false;
done();
});
wait().then(() => {
expect(this.$('.failed').length, 'error message is displayed').to.equal(1);
expect(this.$('.failed').text()).to.match(/The file type you uploaded is not supported/);
expect(this.$('.btn-green').length, 'reset button is displayed').to.equal(1);
expect(this.$('.btn-green').text()).to.equal('Try Again');
done();
});
});
it('fires fileSelected action on file selection', function (done) {
let fileSelected = sinon.spy();
this.set('fileSelected', fileSelected);
it('displays file too large for server error', function (done) {
stubFailedUpload(server, 413, 'RequestEntityTooLargeError');
this.render(hbs`{{gh-file-uploader url=uploadUrl}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.csv'});
stubSuccessfulUpload(server);
this.render(hbs`{{gh-file-uploader url=uploadUrl fileSelected=(action fileSelected)}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.csv'});
wait().then(() => {
expect(fileSelected.calledOnce).to.be.true;
expect(fileSelected.args[0]).to.not.be.blank;
done();
});
wait().then(() => {
expect(this.$('.failed').length, 'error message is displayed').to.equal(1);
expect(this.$('.failed').text()).to.match(/The file you uploaded was larger/);
done();
});
});
it('fires uploadStarted action on upload start', function (done) {
let uploadStarted = sinon.spy();
this.set('uploadStarted', uploadStarted);
stubSuccessfulUpload(server);
this.render(hbs`{{gh-file-uploader url=uploadUrl uploadStarted=(action uploadStarted)}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.csv'});
wait().then(() => {
expect(uploadStarted.calledOnce).to.be.true;
done();
});
it('handles file too large error directly from the web server', function (done) {
server.post('/ghost/api/v0.1/uploads/', function () {
return [413, {}, ''];
});
this.render(hbs`{{gh-file-uploader url=uploadUrl}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.csv'});
it('fires uploadFinished action on successful upload', function (done) {
let uploadFinished = sinon.spy();
this.set('uploadFinished', uploadFinished);
stubSuccessfulUpload(server);
this.render(hbs`{{gh-file-uploader url=uploadUrl uploadFinished=(action uploadFinished)}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.csv'});
wait().then(() => {
expect(uploadFinished.calledOnce).to.be.true;
done();
});
wait().then(() => {
expect(this.$('.failed').length, 'error message is displayed').to.equal(1);
expect(this.$('.failed').text()).to.match(/The file you uploaded was larger/);
done();
});
});
it('fires uploadFinished action on failed upload', function (done) {
let uploadFinished = sinon.spy();
this.set('uploadFinished', uploadFinished);
it('displays other server-side error with message', function (done) {
stubFailedUpload(server, 400, 'UnknownError');
this.render(hbs`{{gh-file-uploader url=uploadUrl}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.csv'});
stubFailedUpload(server);
this.render(hbs`{{gh-file-uploader url=uploadUrl uploadFinished=(action uploadFinished)}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.csv'});
wait().then(() => {
expect(uploadFinished.calledOnce).to.be.true;
done();
});
wait().then(() => {
expect(this.$('.failed').length, 'error message is displayed').to.equal(1);
expect(this.$('.failed').text()).to.match(/Error: UnknownError/);
done();
});
});
it('displays invalid file type error', function (done) {
stubFailedUpload(server, 415, 'UnsupportedMediaTypeError');
this.render(hbs`{{gh-file-uploader url=uploadUrl}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.csv'});
wait().then(() => {
expect(this.$('.failed').length, 'error message is displayed').to.equal(1);
expect(this.$('.failed').text()).to.match(/The file type you uploaded is not supported/);
expect(this.$('.btn-green').length, 'reset button is displayed').to.equal(1);
expect(this.$('.btn-green').text()).to.equal('Try Again');
done();
});
it('handles unknown failure', function (done) {
server.post('/ghost/api/v0.1/uploads/', function () {
return [500, {'Content-Type': 'application/json'}, ''];
});
this.render(hbs`{{gh-file-uploader url=uploadUrl}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.csv'});
it('displays file too large for server error', function (done) {
stubFailedUpload(server, 413, 'RequestEntityTooLargeError');
this.render(hbs`{{gh-file-uploader url=uploadUrl}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.csv'});
wait().then(() => {
expect(this.$('.failed').length, 'error message is displayed').to.equal(1);
expect(this.$('.failed').text()).to.match(/The file you uploaded was larger/);
done();
});
wait().then(() => {
expect(this.$('.failed').length, 'error message is displayed').to.equal(1);
expect(this.$('.failed').text()).to.match(/Something went wrong/);
done();
});
});
it('handles file too large error directly from the web server', function (done) {
server.post('/ghost/api/v0.1/uploads/', function () {
return [413, {}, ''];
});
this.render(hbs`{{gh-file-uploader url=uploadUrl}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.csv'});
it('triggers notifications.showAPIError for VersionMismatchError', function (done) {
let showAPIError = sinon.spy();
this.set('notifications.showAPIError', showAPIError);
wait().then(() => {
expect(this.$('.failed').length, 'error message is displayed').to.equal(1);
expect(this.$('.failed').text()).to.match(/The file you uploaded was larger/);
done();
});
stubFailedUpload(server, 400, 'VersionMismatchError');
this.render(hbs`{{gh-file-uploader url=uploadUrl}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.csv'});
wait().then(() => {
expect(showAPIError.calledOnce).to.be.true;
done();
});
});
it('displays other server-side error with message', function (done) {
stubFailedUpload(server, 400, 'UnknownError');
this.render(hbs`{{gh-file-uploader url=uploadUrl}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.csv'});
it('doesn\'t trigger notifications.showAPIError for other errors', function (done) {
let showAPIError = sinon.spy();
this.set('notifications.showAPIError', showAPIError);
wait().then(() => {
expect(this.$('.failed').length, 'error message is displayed').to.equal(1);
expect(this.$('.failed').text()).to.match(/Error: UnknownError/);
done();
});
stubFailedUpload(server, 400, 'UnknownError');
this.render(hbs`{{gh-file-uploader url=uploadUrl}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.csv'});
wait().then(() => {
expect(showAPIError.called).to.be.false;
done();
});
});
it('handles unknown failure', function (done) {
server.post('/ghost/api/v0.1/uploads/', function () {
return [500, {'Content-Type': 'application/json'}, ''];
});
this.render(hbs`{{gh-file-uploader url=uploadUrl}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.csv'});
wait().then(() => {
expect(this.$('.failed').length, 'error message is displayed').to.equal(1);
expect(this.$('.failed').text()).to.match(/Something went wrong/);
done();
});
});
it('triggers notifications.showAPIError for VersionMismatchError', function (done) {
let showAPIError = sinon.spy();
this.set('notifications.showAPIError', showAPIError);
stubFailedUpload(server, 400, 'VersionMismatchError');
this.render(hbs`{{gh-file-uploader url=uploadUrl}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.csv'});
wait().then(() => {
expect(showAPIError.calledOnce).to.be.true;
done();
});
});
it('doesn\'t trigger notifications.showAPIError for other errors', function (done) {
let showAPIError = sinon.spy();
this.set('notifications.showAPIError', showAPIError);
stubFailedUpload(server, 400, 'UnknownError');
this.render(hbs`{{gh-file-uploader url=uploadUrl}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.csv'});
wait().then(() => {
expect(showAPIError.called).to.be.false;
done();
});
});
it('can be reset after a failed upload', function (done) {
stubFailedUpload(server, 400, 'UnknownError');
this.render(hbs`{{gh-file-uploader url=uploadUrl}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.csv'});
wait().then(() => {
run(() => {
this.$('.btn-green').click();
});
});
wait().then(() => {
expect(this.$('input[type="file"]').length).to.equal(1);
done();
});
});
it('displays upload progress', function (done) {
this.set('done', done);
// pretender fires a progress event every 50ms
stubSuccessfulUpload(server, 150);
this.render(hbs`{{gh-file-uploader url=uploadUrl uploadFinished=(action done)}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.csv'});
// after 75ms we should have had one progress event
run.later(this, function () {
expect(this.$('.progress .bar').length).to.equal(1);
let [, percentageWidth] = this.$('.progress .bar').attr('style').match(/width: (\d+)%?/);
expect(percentageWidth).to.be.above(0);
expect(percentageWidth).to.be.below(100);
}, 75);
});
it('handles drag over/leave', function () {
this.render(hbs`{{gh-file-uploader}}`);
it('can be reset after a failed upload', function (done) {
stubFailedUpload(server, 400, 'UnknownError');
this.render(hbs`{{gh-file-uploader url=uploadUrl}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.csv'});
wait().then(() => {
run(() => {
// eslint-disable-next-line new-cap
let dragover = $.Event('dragover', {
dataTransfer: {
files: []
}
});
this.$('.gh-image-uploader').trigger(dragover);
this.$('.btn-green').click();
});
expect(this.$('.gh-image-uploader').hasClass('-drag-over'), 'has drag-over class').to.be.true;
run(() => {
this.$('.gh-image-uploader').trigger('dragleave');
});
expect(this.$('.gh-image-uploader').hasClass('-drag-over'), 'has drag-over class').to.be.false;
});
it('triggers file upload on file drop', function (done) {
let uploadSuccess = sinon.spy();
wait().then(() => {
expect(this.$('input[type="file"]').length).to.equal(1);
done();
});
});
it('displays upload progress', function (done) {
this.set('done', done);
// pretender fires a progress event every 50ms
stubSuccessfulUpload(server, 150);
this.render(hbs`{{gh-file-uploader url=uploadUrl uploadFinished=(action done)}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.csv'});
// after 75ms we should have had one progress event
run.later(this, function () {
expect(this.$('.progress .bar').length).to.equal(1);
let [, percentageWidth] = this.$('.progress .bar').attr('style').match(/width: (\d+)%?/);
expect(percentageWidth).to.be.above(0);
expect(percentageWidth).to.be.below(100);
}, 75);
});
it('handles drag over/leave', function () {
this.render(hbs`{{gh-file-uploader}}`);
run(() => {
// eslint-disable-next-line new-cap
let drop = $.Event('drop', {
let dragover = $.Event('dragover', {
dataTransfer: {
files: [createFile(['test'], {name: 'test.csv'})]
files: []
}
});
this.set('uploadSuccess', uploadSuccess);
stubSuccessfulUpload(server);
this.render(hbs`{{gh-file-uploader url=uploadUrl uploadSuccess=(action uploadSuccess)}}`);
run(() => {
this.$('.gh-image-uploader').trigger(drop);
});
wait().then(() => {
expect(uploadSuccess.calledOnce).to.be.true;
expect(uploadSuccess.firstCall.args[0]).to.equal('/content/images/test.png');
done();
});
this.$('.gh-image-uploader').trigger(dragover);
});
it('validates extension by default', function (done) {
let uploadSuccess = sinon.spy();
let uploadFailed = sinon.spy();
expect(this.$('.gh-image-uploader').hasClass('-drag-over'), 'has drag-over class').to.be.true;
this.set('uploadSuccess', uploadSuccess);
this.set('uploadFailed', uploadFailed);
stubSuccessfulUpload(server);
this.render(hbs`{{gh-file-uploader
url=uploadUrl
uploadSuccess=(action uploadSuccess)
uploadFailed=(action uploadFailed)}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.txt'});
wait().then(() => {
expect(uploadSuccess.called).to.be.false;
expect(uploadFailed.calledOnce).to.be.true;
expect(this.$('.failed').length, 'error message is displayed').to.equal(1);
expect(this.$('.failed').text()).to.match(/The file type you uploaded is not supported/);
done();
});
run(() => {
this.$('.gh-image-uploader').trigger('dragleave');
});
it('uploads if validate action supplied and returns true', function (done) {
let validate = sinon.stub().returns(true);
let uploadSuccess = sinon.spy();
expect(this.$('.gh-image-uploader').hasClass('-drag-over'), 'has drag-over class').to.be.false;
});
this.set('validate', validate);
this.set('uploadSuccess', uploadSuccess);
stubSuccessfulUpload(server);
this.render(hbs`{{gh-file-uploader
url=uploadUrl
uploadSuccess=(action uploadSuccess)
validate=(action validate)}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.csv'});
wait().then(() => {
expect(validate.calledOnce).to.be.true;
expect(uploadSuccess.calledOnce).to.be.true;
done();
});
it('triggers file upload on file drop', function (done) {
let uploadSuccess = sinon.spy();
// eslint-disable-next-line new-cap
let drop = $.Event('drop', {
dataTransfer: {
files: [createFile(['test'], {name: 'test.csv'})]
}
});
it('skips upload and displays error if validate action supplied and doesn\'t return true', function (done) {
let validate = sinon.stub().returns(new UnsupportedMediaTypeError());
let uploadSuccess = sinon.spy();
let uploadFailed = sinon.spy();
this.set('uploadSuccess', uploadSuccess);
this.set('validate', validate);
this.set('uploadSuccess', uploadSuccess);
this.set('uploadFailed', uploadFailed);
stubSuccessfulUpload(server);
this.render(hbs`{{gh-file-uploader url=uploadUrl uploadSuccess=(action uploadSuccess)}}`);
stubSuccessfulUpload(server);
this.render(hbs`{{gh-file-uploader
url=uploadUrl
uploadSuccess=(action uploadSuccess)
uploadFailed=(action uploadFailed)
validate=(action validate)}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.csv'});
wait().then(() => {
expect(validate.calledOnce).to.be.true;
expect(uploadSuccess.called).to.be.false;
expect(uploadFailed.calledOnce).to.be.true;
expect(this.$('.failed').length, 'error message is displayed').to.equal(1);
expect(this.$('.failed').text()).to.match(/The file type you uploaded is not supported/);
done();
});
run(() => {
this.$('.gh-image-uploader').trigger(drop);
});
}
);
wait().then(() => {
expect(uploadSuccess.calledOnce).to.be.true;
expect(uploadSuccess.firstCall.args[0]).to.equal('/content/images/test.png');
done();
});
});
it('validates extension by default', function (done) {
let uploadSuccess = sinon.spy();
let uploadFailed = sinon.spy();
this.set('uploadSuccess', uploadSuccess);
this.set('uploadFailed', uploadFailed);
stubSuccessfulUpload(server);
this.render(hbs`{{gh-file-uploader
url=uploadUrl
uploadSuccess=(action uploadSuccess)
uploadFailed=(action uploadFailed)}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.txt'});
wait().then(() => {
expect(uploadSuccess.called).to.be.false;
expect(uploadFailed.calledOnce).to.be.true;
expect(this.$('.failed').length, 'error message is displayed').to.equal(1);
expect(this.$('.failed').text()).to.match(/The file type you uploaded is not supported/);
done();
});
});
it('uploads if validate action supplied and returns true', function (done) {
let validate = sinon.stub().returns(true);
let uploadSuccess = sinon.spy();
this.set('validate', validate);
this.set('uploadSuccess', uploadSuccess);
stubSuccessfulUpload(server);
this.render(hbs`{{gh-file-uploader
url=uploadUrl
uploadSuccess=(action uploadSuccess)
validate=(action validate)}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.csv'});
wait().then(() => {
expect(validate.calledOnce).to.be.true;
expect(uploadSuccess.calledOnce).to.be.true;
done();
});
});
it('skips upload and displays error if validate action supplied and doesn\'t return true', function (done) {
let validate = sinon.stub().returns(new UnsupportedMediaTypeError());
let uploadSuccess = sinon.spy();
let uploadFailed = sinon.spy();
this.set('validate', validate);
this.set('uploadSuccess', uploadSuccess);
this.set('uploadFailed', uploadFailed);
stubSuccessfulUpload(server);
this.render(hbs`{{gh-file-uploader
url=uploadUrl
uploadSuccess=(action uploadSuccess)
uploadFailed=(action uploadFailed)
validate=(action validate)}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.csv'});
wait().then(() => {
expect(validate.calledOnce).to.be.true;
expect(uploadSuccess.called).to.be.false;
expect(uploadFailed.calledOnce).to.be.true;
expect(this.$('.failed').length, 'error message is displayed').to.equal(1);
expect(this.$('.failed').text()).to.match(/The file type you uploaded is not supported/);
done();
});
});
});

View File

@ -1,10 +1,8 @@
/* jshint expr:true */
import sinon from 'sinon';
import {expect} from 'chai';
import {
describeComponent,
it
} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupComponentTest} from 'ember-mocha';
import hbs from 'htmlbars-inline-precompile';
import Pretender from 'pretender';
import wait from 'ember-test-helpers/wait';
@ -54,529 +52,526 @@ const stubFailedUpload = function (server, code, error, delay = 0) {
}, delay);
};
describeComponent(
'gh-image-upload',
'Integration: Component: gh-image-uploader',
{
describe('Integration: Component: gh-image-uploader', function() {
setupComponentTest('gh-image-upload', {
integration: true
},
function() {
let server;
});
beforeEach(function () {
this.register('service:config', configStub);
this.register('service:session', sessionStub);
this.register('service:notifications', notificationsStub);
this.inject.service('config', {as: 'configService'});
this.inject.service('session', {as: 'sessionService'});
this.inject.service('notifications', {as: 'notifications'});
this.set('update', function () {});
server = new Pretender();
let server;
beforeEach(function () {
this.register('service:config', configStub);
this.register('service:session', sessionStub);
this.register('service:notifications', notificationsStub);
this.inject.service('config', {as: 'configService'});
this.inject.service('session', {as: 'sessionService'});
this.inject.service('notifications', {as: 'notifications'});
this.set('update', function () {});
server = new Pretender();
});
afterEach(function () {
server.shutdown();
});
it('renders', function() {
this.set('image', 'http://example.com/test.png');
this.render(hbs`{{gh-image-uploader image=image}}`);
expect(this.$()).to.have.length(1);
});
it('defaults to upload form', function () {
this.render(hbs`{{gh-image-uploader image=image}}`);
expect(this.$('input[type="file"]').length).to.equal(1);
});
it('defaults to url form with no filestorage config', function () {
this.set('configService.fileStorage', false);
this.render(hbs`{{gh-image-uploader image=image}}`);
expect(this.$('input[type="file"]').length).to.equal(0);
expect(this.$('input[type="text"].url').length).to.equal(1);
});
it('can switch between form types', function () {
this.render(hbs`{{gh-image-uploader image=image}}`);
expect(this.$('input[type="file"]').length).to.equal(1);
expect(this.$('input[type="text"].url').length).to.equal(0);
this.$('a.image-url').click();
expect(this.$('input[type="file"]').length, 'upload form is visible after switch to url form')
.to.equal(0);
expect(this.$('input[type="text"].url').length, 'url form is visible after switch to url form')
.to.equal(1);
this.$('a.image-upload').click();
expect(this.$('input[type="file"]').length, 'upload form is visible after switch to upload form')
.to.equal(1);
expect(this.$('input[type="text"].url').length, 'url form is visible after switch to upload form')
.to.equal(0);
});
it('triggers formChanged action when switching between forms', function () {
let formChanged = sinon.spy();
this.set('formChanged', formChanged);
this.render(hbs`{{gh-image-uploader image=image formChanged=(action formChanged)}}`);
this.$('a.image-url').click();
this.$('a.image-upload').click();
expect(formChanged.calledTwice).to.be.true;
expect(formChanged.firstCall.args[0]).to.equal('url-input');
expect(formChanged.secondCall.args[0]).to.equal('upload');
});
describe('file upload form', function () {
it('renders form with supplied alt text', function () {
this.render(hbs`{{gh-image-uploader image=image altText="text test"}}`);
expect(this.$('.description').text().trim()).to.equal('Upload image of "text test"');
});
afterEach(function () {
server.shutdown();
it('renders form with supplied text', function () {
this.render(hbs`{{gh-image-uploader image=image text="text test"}}`);
expect(this.$('.description').text().trim()).to.equal('text test');
});
it('renders', function() {
this.set('image', 'http://example.com/test.png');
this.render(hbs`{{gh-image-uploader image=image}}`);
expect(this.$()).to.have.length(1);
it('generates request to correct endpoint', function (done) {
stubSuccessfulUpload(server);
this.render(hbs`{{gh-image-uploader image=image update=(action update)}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.png'});
wait().then(() => {
expect(server.handledRequests.length).to.equal(1);
expect(server.handledRequests[0].url).to.equal('/ghost/api/v0.1/uploads/');
expect(server.handledRequests[0].requestHeaders.Authorization).to.be.undefined;
done();
});
});
it('defaults to upload form', function () {
this.render(hbs`{{gh-image-uploader image=image}}`);
expect(this.$('input[type="file"]').length).to.equal(1);
it('adds authentication headers to request', function (done) {
stubSuccessfulUpload(server);
this.get('sessionService').set('isAuthenticated', true);
this.render(hbs`{{gh-image-uploader image=image update=(action update)}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.png'});
wait().then(() => {
let [request] = server.handledRequests;
expect(request.requestHeaders.Authorization).to.equal('Bearer token');
done();
});
});
it('defaults to url form with no filestorage config', function () {
this.set('configService.fileStorage', false);
this.render(hbs`{{gh-image-uploader image=image}}`);
expect(this.$('input[type="file"]').length).to.equal(0);
expect(this.$('input[type="text"].url').length).to.equal(1);
it('fires update action on successful upload', function (done) {
let update = sinon.spy();
this.set('update', update);
stubSuccessfulUpload(server);
this.render(hbs`{{gh-image-uploader image=image update=(action update)}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.png'});
wait().then(() => {
expect(update.calledOnce).to.be.true;
expect(update.firstCall.args[0]).to.equal('/content/images/test.png');
done();
});
});
it('can switch between form types', function () {
this.render(hbs`{{gh-image-uploader image=image}}`);
expect(this.$('input[type="file"]').length).to.equal(1);
expect(this.$('input[type="text"].url').length).to.equal(0);
it('doesn\'t fire update action on failed upload', function (done) {
let update = sinon.spy();
this.set('update', update);
this.$('a.image-url').click();
stubFailedUpload(server, 500);
expect(this.$('input[type="file"]').length, 'upload form is visible after switch to url form')
.to.equal(0);
expect(this.$('input[type="text"].url').length, 'url form is visible after switch to url form')
.to.equal(1);
this.render(hbs`{{gh-image-uploader image=image update=(action update)}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.png'});
this.$('a.image-upload').click();
expect(this.$('input[type="file"]').length, 'upload form is visible after switch to upload form')
.to.equal(1);
expect(this.$('input[type="text"].url').length, 'url form is visible after switch to upload form')
.to.equal(0);
wait().then(() => {
expect(update.calledOnce).to.be.false;
done();
});
});
it('triggers formChanged action when switching between forms', function () {
let formChanged = sinon.spy();
this.set('formChanged', formChanged);
it('fires fileSelected action on file selection', function (done) {
let fileSelected = sinon.spy();
this.set('fileSelected', fileSelected);
this.render(hbs`{{gh-image-uploader image=image formChanged=(action formChanged)}}`);
stubSuccessfulUpload(server);
this.$('a.image-url').click();
this.$('a.image-upload').click();
this.render(hbs`{{gh-image-uploader url=image fileSelected=(action fileSelected) update=(action update)}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.png'});
expect(formChanged.calledTwice).to.be.true;
expect(formChanged.firstCall.args[0]).to.equal('url-input');
expect(formChanged.secondCall.args[0]).to.equal('upload');
wait().then(() => {
expect(fileSelected.calledOnce).to.be.true;
expect(fileSelected.args[0]).to.not.be.blank;
done();
});
});
describe('file upload form', function () {
it('renders form with supplied alt text', function () {
this.render(hbs`{{gh-image-uploader image=image altText="text test"}}`);
expect(this.$('.description').text().trim()).to.equal('Upload image of "text test"');
it('fires uploadStarted action on upload start', function (done) {
let uploadStarted = sinon.spy();
this.set('uploadStarted', uploadStarted);
stubSuccessfulUpload(server);
this.render(hbs`{{gh-image-uploader image=image uploadStarted=(action uploadStarted) update=(action update)}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.png'});
wait().then(() => {
expect(uploadStarted.calledOnce).to.be.true;
done();
});
});
it('renders form with supplied text', function () {
this.render(hbs`{{gh-image-uploader image=image text="text test"}}`);
expect(this.$('.description').text().trim()).to.equal('text test');
it('fires uploadFinished action on successful upload', function (done) {
let uploadFinished = sinon.spy();
this.set('uploadFinished', uploadFinished);
stubSuccessfulUpload(server);
this.render(hbs`{{gh-image-uploader image=image uploadFinished=(action uploadFinished) update=(action update)}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.png'});
wait().then(() => {
expect(uploadFinished.calledOnce).to.be.true;
done();
});
});
it('generates request to correct endpoint', function (done) {
stubSuccessfulUpload(server);
it('fires uploadFinished action on failed upload', function (done) {
let uploadFinished = sinon.spy();
this.set('uploadFinished', uploadFinished);
this.render(hbs`{{gh-image-uploader image=image update=(action update)}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.png'});
stubFailedUpload(server);
wait().then(() => {
expect(server.handledRequests.length).to.equal(1);
expect(server.handledRequests[0].url).to.equal('/ghost/api/v0.1/uploads/');
expect(server.handledRequests[0].requestHeaders.Authorization).to.be.undefined;
done();
});
this.render(hbs`{{gh-image-uploader image=image uploadFinished=(action uploadFinished) update=(action update)}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.png'});
wait().then(() => {
expect(uploadFinished.calledOnce).to.be.true;
done();
});
});
it('adds authentication headers to request', function (done) {
stubSuccessfulUpload(server);
it('displays invalid file type error', function (done) {
stubFailedUpload(server, 415, 'UnsupportedMediaTypeError');
this.render(hbs`{{gh-image-uploader image=image update=(action update)}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.png'});
this.get('sessionService').set('isAuthenticated', true);
this.render(hbs`{{gh-image-uploader image=image update=(action update)}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.png'});
wait().then(() => {
let [request] = server.handledRequests;
expect(request.requestHeaders.Authorization).to.equal('Bearer token');
done();
});
wait().then(() => {
expect(this.$('.failed').length, 'error message is displayed').to.equal(1);
expect(this.$('.failed').text()).to.match(/The image type you uploaded is not supported/);
expect(this.$('.btn-green').length, 'reset button is displayed').to.equal(1);
expect(this.$('.btn-green').text()).to.equal('Try Again');
done();
});
});
it('fires update action on successful upload', function (done) {
let update = sinon.spy();
this.set('update', update);
it('displays file too large for server error', function (done) {
stubFailedUpload(server, 413, 'RequestEntityTooLargeError');
this.render(hbs`{{gh-image-uploader image=image update=(action update)}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.png'});
stubSuccessfulUpload(server);
this.render(hbs`{{gh-image-uploader image=image update=(action update)}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.png'});
wait().then(() => {
expect(update.calledOnce).to.be.true;
expect(update.firstCall.args[0]).to.equal('/content/images/test.png');
done();
});
wait().then(() => {
expect(this.$('.failed').length, 'error message is displayed').to.equal(1);
expect(this.$('.failed').text()).to.match(/The image you uploaded was larger/);
done();
});
});
it('doesn\'t fire update action on failed upload', function (done) {
let update = sinon.spy();
this.set('update', update);
stubFailedUpload(server, 500);
this.render(hbs`{{gh-image-uploader image=image update=(action update)}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.png'});
wait().then(() => {
expect(update.calledOnce).to.be.false;
done();
});
it('handles file too large error directly from the web server', function (done) {
server.post('/ghost/api/v0.1/uploads/', function () {
return [413, {}, ''];
});
this.render(hbs`{{gh-image-uploader image=image update=(action update)}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.png'});
it('fires fileSelected action on file selection', function (done) {
let fileSelected = sinon.spy();
this.set('fileSelected', fileSelected);
stubSuccessfulUpload(server);
this.render(hbs`{{gh-image-uploader url=image fileSelected=(action fileSelected) update=(action update)}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.png'});
wait().then(() => {
expect(fileSelected.calledOnce).to.be.true;
expect(fileSelected.args[0]).to.not.be.blank;
done();
});
wait().then(() => {
expect(this.$('.failed').length, 'error message is displayed').to.equal(1);
expect(this.$('.failed').text()).to.match(/The image you uploaded was larger/);
done();
});
});
it('fires uploadStarted action on upload start', function (done) {
let uploadStarted = sinon.spy();
this.set('uploadStarted', uploadStarted);
it('displays other server-side error with message', function (done) {
stubFailedUpload(server, 400, 'UnknownError');
this.render(hbs`{{gh-image-uploader image=image update=(action update)}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.png'});
stubSuccessfulUpload(server);
this.render(hbs`{{gh-image-uploader image=image uploadStarted=(action uploadStarted) update=(action update)}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.png'});
wait().then(() => {
expect(uploadStarted.calledOnce).to.be.true;
done();
});
wait().then(() => {
expect(this.$('.failed').length, 'error message is displayed').to.equal(1);
expect(this.$('.failed').text()).to.match(/Error: UnknownError/);
done();
});
});
it('fires uploadFinished action on successful upload', function (done) {
let uploadFinished = sinon.spy();
this.set('uploadFinished', uploadFinished);
stubSuccessfulUpload(server);
this.render(hbs`{{gh-image-uploader image=image uploadFinished=(action uploadFinished) update=(action update)}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.png'});
wait().then(() => {
expect(uploadFinished.calledOnce).to.be.true;
done();
});
it('handles unknown failure', function (done) {
server.post('/ghost/api/v0.1/uploads/', function () {
return [500, {'Content-Type': 'application/json'}, ''];
});
this.render(hbs`{{gh-image-uploader image=image update=(action update)}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.png'});
it('fires uploadFinished action on failed upload', function (done) {
let uploadFinished = sinon.spy();
this.set('uploadFinished', uploadFinished);
stubFailedUpload(server);
this.render(hbs`{{gh-image-uploader image=image uploadFinished=(action uploadFinished) update=(action update)}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.png'});
wait().then(() => {
expect(uploadFinished.calledOnce).to.be.true;
done();
});
wait().then(() => {
expect(this.$('.failed').length, 'error message is displayed').to.equal(1);
expect(this.$('.failed').text()).to.match(/Something went wrong/);
done();
});
});
it('displays invalid file type error', function (done) {
stubFailedUpload(server, 415, 'UnsupportedMediaTypeError');
this.render(hbs`{{gh-image-uploader image=image update=(action update)}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.png'});
it('triggers notifications.showAPIError for VersionMismatchError', function (done) {
let showAPIError = sinon.spy();
this.set('notifications.showAPIError', showAPIError);
wait().then(() => {
expect(this.$('.failed').length, 'error message is displayed').to.equal(1);
expect(this.$('.failed').text()).to.match(/The image type you uploaded is not supported/);
expect(this.$('.btn-green').length, 'reset button is displayed').to.equal(1);
expect(this.$('.btn-green').text()).to.equal('Try Again');
done();
});
stubFailedUpload(server, 400, 'VersionMismatchError');
this.render(hbs`{{gh-image-uploader image=image update=(action update)}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.png'});
wait().then(() => {
expect(showAPIError.calledOnce).to.be.true;
done();
});
});
it('displays file too large for server error', function (done) {
stubFailedUpload(server, 413, 'RequestEntityTooLargeError');
this.render(hbs`{{gh-image-uploader image=image update=(action update)}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.png'});
it('doesn\'t trigger notifications.showAPIError for other errors', function (done) {
let showAPIError = sinon.spy();
this.set('notifications.showAPIError', showAPIError);
wait().then(() => {
expect(this.$('.failed').length, 'error message is displayed').to.equal(1);
expect(this.$('.failed').text()).to.match(/The image you uploaded was larger/);
done();
});
stubFailedUpload(server, 400, 'UnknownError');
this.render(hbs`{{gh-image-uploader image=image update=(action update)}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.png'});
wait().then(() => {
expect(showAPIError.called).to.be.false;
done();
});
});
it('handles file too large error directly from the web server', function (done) {
server.post('/ghost/api/v0.1/uploads/', function () {
return [413, {}, ''];
});
this.render(hbs`{{gh-image-uploader image=image update=(action update)}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.png'});
wait().then(() => {
expect(this.$('.failed').length, 'error message is displayed').to.equal(1);
expect(this.$('.failed').text()).to.match(/The image you uploaded was larger/);
done();
});
});
it('displays other server-side error with message', function (done) {
stubFailedUpload(server, 400, 'UnknownError');
this.render(hbs`{{gh-image-uploader image=image update=(action update)}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.png'});
wait().then(() => {
expect(this.$('.failed').length, 'error message is displayed').to.equal(1);
expect(this.$('.failed').text()).to.match(/Error: UnknownError/);
done();
});
});
it('handles unknown failure', function (done) {
server.post('/ghost/api/v0.1/uploads/', function () {
return [500, {'Content-Type': 'application/json'}, ''];
});
this.render(hbs`{{gh-image-uploader image=image update=(action update)}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.png'});
wait().then(() => {
expect(this.$('.failed').length, 'error message is displayed').to.equal(1);
expect(this.$('.failed').text()).to.match(/Something went wrong/);
done();
});
});
it('triggers notifications.showAPIError for VersionMismatchError', function (done) {
let showAPIError = sinon.spy();
this.set('notifications.showAPIError', showAPIError);
stubFailedUpload(server, 400, 'VersionMismatchError');
this.render(hbs`{{gh-image-uploader image=image update=(action update)}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.png'});
wait().then(() => {
expect(showAPIError.calledOnce).to.be.true;
done();
});
});
it('doesn\'t trigger notifications.showAPIError for other errors', function (done) {
let showAPIError = sinon.spy();
this.set('notifications.showAPIError', showAPIError);
stubFailedUpload(server, 400, 'UnknownError');
this.render(hbs`{{gh-image-uploader image=image update=(action update)}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.png'});
wait().then(() => {
expect(showAPIError.called).to.be.false;
done();
});
});
it('can be reset after a failed upload', function (done) {
stubFailedUpload(server, 400, 'UnknownError');
this.render(hbs`{{gh-image-uploader image=image update=(action update)}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {type: 'test.png'});
wait().then(() => {
run(() => {
this.$('.btn-green').click();
});
});
wait().then(() => {
expect(this.$('input[type="file"]').length).to.equal(1);
done();
});
});
it('displays upload progress', function (done) {
this.set('done', done);
// pretender fires a progress event every 50ms
stubSuccessfulUpload(server, 150);
this.render(hbs`{{gh-image-uploader image=image uploadFinished=(action done) update=(action update)}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.png'});
// after 75ms we should have had one progress event
run.later(this, function () {
expect(this.$('.progress .bar').length).to.equal(1);
let [, percentageWidth] = this.$('.progress .bar').attr('style').match(/width: (\d+)%?/);
expect(percentageWidth).to.be.above(0);
expect(percentageWidth).to.be.below(100);
}, 75);
});
it('handles drag over/leave', function () {
stubSuccessfulUpload(server);
this.render(hbs`{{gh-image-uploader image=image update=(action update)}}`);
it('can be reset after a failed upload', function (done) {
stubFailedUpload(server, 400, 'UnknownError');
this.render(hbs`{{gh-image-uploader image=image update=(action update)}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {type: 'test.png'});
wait().then(() => {
run(() => {
// eslint-disable-next-line new-cap
let dragover = $.Event('dragover', {
dataTransfer: {
files: []
}
});
this.$('.gh-image-uploader').trigger(dragover);
this.$('.btn-green').click();
});
expect(this.$('.gh-image-uploader').hasClass('-drag-over'), 'has drag-over class').to.be.true;
run(() => {
this.$('.gh-image-uploader').trigger('dragleave');
});
expect(this.$('.gh-image-uploader').hasClass('-drag-over'), 'has drag-over class').to.be.false;
});
it('triggers file upload on file drop', function (done) {
let uploadSuccess = sinon.spy();
wait().then(() => {
expect(this.$('input[type="file"]').length).to.equal(1);
done();
});
});
it('displays upload progress', function (done) {
this.set('done', done);
// pretender fires a progress event every 50ms
stubSuccessfulUpload(server, 150);
this.render(hbs`{{gh-image-uploader image=image uploadFinished=(action done) update=(action update)}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.png'});
// after 75ms we should have had one progress event
run.later(this, function () {
expect(this.$('.progress .bar').length).to.equal(1);
let [, percentageWidth] = this.$('.progress .bar').attr('style').match(/width: (\d+)%?/);
expect(percentageWidth).to.be.above(0);
expect(percentageWidth).to.be.below(100);
}, 75);
});
it('handles drag over/leave', function () {
stubSuccessfulUpload(server);
this.render(hbs`{{gh-image-uploader image=image update=(action update)}}`);
run(() => {
// eslint-disable-next-line new-cap
let drop = $.Event('drop', {
let dragover = $.Event('dragover', {
dataTransfer: {
files: [createFile(['test'], {name: 'test.png'})]
files: []
}
});
this.set('uploadSuccess', uploadSuccess);
stubSuccessfulUpload(server);
this.render(hbs`{{gh-image-uploader uploadSuccess=(action uploadSuccess)}}`);
run(() => {
this.$('.gh-image-uploader').trigger(drop);
});
wait().then(() => {
expect(uploadSuccess.calledOnce).to.be.true;
expect(uploadSuccess.firstCall.args[0]).to.equal('/content/images/test.png');
done();
});
this.$('.gh-image-uploader').trigger(dragover);
});
it('validates extension by default', function (done) {
let uploadSuccess = sinon.spy();
let uploadFailed = sinon.spy();
expect(this.$('.gh-image-uploader').hasClass('-drag-over'), 'has drag-over class').to.be.true;
this.set('uploadSuccess', uploadSuccess);
this.set('uploadFailed', uploadFailed);
stubSuccessfulUpload(server);
this.render(hbs`{{gh-image-uploader
uploadSuccess=(action uploadSuccess)
uploadFailed=(action uploadFailed)}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.json'});
wait().then(() => {
expect(uploadSuccess.called).to.be.false;
expect(uploadFailed.calledOnce).to.be.true;
expect(this.$('.failed').length, 'error message is displayed').to.equal(1);
expect(this.$('.failed').text()).to.match(/The image type you uploaded is not supported/);
done();
});
run(() => {
this.$('.gh-image-uploader').trigger('dragleave');
});
it('uploads if validate action supplied and returns true', function (done) {
let validate = sinon.stub().returns(true);
let uploadSuccess = sinon.spy();
expect(this.$('.gh-image-uploader').hasClass('-drag-over'), 'has drag-over class').to.be.false;
});
this.set('validate', validate);
this.set('uploadSuccess', uploadSuccess);
stubSuccessfulUpload(server);
this.render(hbs`{{gh-image-uploader
uploadSuccess=(action uploadSuccess)
validate=(action validate)}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.txt'});
wait().then(() => {
expect(validate.calledOnce).to.be.true;
expect(uploadSuccess.calledOnce).to.be.true;
done();
});
it('triggers file upload on file drop', function (done) {
let uploadSuccess = sinon.spy();
// eslint-disable-next-line new-cap
let drop = $.Event('drop', {
dataTransfer: {
files: [createFile(['test'], {name: 'test.png'})]
}
});
it('skips upload and displays error if validate action supplied and doesn\'t return true', function (done) {
let validate = sinon.stub().returns(new UnsupportedMediaTypeError());
let uploadSuccess = sinon.spy();
let uploadFailed = sinon.spy();
this.set('uploadSuccess', uploadSuccess);
this.set('validate', validate);
this.set('uploadSuccess', uploadSuccess);
this.set('uploadFailed', uploadFailed);
stubSuccessfulUpload(server);
this.render(hbs`{{gh-image-uploader uploadSuccess=(action uploadSuccess)}}`);
stubSuccessfulUpload(server);
run(() => {
this.$('.gh-image-uploader').trigger(drop);
});
this.render(hbs`{{gh-image-uploader
uploadSuccess=(action uploadSuccess)
uploadFailed=(action uploadFailed)
validate=(action validate)}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.png'});
wait().then(() => {
expect(validate.calledOnce).to.be.true;
expect(uploadSuccess.called).to.be.false;
expect(uploadFailed.calledOnce).to.be.true;
expect(this.$('.failed').length, 'error message is displayed').to.equal(1);
expect(this.$('.failed').text()).to.match(/The image type you uploaded is not supported/);
done();
});
wait().then(() => {
expect(uploadSuccess.calledOnce).to.be.true;
expect(uploadSuccess.firstCall.args[0]).to.equal('/content/images/test.png');
done();
});
});
describe('URL input form', function () {
beforeEach(function () {
this.set('configService.fileStorage', false);
});
it('validates extension by default', function (done) {
let uploadSuccess = sinon.spy();
let uploadFailed = sinon.spy();
it('displays save button by default', function () {
this.set('image', 'http://example.com/test.png');
this.render(hbs`{{gh-image-uploader image=image text="text test"}}`);
expect(this.$('button').length).to.equal(1);
expect(this.$('input[type="text"]').val()).to.equal('http://example.com/test.png');
});
this.set('uploadSuccess', uploadSuccess);
this.set('uploadFailed', uploadFailed);
it('can render without a save button', function () {
this.render(hbs`{{gh-image-uploader image=image saveButton=false text="text test"}}`);
expect(this.$('button').length).to.equal(0);
expect(this.$('.description').text().trim()).to.equal('text test');
});
stubSuccessfulUpload(server);
it('fires update action when save button clicked', function () {
let update = sinon.spy();
this.set('update', update);
this.render(hbs`{{gh-image-uploader
uploadSuccess=(action uploadSuccess)
uploadFailed=(action uploadFailed)}}`);
this.render(hbs`{{gh-image-uploader image=image update=(action update)}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.json'});
this.$('input[type="text"]').val('saved url');
this.$('input[type="text"]').change();
this.$('button.btn-blue').click();
expect(update.calledOnce).to.be.true;
expect(update.firstCall.args[0]).to.equal('saved url');
});
it('fires onInput action when typing URL', function () {
let onInput = sinon.spy();
this.set('onInput', onInput);
this.render(hbs`{{gh-image-uploader image=image onInput=(action onInput)}}`);
this.$('input[type="text"]').val('input url');
this.$('input[type="text"]').change();
expect(onInput.calledOnce).to.be.true;
expect(onInput.firstCall.args[0]).to.equal('input url');
});
it('saves on enter key', function () {
let update = sinon.spy();
this.set('update', update);
this.render(hbs`{{gh-image-uploader image=image update=(action update)}}`);
this.$('input[type="text"]').val('saved url');
this.$('input[type="text"]').change();
this.$('input[type="text"]').trigger(
// eslint-disable-next-line new-cap
$.Event('keyup', {keyCode: keyCodes.enter, which: keyCodes.enter})
);
expect(update.calledOnce).to.be.true;
expect(update.firstCall.args[0]).to.equal('saved url');
wait().then(() => {
expect(uploadSuccess.called).to.be.false;
expect(uploadFailed.calledOnce).to.be.true;
expect(this.$('.failed').length, 'error message is displayed').to.equal(1);
expect(this.$('.failed').text()).to.match(/The image type you uploaded is not supported/);
done();
});
});
}
);
it('uploads if validate action supplied and returns true', function (done) {
let validate = sinon.stub().returns(true);
let uploadSuccess = sinon.spy();
this.set('validate', validate);
this.set('uploadSuccess', uploadSuccess);
stubSuccessfulUpload(server);
this.render(hbs`{{gh-image-uploader
uploadSuccess=(action uploadSuccess)
validate=(action validate)}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.txt'});
wait().then(() => {
expect(validate.calledOnce).to.be.true;
expect(uploadSuccess.calledOnce).to.be.true;
done();
});
});
it('skips upload and displays error if validate action supplied and doesn\'t return true', function (done) {
let validate = sinon.stub().returns(new UnsupportedMediaTypeError());
let uploadSuccess = sinon.spy();
let uploadFailed = sinon.spy();
this.set('validate', validate);
this.set('uploadSuccess', uploadSuccess);
this.set('uploadFailed', uploadFailed);
stubSuccessfulUpload(server);
this.render(hbs`{{gh-image-uploader
uploadSuccess=(action uploadSuccess)
uploadFailed=(action uploadFailed)
validate=(action validate)}}`);
fileUpload(this.$('input[type="file"]'), ['test'], {name: 'test.png'});
wait().then(() => {
expect(validate.calledOnce).to.be.true;
expect(uploadSuccess.called).to.be.false;
expect(uploadFailed.calledOnce).to.be.true;
expect(this.$('.failed').length, 'error message is displayed').to.equal(1);
expect(this.$('.failed').text()).to.match(/The image type you uploaded is not supported/);
done();
});
});
});
describe('URL input form', function () {
beforeEach(function () {
this.set('configService.fileStorage', false);
});
it('displays save button by default', function () {
this.set('image', 'http://example.com/test.png');
this.render(hbs`{{gh-image-uploader image=image text="text test"}}`);
expect(this.$('button').length).to.equal(1);
expect(this.$('input[type="text"]').val()).to.equal('http://example.com/test.png');
});
it('can render without a save button', function () {
this.render(hbs`{{gh-image-uploader image=image saveButton=false text="text test"}}`);
expect(this.$('button').length).to.equal(0);
expect(this.$('.description').text().trim()).to.equal('text test');
});
it('fires update action when save button clicked', function () {
let update = sinon.spy();
this.set('update', update);
this.render(hbs`{{gh-image-uploader image=image update=(action update)}}`);
this.$('input[type="text"]').val('saved url');
this.$('input[type="text"]').change();
this.$('button.btn-blue').click();
expect(update.calledOnce).to.be.true;
expect(update.firstCall.args[0]).to.equal('saved url');
});
it('fires onInput action when typing URL', function () {
let onInput = sinon.spy();
this.set('onInput', onInput);
this.render(hbs`{{gh-image-uploader image=image onInput=(action onInput)}}`);
this.$('input[type="text"]').val('input url');
this.$('input[type="text"]').change();
expect(onInput.calledOnce).to.be.true;
expect(onInput.firstCall.args[0]).to.equal('input url');
});
it('saves on enter key', function () {
let update = sinon.spy();
this.set('update', update);
this.render(hbs`{{gh-image-uploader image=image update=(action update)}}`);
this.$('input[type="text"]').val('saved url');
this.$('input[type="text"]').change();
this.$('input[type="text"]').trigger(
// eslint-disable-next-line new-cap
$.Event('keyup', {keyCode: keyCodes.enter, which: keyCodes.enter})
);
expect(update.calledOnce).to.be.true;
expect(update.firstCall.args[0]).to.equal('saved url');
});
});
});

View File

@ -1,46 +1,41 @@
/* jshint expr:true */
import {expect} from 'chai';
import {
describeComponent,
it
} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupComponentTest} from 'ember-mocha';
import hbs from 'htmlbars-inline-precompile';
import run from 'ember-runloop';
import sinon from 'sinon';
describeComponent(
'gh-image-uploader-with-preview',
'Integration: Component: gh-image-uploader-with-preview',
{
describe('Integration: Component: gh-image-uploader-with-preview', function() {
setupComponentTest('gh-image-uploader-with-preview', {
integration: true
},
function() {
it('renders image if provided', function() {
this.set('image', 'http://example.com/test.png');
});
this.render(hbs`{{gh-image-uploader-with-preview image=image}}`);
it('renders image if provided', function() {
this.set('image', 'http://example.com/test.png');
expect(this.$('.gh-image-uploader.-with-image').length).to.equal(1);
expect(this.$('img').attr('src')).to.equal('http://example.com/test.png');
this.render(hbs`{{gh-image-uploader-with-preview image=image}}`);
expect(this.$('.gh-image-uploader.-with-image').length).to.equal(1);
expect(this.$('img').attr('src')).to.equal('http://example.com/test.png');
});
it('renders upload form when no image provided', function () {
this.render(hbs`{{gh-image-uploader-with-preview image=image}}`);
expect(this.$('input[type="file"]').length).to.equal(1);
});
it('triggers remove action when delete icon is clicked', function () {
let remove = sinon.spy();
this.set('remove', remove);
this.set('image', 'http://example.com/test.png');
this.render(hbs`{{gh-image-uploader-with-preview image=image remove=(action remove)}}`);
run(() => {
this.$('.icon-trash').click();
});
it('renders upload form when no image provided', function () {
this.render(hbs`{{gh-image-uploader-with-preview image=image}}`);
expect(this.$('input[type="file"]').length).to.equal(1);
});
it('triggers remove action when delete icon is clicked', function () {
let remove = sinon.spy();
this.set('remove', remove);
this.set('image', 'http://example.com/test.png');
this.render(hbs`{{gh-image-uploader-with-preview image=image remove=(action remove)}}`);
run(() => {
this.$('.icon-trash').click();
});
expect(remove.calledOnce).to.be.true;
});
}
);
expect(remove.calledOnce).to.be.true;
});
});

View File

@ -1,74 +1,72 @@
/* jshint expr:true */
import {expect} from 'chai';
import {describeComponent, it} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupComponentTest} from 'ember-mocha';
import hbs from 'htmlbars-inline-precompile';
import $ from 'jquery';
import run from 'ember-runloop';
import NavItem from 'ghost-admin/models/navigation-item';
describeComponent(
'gh-navigation',
'Integration: Component: gh-navigation',
{
describe('Integration: Component: gh-navigation', function () {
setupComponentTest('gh-navigation', {
integration: true
},
function () {
it('renders', function () {
this.render(hbs`{{#gh-navigation}}<div class="js-gh-blognav"><div class="gh-blognav-item"></div></div>{{/gh-navigation}}`);
expect(this.$('section.gh-view')).to.have.length(1);
expect(this.$('.ui-sortable')).to.have.length(1);
});
it('renders', function () {
this.render(hbs`{{#gh-navigation}}<div class="js-gh-blognav"><div class="gh-blognav-item"></div></div>{{/gh-navigation}}`);
expect(this.$('section.gh-view')).to.have.length(1);
expect(this.$('.ui-sortable')).to.have.length(1);
});
it('triggers reorder action', function () {
let navItems = [];
let expectedOldIndex = -1;
let expectedNewIndex = -1;
navItems.pushObject(NavItem.create({label: 'First', url: '/first'}));
navItems.pushObject(NavItem.create({label: 'Second', url: '/second'}));
navItems.pushObject(NavItem.create({label: 'Third', url: '/third'}));
navItems.pushObject(NavItem.create({label: '', url: '', last: true}));
this.set('navigationItems', navItems);
this.set('blogUrl', 'http://localhost:2368');
this.on('moveItem', (oldIndex, newIndex) => {
expect(oldIndex).to.equal(expectedOldIndex);
expect(newIndex).to.equal(expectedNewIndex);
});
it('triggers reorder action', function () {
let navItems = [];
let expectedOldIndex = -1;
let expectedNewIndex = -1;
run(() => {
this.render(hbs `
{{#gh-navigation moveItem="moveItem"}}
<form id="settings-navigation" class="gh-blognav js-gh-blognav" novalidate="novalidate">
{{#each navigationItems as |navItem|}}
{{gh-navitem navItem=navItem baseUrl=blogUrl addItem="addItem" deleteItem="deleteItem" updateUrl="updateUrl"}}
{{/each}}
</form>
{{/gh-navigation}}`);
});
navItems.pushObject(NavItem.create({label: 'First', url: '/first'}));
navItems.pushObject(NavItem.create({label: 'Second', url: '/second'}));
navItems.pushObject(NavItem.create({label: 'Third', url: '/third'}));
navItems.pushObject(NavItem.create({label: '', url: '', last: true}));
this.set('navigationItems', navItems);
this.set('blogUrl', 'http://localhost:2368');
// check it renders the nav item rows
expect(this.$('.gh-blognav-item')).to.have.length(4);
this.on('moveItem', (oldIndex, newIndex) => {
expect(oldIndex).to.equal(expectedOldIndex);
expect(newIndex).to.equal(expectedNewIndex);
});
run(() => {
this.render(hbs `
{{#gh-navigation moveItem="moveItem"}}
<form id="settings-navigation" class="gh-blognav js-gh-blognav" novalidate="novalidate">
{{#each navigationItems as |navItem|}}
{{gh-navitem navItem=navItem baseUrl=blogUrl addItem="addItem" deleteItem="deleteItem" updateUrl="updateUrl"}}
{{/each}}
</form>
{{/gh-navigation}}`);
});
// check it renders the nav item rows
expect(this.$('.gh-blognav-item')).to.have.length(4);
// move second item up one
expectedOldIndex = 1;
expectedNewIndex = 0;
run(() => {
$(this.$('.gh-blognav-item')[1]).simulateDragSortable({
move: -1,
handle: '.gh-blognav-grab'
});
});
// move second item down one
expectedOldIndex = 1;
expectedNewIndex = 2;
run(() => {
$(this.$('.gh-blognav-item')[1]).simulateDragSortable({
move: 1,
handle: '.gh-blognav-grab'
});
// move second item up one
expectedOldIndex = 1;
expectedNewIndex = 0;
run(() => {
$(this.$('.gh-blognav-item')[1]).simulateDragSortable({
move: -1,
handle: '.gh-blognav-grab'
});
});
}
);
// move second item down one
expectedOldIndex = 1;
expectedNewIndex = 2;
run(() => {
$(this.$('.gh-blognav-item')[1]).simulateDragSortable({
move: 1,
handle: '.gh-blognav-grab'
});
});
});
});

View File

@ -1,111 +1,109 @@
/* jshint expr:true */
import {expect} from 'chai';
import {describeComponent, it} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupComponentTest} from 'ember-mocha';
import hbs from 'htmlbars-inline-precompile';
import NavItem from 'ghost-admin/models/navigation-item';
describeComponent(
'gh-navitem',
'Integration: Component: gh-navitem',
{
describe('Integration: Component: gh-navitem', function () {
setupComponentTest('gh-navitem', {
integration: true
},
function () {
beforeEach(function () {
this.set('baseUrl', 'http://localhost:2368');
});
beforeEach(function () {
this.set('baseUrl', 'http://localhost:2368');
});
it('renders', function () {
this.set('navItem', NavItem.create({label: 'Test', url: '/url'}));
this.render(hbs`{{gh-navitem navItem=navItem baseUrl=baseUrl}}`);
let $item = this.$('.gh-blognav-item');
expect($item.find('.gh-blognav-grab').length).to.equal(1);
expect($item.find('.gh-blognav-label').length).to.equal(1);
expect($item.find('.gh-blognav-url').length).to.equal(1);
expect($item.find('.gh-blognav-delete').length).to.equal(1);
// doesn't show any errors
expect($item.hasClass('gh-blognav-item--error')).to.be.false;
expect($item.find('.error').length).to.equal(0);
expect($item.find('.response:visible').length).to.equal(0);
});
it('doesn\'t show drag handle for new items', function () {
this.set('navItem', NavItem.create({label: 'Test', url: '/url', isNew: true}));
this.render(hbs`{{gh-navitem navItem=navItem baseUrl=baseUrl}}`);
let $item = this.$('.gh-blognav-item');
expect($item.find('.gh-blognav-grab').length).to.equal(0);
});
it('shows add button for new items', function () {
this.set('navItem', NavItem.create({label: 'Test', url: '/url', isNew: true}));
this.render(hbs`{{gh-navitem navItem=navItem baseUrl=baseUrl}}`);
let $item = this.$('.gh-blognav-item');
expect($item.find('.gh-blognav-add').length).to.equal(1);
expect($item.find('.gh-blognav-delete').length).to.equal(0);
});
it('triggers delete action', function () {
this.set('navItem', NavItem.create({label: 'Test', url: '/url'}));
let deleteActionCallCount = 0;
this.on('deleteItem', (navItem) => {
expect(navItem).to.equal(this.get('navItem'));
deleteActionCallCount++;
});
it('renders', function () {
this.set('navItem', NavItem.create({label: 'Test', url: '/url'}));
this.render(hbs`{{gh-navitem navItem=navItem baseUrl=baseUrl deleteItem="deleteItem"}}`);
this.$('.gh-blognav-delete').trigger('click');
this.render(hbs`{{gh-navitem navItem=navItem baseUrl=baseUrl}}`);
let $item = this.$('.gh-blognav-item');
expect(deleteActionCallCount).to.equal(1);
});
expect($item.find('.gh-blognav-grab').length).to.equal(1);
expect($item.find('.gh-blognav-label').length).to.equal(1);
expect($item.find('.gh-blognav-url').length).to.equal(1);
expect($item.find('.gh-blognav-delete').length).to.equal(1);
it('triggers add action', function () {
this.set('navItem', NavItem.create({label: 'Test', url: '/url', isNew: true}));
// doesn't show any errors
expect($item.hasClass('gh-blognav-item--error')).to.be.false;
expect($item.find('.error').length).to.equal(0);
expect($item.find('.response:visible').length).to.equal(0);
let addActionCallCount = 0;
this.on('add', () => {
addActionCallCount++;
});
it('doesn\'t show drag handle for new items', function () {
this.set('navItem', NavItem.create({label: 'Test', url: '/url', isNew: true}));
this.render(hbs`{{gh-navitem navItem=navItem baseUrl=baseUrl addItem="add"}}`);
this.$('.gh-blognav-add').trigger('click');
this.render(hbs`{{gh-navitem navItem=navItem baseUrl=baseUrl}}`);
let $item = this.$('.gh-blognav-item');
expect(addActionCallCount).to.equal(1);
});
expect($item.find('.gh-blognav-grab').length).to.equal(0);
it('triggers update action', function () {
this.set('navItem', NavItem.create({label: 'Test', url: '/url'}));
let updateActionCallCount = 0;
this.on('update', () => {
updateActionCallCount++;
});
it('shows add button for new items', function () {
this.set('navItem', NavItem.create({label: 'Test', url: '/url', isNew: true}));
this.render(hbs`{{gh-navitem navItem=navItem baseUrl=baseUrl updateUrl="update"}}`);
this.$('.gh-blognav-url input').trigger('blur');
this.render(hbs`{{gh-navitem navItem=navItem baseUrl=baseUrl}}`);
let $item = this.$('.gh-blognav-item');
expect(updateActionCallCount).to.equal(1);
});
expect($item.find('.gh-blognav-add').length).to.equal(1);
expect($item.find('.gh-blognav-delete').length).to.equal(0);
});
it('displays inline errors', function () {
this.set('navItem', NavItem.create({label: '', url: ''}));
this.get('navItem').validate();
it('triggers delete action', function () {
this.set('navItem', NavItem.create({label: 'Test', url: '/url'}));
this.render(hbs`{{gh-navitem navItem=navItem baseUrl=baseUrl}}`);
let $item = this.$('.gh-blognav-item');
let deleteActionCallCount = 0;
this.on('deleteItem', (navItem) => {
expect(navItem).to.equal(this.get('navItem'));
deleteActionCallCount++;
});
this.render(hbs`{{gh-navitem navItem=navItem baseUrl=baseUrl deleteItem="deleteItem"}}`);
this.$('.gh-blognav-delete').trigger('click');
expect(deleteActionCallCount).to.equal(1);
});
it('triggers add action', function () {
this.set('navItem', NavItem.create({label: 'Test', url: '/url', isNew: true}));
let addActionCallCount = 0;
this.on('add', () => {
addActionCallCount++;
});
this.render(hbs`{{gh-navitem navItem=navItem baseUrl=baseUrl addItem="add"}}`);
this.$('.gh-blognav-add').trigger('click');
expect(addActionCallCount).to.equal(1);
});
it('triggers update action', function () {
this.set('navItem', NavItem.create({label: 'Test', url: '/url'}));
let updateActionCallCount = 0;
this.on('update', () => {
updateActionCallCount++;
});
this.render(hbs`{{gh-navitem navItem=navItem baseUrl=baseUrl updateUrl="update"}}`);
this.$('.gh-blognav-url input').trigger('blur');
expect(updateActionCallCount).to.equal(1);
});
it('displays inline errors', function () {
this.set('navItem', NavItem.create({label: '', url: ''}));
this.get('navItem').validate();
this.render(hbs`{{gh-navitem navItem=navItem baseUrl=baseUrl}}`);
let $item = this.$('.gh-blognav-item');
expect($item.hasClass('gh-blognav-item--error')).to.be.true;
expect($item.find('.gh-blognav-label').hasClass('error')).to.be.true;
expect($item.find('.gh-blognav-label .response').text().trim()).to.equal('You must specify a label');
expect($item.find('.gh-blognav-url').hasClass('error')).to.be.true;
expect($item.find('.gh-blognav-url .response').text().trim()).to.equal('You must specify a URL or relative path');
});
}
);
expect($item.hasClass('gh-blognav-item--error')).to.be.true;
expect($item.find('.gh-blognav-label').hasClass('error')).to.be.true;
expect($item.find('.gh-blognav-label .response').text().trim()).to.equal('You must specify a label');
expect($item.find('.gh-blognav-url').hasClass('error')).to.be.true;
expect($item.find('.gh-blognav-url .response').text().trim()).to.equal('You must specify a URL or relative path');
});
});

View File

@ -1,9 +1,7 @@
/* jshint scripturl:true */
import {expect} from 'chai';
import {
describeComponent,
it
} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupComponentTest} from 'ember-mocha';
import hbs from 'htmlbars-inline-precompile';
import Ember from 'ember';
@ -13,246 +11,440 @@ const {$, run} = Ember;
// handled as expected (browser auto-sets the domain when using a.href)
let currentUrl = `${window.location.protocol}//${window.location.host}/`;
describeComponent(
'gh-navitem-url-input',
'Integration: Component: gh-navitem-url-input', {
describe('Integration: Component: gh-navitem-url-input', function () {
setupComponentTest('gh-navitem-url-input', {
integration: true
},
function () {
});
beforeEach(function () {
// set defaults
this.set('baseUrl', currentUrl);
this.set('url', '');
this.set('isNew', false);
this.on('clearErrors', function () {
return null;
});
});
it('renders correctly with blank url', function () {
this.render(hbs`
{{gh-navitem-url-input baseUrl=baseUrl url=url isNew=isNew change="updateUrl" clearErrors=(action "clearErrors")}}
`);
let $input = this.$('input');
expect($input).to.have.length(1);
expect($input.hasClass('gh-input')).to.be.true;
expect($input.val()).to.equal(currentUrl);
});
it('renders correctly with relative urls', function () {
this.set('url', '/about');
this.render(hbs`
{{gh-navitem-url-input baseUrl=baseUrl url=url isNew=isNew change="updateUrl" clearErrors=(action "clearErrors")}}
`);
let $input = this.$('input');
expect($input.val()).to.equal(`${currentUrl}about`);
this.set('url', '/about#contact');
expect($input.val()).to.equal(`${currentUrl}about#contact`);
});
it('renders correctly with absolute urls', function () {
this.set('url', 'https://example.com:2368/#test');
this.render(hbs`
{{gh-navitem-url-input baseUrl=baseUrl url=url isNew=isNew change="updateUrl" clearErrors=(action "clearErrors")}}
`);
let $input = this.$('input');
expect($input.val()).to.equal('https://example.com:2368/#test');
this.set('url', 'mailto:test@example.com');
expect($input.val()).to.equal('mailto:test@example.com');
this.set('url', 'tel:01234-5678-90');
expect($input.val()).to.equal('tel:01234-5678-90');
this.set('url', '//protocol-less-url.com');
expect($input.val()).to.equal('//protocol-less-url.com');
this.set('url', '#anchor');
expect($input.val()).to.equal('#anchor');
});
it('deletes base URL on backspace', function () {
this.render(hbs`
{{gh-navitem-url-input baseUrl=baseUrl url=url isNew=isNew change="updateUrl" clearErrors=(action "clearErrors")}}
`);
let $input = this.$('input');
expect($input.val()).to.equal(currentUrl);
run(() => {
// TODO: why is ember's keyEvent helper not available here?
// eslint-disable-next-line new-cap
let e = $.Event('keydown');
e.keyCode = 8;
$input.trigger(e);
});
expect($input.val()).to.equal('');
});
it('deletes base URL on delete', function () {
this.render(hbs`
{{gh-navitem-url-input baseUrl=baseUrl url=url isNew=isNew change="updateUrl" clearErrors=(action "clearErrors")}}
`);
let $input = this.$('input');
expect($input.val()).to.equal(currentUrl);
run(() => {
// TODO: why is ember's keyEvent helper not available here?
// eslint-disable-next-line new-cap
let e = $.Event('keydown');
e.keyCode = 46;
$input.trigger(e);
});
expect($input.val()).to.equal('');
});
it('adds base url to relative urls on blur', function () {
this.on('updateUrl', () => {
return null;
});
this.render(hbs`
{{gh-navitem-url-input baseUrl=baseUrl url=url isNew=isNew change="updateUrl" clearErrors=(action "clearErrors")}}
`);
let $input = this.$('input');
run(() => {
$input.val('/about').trigger('input');
});
run(() => {
$input.trigger('blur');
});
expect($input.val()).to.equal(`${currentUrl}about`);
});
it('adds "mailto:" to email addresses on blur', function () {
this.on('updateUrl', () => {
return null;
});
this.render(hbs`
{{gh-navitem-url-input baseUrl=baseUrl url=url isNew=isNew change="updateUrl" clearErrors=(action "clearErrors")}}
`);
let $input = this.$('input');
run(() => {
$input.val('test@example.com').trigger('input');
});
run(() => {
$input.trigger('blur');
});
expect($input.val()).to.equal('mailto:test@example.com');
// ensure we don't double-up on the mailto:
run(() => {
$input.trigger('blur');
});
expect($input.val()).to.equal('mailto:test@example.com');
});
it('doesn\'t add base url to invalid urls on blur', function () {
this.on('updateUrl', () => {
return null;
});
this.render(hbs`
{{gh-navitem-url-input baseUrl=baseUrl url=url isNew=isNew change="updateUrl" clearErrors=(action "clearErrors")}}
`);
let $input = this.$('input');
let changeValue = function (value) {
run(() => {
$input.val(value).trigger('input').trigger('blur');
});
};
changeValue('with spaces');
expect($input.val()).to.equal('with spaces');
changeValue('/with spaces');
expect($input.val()).to.equal('/with spaces');
});
it('doesn\'t mangle invalid urls on blur', function () {
this.on('updateUrl', () => {
return null;
});
this.render(hbs`
{{gh-navitem-url-input baseUrl=baseUrl url=url isNew=isNew change="updateUrl" clearErrors=(action "clearErrors")}}
`);
let $input = this.$('input');
run(() => {
$input.val(`${currentUrl} /test`).trigger('input').trigger('blur');
});
expect($input.val()).to.equal(`${currentUrl} /test`);
});
it('triggers "change" action on blur', function () {
let changeActionCallCount = 0;
this.on('updateUrl', () => {
changeActionCallCount++;
});
this.render(hbs `
{{gh-navitem-url-input baseUrl=baseUrl url=url isNew=isNew change="updateUrl" clearErrors=(action "clearErrors")}}
`);
let $input = this.$('input');
$input.trigger('blur');
expect(changeActionCallCount).to.equal(1);
});
it('triggers "change" action on enter', function () {
let changeActionCallCount = 0;
this.on('updateUrl', () => {
changeActionCallCount++;
});
this.render(hbs `
{{gh-navitem-url-input baseUrl=baseUrl url=url isNew=isNew change="updateUrl" clearErrors=(action "clearErrors")}}
`);
let $input = this.$('input');
run(() => {
// TODO: why is ember's keyEvent helper not available here?
// eslint-disable-next-line new-cap
let e = $.Event('keypress');
e.keyCode = 13;
$input.trigger(e);
});
expect(changeActionCallCount).to.equal(1);
});
it('triggers "change" action on CMD-S', function () {
let changeActionCallCount = 0;
this.on('updateUrl', () => {
changeActionCallCount++;
});
this.render(hbs `
{{gh-navitem-url-input baseUrl=baseUrl url=url isNew=isNew change="updateUrl" clearErrors=(action "clearErrors")}}
`);
let $input = this.$('input');
run(() => {
// TODO: why is ember's keyEvent helper not available here?
// eslint-disable-next-line new-cap
let e = $.Event('keydown');
e.keyCode = 83;
e.metaKey = true;
$input.trigger(e);
});
expect(changeActionCallCount).to.equal(1);
});
it('sends absolute urls straight through to change action', function () {
let expectedUrl = '';
this.on('updateUrl', (url) => {
expect(url).to.equal(expectedUrl);
});
this.render(hbs `
{{gh-navitem-url-input baseUrl=baseUrl url=url isNew=isNew change="updateUrl" clearErrors=(action "clearErrors")}}
`);
let $input = this.$('input');
let testUrl = (url) => {
expectedUrl = url;
run(() => {
$input.val(url).trigger('input');
});
run(() => {
$input.trigger('blur');
});
};
testUrl('http://example.com');
testUrl('http://example.com/');
testUrl('https://example.com');
testUrl('//example.com');
testUrl('//localhost:1234');
testUrl('#anchor');
testUrl('mailto:test@example.com');
testUrl('tel:12345-567890');
testUrl('javascript:alert("testing");');
});
it('strips base url from relative urls before sending to change action', function () {
let expectedUrl = '';
this.on('updateUrl', (url) => {
expect(url).to.equal(expectedUrl);
});
this.render(hbs `
{{gh-navitem-url-input baseUrl=baseUrl url=url isNew=isNew change="updateUrl" clearErrors=(action "clearErrors")}}
`);
let $input = this.$('input');
let testUrl = (url) => {
expectedUrl = `/${url}`;
run(() => {
$input.val(`${currentUrl}${url}`).trigger('input');
});
run(() => {
$input.trigger('blur');
});
};
testUrl('about/');
testUrl('about#contact');
testUrl('test/nested/');
});
it('handles links to subdomains of blog domain', function () {
let expectedUrl = '';
this.set('baseUrl', 'http://example.com/');
this.on('updateUrl', (url) => {
expect(url).to.equal(expectedUrl);
});
this.render(hbs `
{{gh-navitem-url-input baseUrl=baseUrl url=url isNew=isNew change="updateUrl" clearErrors=(action "clearErrors")}}
`);
let $input = this.$('input');
expectedUrl = 'http://test.example.com/';
run(() => {
$input.val(expectedUrl).trigger('input').trigger('blur');
});
expect($input.val()).to.equal(expectedUrl);
});
it('adds trailing slash to relative URL', function () {
let expectedUrl = '';
this.on('updateUrl', (url) => {
expect(url).to.equal(expectedUrl);
});
this.render(hbs `
{{gh-navitem-url-input baseUrl=baseUrl url=url isNew=isNew change="updateUrl" clearErrors=(action "clearErrors")}}
`);
let $input = this.$('input');
let testUrl = (url) => {
expectedUrl = `/${url}/`;
run(() => {
$input.val(`${currentUrl}${url}`).trigger('input');
});
run(() => {
$input.trigger('blur');
});
};
testUrl('about');
testUrl('test/nested');
});
it('does not add trailing slash on relative URL with [.?#]', function () {
let expectedUrl = '';
this.on('updateUrl', (url) => {
expect(url).to.equal(expectedUrl);
});
this.render(hbs `
{{gh-navitem-url-input baseUrl=baseUrl url=url isNew=isNew change="updateUrl" clearErrors=(action "clearErrors")}}
`);
let $input = this.$('input');
let testUrl = (url) => {
expectedUrl = `/${url}`;
run(() => {
$input.val(`${currentUrl}${url}`).trigger('input');
});
run(() => {
$input.trigger('blur');
});
};
testUrl('about#contact');
testUrl('test/nested.svg');
testUrl('test?gho=sties');
testUrl('test/nested?sli=mer');
});
it('does not add trailing slash on non-relative URLs', function () {
let expectedUrl = '';
this.on('updateUrl', (url) => {
expect(url).to.equal(expectedUrl);
});
this.render(hbs `
{{gh-navitem-url-input baseUrl=baseUrl url=url isNew=isNew change="updateUrl" clearErrors=(action "clearErrors")}}
`);
let $input = this.$('input');
let testUrl = (url) => {
expectedUrl = `/${url}`;
run(() => {
$input.val(`${currentUrl}${url}`).trigger('input');
});
run(() => {
$input.trigger('blur');
});
};
testUrl('http://woo.ff/test');
testUrl('http://me.ow:2342/nested/test');
testUrl('https://wro.om/car#race');
testUrl('https://kabo.om/explosion?really=now');
});
describe('with sub-folder baseUrl', function () {
beforeEach(function () {
// set defaults
this.set('baseUrl', currentUrl);
this.set('url', '');
this.set('isNew', false);
this.on('clearErrors', function () {
return null;
});
this.set('baseUrl', `${currentUrl}blog/`);
});
it('renders correctly with blank url', function () {
this.render(hbs`
it('handles URLs relative to base url', function () {
let expectedUrl = '';
this.on('updateUrl', (url) => {
expect(url).to.equal(expectedUrl);
});
this.render(hbs `
{{gh-navitem-url-input baseUrl=baseUrl url=url isNew=isNew change="updateUrl" clearErrors=(action "clearErrors")}}
`);
let $input = this.$('input');
expect($input).to.have.length(1);
expect($input.hasClass('gh-input')).to.be.true;
expect($input.val()).to.equal(currentUrl);
});
it('renders correctly with relative urls', function () {
this.set('url', '/about');
this.render(hbs`
{{gh-navitem-url-input baseUrl=baseUrl url=url isNew=isNew change="updateUrl" clearErrors=(action "clearErrors")}}
`);
let $input = this.$('input');
expect($input.val()).to.equal(`${currentUrl}about`);
this.set('url', '/about#contact');
expect($input.val()).to.equal(`${currentUrl}about#contact`);
});
it('renders correctly with absolute urls', function () {
this.set('url', 'https://example.com:2368/#test');
this.render(hbs`
{{gh-navitem-url-input baseUrl=baseUrl url=url isNew=isNew change="updateUrl" clearErrors=(action "clearErrors")}}
`);
let $input = this.$('input');
expect($input.val()).to.equal('https://example.com:2368/#test');
this.set('url', 'mailto:test@example.com');
expect($input.val()).to.equal('mailto:test@example.com');
this.set('url', 'tel:01234-5678-90');
expect($input.val()).to.equal('tel:01234-5678-90');
this.set('url', '//protocol-less-url.com');
expect($input.val()).to.equal('//protocol-less-url.com');
this.set('url', '#anchor');
expect($input.val()).to.equal('#anchor');
});
it('deletes base URL on backspace', function () {
this.render(hbs`
{{gh-navitem-url-input baseUrl=baseUrl url=url isNew=isNew change="updateUrl" clearErrors=(action "clearErrors")}}
`);
let $input = this.$('input');
expect($input.val()).to.equal(currentUrl);
run(() => {
// TODO: why is ember's keyEvent helper not available here?
// eslint-disable-next-line new-cap
let e = $.Event('keydown');
e.keyCode = 8;
$input.trigger(e);
});
expect($input.val()).to.equal('');
});
it('deletes base URL on delete', function () {
this.render(hbs`
{{gh-navitem-url-input baseUrl=baseUrl url=url isNew=isNew change="updateUrl" clearErrors=(action "clearErrors")}}
`);
let $input = this.$('input');
expect($input.val()).to.equal(currentUrl);
run(() => {
// TODO: why is ember's keyEvent helper not available here?
// eslint-disable-next-line new-cap
let e = $.Event('keydown');
e.keyCode = 46;
$input.trigger(e);
});
expect($input.val()).to.equal('');
});
it('adds base url to relative urls on blur', function () {
this.on('updateUrl', () => {
return null;
});
this.render(hbs`
{{gh-navitem-url-input baseUrl=baseUrl url=url isNew=isNew change="updateUrl" clearErrors=(action "clearErrors")}}
`);
let $input = this.$('input');
run(() => {
$input.val('/about').trigger('input');
});
run(() => {
$input.trigger('blur');
});
expect($input.val()).to.equal(`${currentUrl}about`);
});
it('adds "mailto:" to email addresses on blur', function () {
this.on('updateUrl', () => {
return null;
});
this.render(hbs`
{{gh-navitem-url-input baseUrl=baseUrl url=url isNew=isNew change="updateUrl" clearErrors=(action "clearErrors")}}
`);
let $input = this.$('input');
run(() => {
$input.val('test@example.com').trigger('input');
});
run(() => {
$input.trigger('blur');
});
expect($input.val()).to.equal('mailto:test@example.com');
// ensure we don't double-up on the mailto:
run(() => {
$input.trigger('blur');
});
expect($input.val()).to.equal('mailto:test@example.com');
});
it('doesn\'t add base url to invalid urls on blur', function () {
this.on('updateUrl', () => {
return null;
});
this.render(hbs`
{{gh-navitem-url-input baseUrl=baseUrl url=url isNew=isNew change="updateUrl" clearErrors=(action "clearErrors")}}
`);
let $input = this.$('input');
let changeValue = function (value) {
let testUrl = (url) => {
expectedUrl = url;
run(() => {
$input.val(value).trigger('input').trigger('blur');
$input.val(`${currentUrl}blog${url}`).trigger('input');
});
run(() => {
$input.trigger('blur');
});
};
changeValue('with spaces');
expect($input.val()).to.equal('with spaces');
changeValue('/with spaces');
expect($input.val()).to.equal('/with spaces');
testUrl('/about/');
testUrl('/about#contact');
testUrl('/test/nested/');
});
it('doesn\'t mangle invalid urls on blur', function () {
this.on('updateUrl', () => {
return null;
});
this.render(hbs`
{{gh-navitem-url-input baseUrl=baseUrl url=url isNew=isNew change="updateUrl" clearErrors=(action "clearErrors")}}
`);
let $input = this.$('input');
run(() => {
$input.val(`${currentUrl} /test`).trigger('input').trigger('blur');
});
expect($input.val()).to.equal(`${currentUrl} /test`);
});
it('triggers "change" action on blur', function () {
let changeActionCallCount = 0;
this.on('updateUrl', () => {
changeActionCallCount++;
});
this.render(hbs `
{{gh-navitem-url-input baseUrl=baseUrl url=url isNew=isNew change="updateUrl" clearErrors=(action "clearErrors")}}
`);
let $input = this.$('input');
$input.trigger('blur');
expect(changeActionCallCount).to.equal(1);
});
it('triggers "change" action on enter', function () {
let changeActionCallCount = 0;
this.on('updateUrl', () => {
changeActionCallCount++;
});
this.render(hbs `
{{gh-navitem-url-input baseUrl=baseUrl url=url isNew=isNew change="updateUrl" clearErrors=(action "clearErrors")}}
`);
let $input = this.$('input');
run(() => {
// TODO: why is ember's keyEvent helper not available here?
// eslint-disable-next-line new-cap
let e = $.Event('keypress');
e.keyCode = 13;
$input.trigger(e);
});
expect(changeActionCallCount).to.equal(1);
});
it('triggers "change" action on CMD-S', function () {
let changeActionCallCount = 0;
this.on('updateUrl', () => {
changeActionCallCount++;
});
this.render(hbs `
{{gh-navitem-url-input baseUrl=baseUrl url=url isNew=isNew change="updateUrl" clearErrors=(action "clearErrors")}}
`);
let $input = this.$('input');
run(() => {
// TODO: why is ember's keyEvent helper not available here?
// eslint-disable-next-line new-cap
let e = $.Event('keydown');
e.keyCode = 83;
e.metaKey = true;
$input.trigger(e);
});
expect(changeActionCallCount).to.equal(1);
});
it('sends absolute urls straight through to change action', function () {
it('handles URLs relative to base host', function () {
let expectedUrl = '';
this.on('updateUrl', (url) => {
@ -274,212 +466,16 @@ describeComponent(
});
};
testUrl('http://example.com');
testUrl('http://example.com/');
testUrl('https://example.com');
testUrl('//example.com');
testUrl('//localhost:1234');
testUrl('#anchor');
testUrl('mailto:test@example.com');
testUrl('tel:12345-567890');
testUrl('javascript:alert("testing");');
testUrl(`http://${window.location.host}`);
testUrl(`https://${window.location.host}`);
testUrl(`http://${window.location.host}/`);
testUrl(`https://${window.location.host}/`);
testUrl(`http://${window.location.host}/test`);
testUrl(`https://${window.location.host}/test`);
testUrl(`http://${window.location.host}/#test`);
testUrl(`https://${window.location.host}/#test`);
testUrl(`http://${window.location.host}/another/folder`);
testUrl(`https://${window.location.host}/another/folder`);
});
it('strips base url from relative urls before sending to change action', function () {
let expectedUrl = '';
this.on('updateUrl', (url) => {
expect(url).to.equal(expectedUrl);
});
this.render(hbs `
{{gh-navitem-url-input baseUrl=baseUrl url=url isNew=isNew change="updateUrl" clearErrors=(action "clearErrors")}}
`);
let $input = this.$('input');
let testUrl = (url) => {
expectedUrl = `/${url}`;
run(() => {
$input.val(`${currentUrl}${url}`).trigger('input');
});
run(() => {
$input.trigger('blur');
});
};
testUrl('about/');
testUrl('about#contact');
testUrl('test/nested/');
});
it('handles links to subdomains of blog domain', function () {
let expectedUrl = '';
this.set('baseUrl', 'http://example.com/');
this.on('updateUrl', (url) => {
expect(url).to.equal(expectedUrl);
});
this.render(hbs `
{{gh-navitem-url-input baseUrl=baseUrl url=url isNew=isNew change="updateUrl" clearErrors=(action "clearErrors")}}
`);
let $input = this.$('input');
expectedUrl = 'http://test.example.com/';
run(() => {
$input.val(expectedUrl).trigger('input').trigger('blur');
});
expect($input.val()).to.equal(expectedUrl);
});
it('adds trailing slash to relative URL', function () {
let expectedUrl = '';
this.on('updateUrl', (url) => {
expect(url).to.equal(expectedUrl);
});
this.render(hbs `
{{gh-navitem-url-input baseUrl=baseUrl url=url isNew=isNew change="updateUrl" clearErrors=(action "clearErrors")}}
`);
let $input = this.$('input');
let testUrl = (url) => {
expectedUrl = `/${url}/`;
run(() => {
$input.val(`${currentUrl}${url}`).trigger('input');
});
run(() => {
$input.trigger('blur');
});
};
testUrl('about');
testUrl('test/nested');
});
it('does not add trailing slash on relative URL with [.?#]', function () {
let expectedUrl = '';
this.on('updateUrl', (url) => {
expect(url).to.equal(expectedUrl);
});
this.render(hbs `
{{gh-navitem-url-input baseUrl=baseUrl url=url isNew=isNew change="updateUrl" clearErrors=(action "clearErrors")}}
`);
let $input = this.$('input');
let testUrl = (url) => {
expectedUrl = `/${url}`;
run(() => {
$input.val(`${currentUrl}${url}`).trigger('input');
});
run(() => {
$input.trigger('blur');
});
};
testUrl('about#contact');
testUrl('test/nested.svg');
testUrl('test?gho=sties');
testUrl('test/nested?sli=mer');
});
it('does not add trailing slash on non-relative URLs', function () {
let expectedUrl = '';
this.on('updateUrl', (url) => {
expect(url).to.equal(expectedUrl);
});
this.render(hbs `
{{gh-navitem-url-input baseUrl=baseUrl url=url isNew=isNew change="updateUrl" clearErrors=(action "clearErrors")}}
`);
let $input = this.$('input');
let testUrl = (url) => {
expectedUrl = `/${url}`;
run(() => {
$input.val(`${currentUrl}${url}`).trigger('input');
});
run(() => {
$input.trigger('blur');
});
};
testUrl('http://woo.ff/test');
testUrl('http://me.ow:2342/nested/test');
testUrl('https://wro.om/car#race');
testUrl('https://kabo.om/explosion?really=now');
});
describe('with sub-folder baseUrl', function () {
beforeEach(function () {
this.set('baseUrl', `${currentUrl}blog/`);
});
it('handles URLs relative to base url', function () {
let expectedUrl = '';
this.on('updateUrl', (url) => {
expect(url).to.equal(expectedUrl);
});
this.render(hbs `
{{gh-navitem-url-input baseUrl=baseUrl url=url isNew=isNew change="updateUrl" clearErrors=(action "clearErrors")}}
`);
let $input = this.$('input');
let testUrl = (url) => {
expectedUrl = url;
run(() => {
$input.val(`${currentUrl}blog${url}`).trigger('input');
});
run(() => {
$input.trigger('blur');
});
};
testUrl('/about/');
testUrl('/about#contact');
testUrl('/test/nested/');
});
it('handles URLs relative to base host', function () {
let expectedUrl = '';
this.on('updateUrl', (url) => {
expect(url).to.equal(expectedUrl);
});
this.render(hbs `
{{gh-navitem-url-input baseUrl=baseUrl url=url isNew=isNew change="updateUrl" clearErrors=(action "clearErrors")}}
`);
let $input = this.$('input');
let testUrl = (url) => {
expectedUrl = url;
run(() => {
$input.val(url).trigger('input');
});
run(() => {
$input.trigger('blur');
});
};
testUrl(`http://${window.location.host}`);
testUrl(`https://${window.location.host}`);
testUrl(`http://${window.location.host}/`);
testUrl(`https://${window.location.host}/`);
testUrl(`http://${window.location.host}/test`);
testUrl(`https://${window.location.host}/test`);
testUrl(`http://${window.location.host}/#test`);
testUrl(`https://${window.location.host}/#test`);
testUrl(`http://${window.location.host}/another/folder`);
testUrl(`https://${window.location.host}/another/folder`);
});
});
}
);
});
});

View File

@ -1,44 +1,39 @@
/* jshint expr:true */
import {expect} from 'chai';
import {
describeComponent,
it
} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupComponentTest} from 'ember-mocha';
import hbs from 'htmlbars-inline-precompile';
describeComponent(
'gh-notification',
'Integration: Component: gh-notification',
{
describe('Integration: Component: gh-notification', function () {
setupComponentTest('gh-notification', {
integration: true
},
function () {
it('renders', function () {
this.set('message', {message: 'Test message', type: 'success'});
});
this.render(hbs`{{gh-notification message=message}}`);
it('renders', function () {
this.set('message', {message: 'Test message', type: 'success'});
expect(this.$('article.gh-notification')).to.have.length(1);
let $notification = this.$('.gh-notification');
this.render(hbs`{{gh-notification message=message}}`);
expect($notification.hasClass('gh-notification-passive')).to.be.true;
expect($notification.text()).to.match(/Test message/);
});
expect(this.$('article.gh-notification')).to.have.length(1);
let $notification = this.$('.gh-notification');
it('maps message types to CSS classes', function () {
this.set('message', {message: 'Test message', type: 'success'});
expect($notification.hasClass('gh-notification-passive')).to.be.true;
expect($notification.text()).to.match(/Test message/);
});
this.render(hbs`{{gh-notification message=message}}`);
let $notification = this.$('.gh-notification');
it('maps message types to CSS classes', function () {
this.set('message', {message: 'Test message', type: 'success'});
this.set('message.type', 'success');
expect($notification.hasClass('gh-notification-green'), 'success class isn\'t green').to.be.true;
this.render(hbs`{{gh-notification message=message}}`);
let $notification = this.$('.gh-notification');
this.set('message.type', 'error');
expect($notification.hasClass('gh-notification-red'), 'success class isn\'t red').to.be.true;
this.set('message.type', 'success');
expect($notification.hasClass('gh-notification-green'), 'success class isn\'t green').to.be.true;
this.set('message.type', 'warn');
expect($notification.hasClass('gh-notification-yellow'), 'success class isn\'t yellow').to.be.true;
});
}
);
this.set('message.type', 'error');
expect($notification.hasClass('gh-notification-red'), 'success class isn\'t red').to.be.true;
this.set('message.type', 'warn');
expect($notification.hasClass('gh-notification-yellow'), 'success class isn\'t yellow').to.be.true;
});
});

View File

@ -1,9 +1,7 @@
/* jshint expr:true */
import {expect} from 'chai';
import {
describeComponent,
it
} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupComponentTest} from 'ember-mocha';
import hbs from 'htmlbars-inline-precompile';
import Service from 'ember-service';
import {A as emberA} from 'ember-array/utils';
@ -12,31 +10,28 @@ let notificationsStub = Service.extend({
notifications: emberA()
});
describeComponent(
'gh-notifications',
'Integration: Component: gh-notifications',
{
describe('Integration: Component: gh-notifications', function () {
setupComponentTest('gh-notifications', {
integration: true
},
function () {
beforeEach(function () {
this.register('service:notifications', notificationsStub);
this.inject.service('notifications', {as: 'notifications'});
});
this.set('notifications.notifications', [
{message: 'First', type: 'error'},
{message: 'Second', type: 'warn'}
]);
});
beforeEach(function () {
this.register('service:notifications', notificationsStub);
this.inject.service('notifications', {as: 'notifications'});
it('renders', function () {
this.render(hbs`{{gh-notifications}}`);
expect(this.$('.gh-notifications').length).to.equal(1);
this.set('notifications.notifications', [
{message: 'First', type: 'error'},
{message: 'Second', type: 'warn'}
]);
});
expect(this.$('.gh-notifications').children().length).to.equal(2);
it('renders', function () {
this.render(hbs`{{gh-notifications}}`);
expect(this.$('.gh-notifications').length).to.equal(1);
this.set('notifications.notifications', emberA());
expect(this.$('.gh-notifications').children().length).to.equal(0);
});
}
);
expect(this.$('.gh-notifications').children().length).to.equal(2);
this.set('notifications.notifications', emberA());
expect(this.$('.gh-notifications').children().length).to.equal(0);
});
});

View File

@ -1,10 +1,8 @@
/* jshint expr:true */
/* global md5 */
import {expect} from 'chai';
import {
describeComponent,
it
} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupComponentTest} from 'ember-mocha';
import hbs from 'htmlbars-inline-precompile';
import Service from 'ember-service';
import run from 'ember-runloop';
@ -34,118 +32,115 @@ const stubUnknownGravatar = function (server) {
});
};
describeComponent(
'gh-profile-image',
'Integration: Component: gh-profile-image',
{
describe('Integration: Component: gh-profile-image', function () {
setupComponentTest('gh-profile-image', {
integration: true
},
function () {
let server;
});
beforeEach(function () {
this.register('service:ghost-paths', pathsStub);
this.inject.service('ghost-paths', {as: 'ghost-paths'});
let server;
server = new Pretender();
stubKnownGravatar(server);
beforeEach(function () {
this.register('service:ghost-paths', pathsStub);
this.inject.service('ghost-paths', {as: 'ghost-paths'});
server = new Pretender();
stubKnownGravatar(server);
});
afterEach(function () {
server.shutdown();
});
it('renders', function () {
this.set('email', '');
this.render(hbs`
{{gh-profile-image email=email}}
`);
expect(this.$()).to.have.length(1);
});
it('renders and tears down ok with fileStorage:false', function () {
this.set('fileStorage', false);
this.render(hbs`
{{gh-profile-image fileStorage=fileStorage}}
`);
expect(this.$()).to.have.length(1);
expect(this.$('input')).to.have.length(0);
}),
it('renders default image if no email supplied', function () {
this.set('email', null);
this.render(hbs`
{{gh-profile-image email=email size=100 debounce=50}}
`);
expect(this.$('.gravatar-img').attr('style'), 'gravatar image style')
.to.be.blank;
});
it('renders the gravatar if valid email supplied', function (done) {
let email = 'test@example.com';
let expectedUrl = `//www.gravatar.com/avatar/${md5(email)}?s=100&d=404`;
this.set('email', email);
this.render(hbs`
{{gh-profile-image email=email size=100 debounce=50}}
`);
// wait for the ajax request to complete
wait().then(() => {
expect(this.$('.gravatar-img').attr('style'), 'gravatar image style')
.to.equal(`background-image: url(${expectedUrl})`);
done();
});
});
afterEach(function () {
server.shutdown();
});
it('doesn\'t add background url if gravatar image doesn\'t exist', function (done) {
stubUnknownGravatar(server);
it('renders', function () {
this.set('email', '');
this.render(hbs`
{{gh-profile-image email=email}}
`);
expect(this.$()).to.have.length(1);
});
it('renders and tears down ok with fileStorage:false', function () {
this.set('fileStorage', false);
this.render(hbs`
{{gh-profile-image fileStorage=fileStorage}}
`);
expect(this.$()).to.have.length(1);
expect(this.$('input')).to.have.length(0);
}),
it('renders default image if no email supplied', function () {
this.set('email', null);
this.render(hbs`
{{gh-profile-image email=email size=100 debounce=50}}
`);
this.render(hbs`
{{gh-profile-image email="test@example.com" size=100 debounce=50}}
`);
wait().then(() => {
expect(this.$('.gravatar-img').attr('style'), 'gravatar image style')
.to.be.blank;
done();
});
});
it('renders the gravatar if valid email supplied', function (done) {
let email = 'test@example.com';
let expectedUrl = `//www.gravatar.com/avatar/${md5(email)}?s=100&d=404`;
it('throttles gravatar loading as email is changed', function (done) {
let email = 'test@example.com';
let expectedUrl = `//www.gravatar.com/avatar/${md5(email)}?s=100&d=404`;
this.set('email', 'test');
this.render(hbs`
{{gh-profile-image email=email size=100 debounce=300}}
`);
run(() => {
this.set('email', email);
this.render(hbs`
{{gh-profile-image email=email size=100 debounce=50}}
`);
// wait for the ajax request to complete
wait().then(() => {
expect(this.$('.gravatar-img').attr('style'), 'gravatar image style')
.to.equal(`background-image: url(${expectedUrl})`);
done();
});
});
it('doesn\'t add background url if gravatar image doesn\'t exist', function (done) {
stubUnknownGravatar(server);
expect(this.$('.gravatar-img').attr('style'), '.gravatar-img background not immediately changed on email change')
.to.be.blank;
this.render(hbs`
{{gh-profile-image email="test@example.com" size=100 debounce=50}}
`);
wait().then(() => {
expect(this.$('.gravatar-img').attr('style'), 'gravatar image style')
.to.be.blank;
done();
});
});
it('throttles gravatar loading as email is changed', function (done) {
let email = 'test@example.com';
let expectedUrl = `//www.gravatar.com/avatar/${md5(email)}?s=100&d=404`;
this.set('email', 'test');
this.render(hbs`
{{gh-profile-image email=email size=100 debounce=300}}
`);
run(() => {
this.set('email', email);
});
expect(this.$('.gravatar-img').attr('style'), '.gravatar-img background not immediately changed on email change')
run.later(this, function () {
expect(this.$('.gravatar-img').attr('style'), '.gravatar-img background still not changed before debounce timeout')
.to.be.blank;
}, 250);
run.later(this, function () {
expect(this.$('.gravatar-img').attr('style'), '.gravatar-img background still not changed before debounce timeout')
.to.be.blank;
}, 250);
run.later(this, function () {
expect(this.$('.gravatar-img').attr('style'), '.gravatar-img background changed after debounce timeout')
.to.equal(`background-image: url(${expectedUrl})`);
done();
}, 400);
});
}
);
run.later(this, function () {
expect(this.$('.gravatar-img').attr('style'), '.gravatar-img background changed after debounce timeout')
.to.equal(`background-image: url(${expectedUrl})`);
done();
}, 400);
});
});

View File

@ -1,50 +1,45 @@
/* jshint expr:true */
import {expect} from 'chai';
import {
describeComponent,
it
} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupComponentTest} from 'ember-mocha';
import hbs from 'htmlbars-inline-precompile';
import run from 'ember-runloop';
import Pretender from 'pretender';
import wait from 'ember-test-helpers/wait';
describeComponent(
'gh-search-input',
'Integration: Component: gh-search-input',
{
describe('Integration: Component: gh-search-input', function () {
setupComponentTest('gh-search-input', {
integration: true
},
function () {
let server;
});
beforeEach(function () {
server = new Pretender();
let server;
beforeEach(function () {
server = new Pretender();
});
afterEach(function () {
server.shutdown();
});
it('renders', function () {
// renders the component on the page
this.render(hbs`{{gh-search-input}}`);
expect(this.$('.ember-power-select-search input')).to.have.length(1);
});
it('opens the dropdown on text entry', function (done) {
this.render(hbs`{{gh-search-input}}`);
// enter text to trigger search
run(() => {
this.$('input[type="search"]').val('test').trigger('input');
});
afterEach(function () {
server.shutdown();
wait().then(() => {
expect(this.$('.ember-basic-dropdown-content').length).to.equal(1);
done();
});
it('renders', function () {
// renders the component on the page
this.render(hbs`{{gh-search-input}}`);
expect(this.$('.ember-power-select-search input')).to.have.length(1);
});
it('opens the dropdown on text entry', function (done) {
this.render(hbs`{{gh-search-input}}`);
// enter text to trigger search
run(() => {
this.$('input[type="search"]').val('test').trigger('input');
});
wait().then(() => {
expect(this.$('.ember-basic-dropdown-content').length).to.equal(1);
done();
});
});
}
);
});
});

View File

@ -1,26 +1,21 @@
/* jshint expr:true */
import {expect} from 'chai';
import {
describeComponent,
it
} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupComponentTest} from 'ember-mocha';
import hbs from 'htmlbars-inline-precompile';
import Table from 'ember-light-table';
describeComponent(
'gh-subscribers-table',
'Integration: Component: gh-subscribers-table',
{
describe('Integration: Component: gh-subscribers-table', function() {
setupComponentTest('gh-subscribers-table', {
integration: true
},
function() {
it('renders', function() {
this.set('table', new Table([], []));
this.set('sortByColumn', function () {});
this.set('delete', function () {});
});
this.render(hbs`{{gh-subscribers-table table=table sortByColumn=(action sortByColumn) delete=(action delete)}}`);
expect(this.$()).to.have.length(1);
});
}
);
it('renders', function() {
this.set('table', new Table([], []));
this.set('sortByColumn', function () {});
this.set('delete', function () {});
this.render(hbs`{{gh-subscribers-table table=table sortByColumn=(action sortByColumn) delete=(action delete)}}`);
expect(this.$()).to.have.length(1);
});
});

View File

@ -1,9 +1,7 @@
/* jshint expr:true */
import {expect} from 'chai';
import {
describeComponent,
it
} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupComponentTest} from 'ember-mocha';
import hbs from 'htmlbars-inline-precompile';
import Service from 'ember-service';
import EmberObject from 'ember-object';
@ -20,305 +18,302 @@ let mediaQueriesStub = Service.extend({
maxWidth600: false
});
describeComponent(
'gh-tag-settings-form',
'Integration: Component: gh-tag-settings-form',
{
describe('Integration: Component: gh-tag-settings-form', function () {
setupComponentTest('gh-tag-settings-form', {
integration: true
},
function () {
beforeEach(function () {
/* eslint-disable camelcase */
let tag = EmberObject.create({
id: 1,
name: 'Test',
slug: 'test',
description: 'Description.',
metaTitle: 'Meta Title',
metaDescription: 'Meta description',
errors: Errors.create(),
hasValidated: []
});
/* eslint-enable camelcase */
});
this.set('tag', tag);
this.set('actions.setProperty', function (property, value) {
// this should be overridden if a call is expected
// eslint-disable-next-line no-console
console.error(`setProperty called '${property}: ${value}'`);
});
beforeEach(function () {
/* eslint-disable camelcase */
let tag = EmberObject.create({
id: 1,
name: 'Test',
slug: 'test',
description: 'Description.',
metaTitle: 'Meta Title',
metaDescription: 'Meta description',
errors: Errors.create(),
hasValidated: []
});
/* eslint-enable camelcase */
this.register('service:config', configStub);
this.inject.service('config', {as: 'config'});
this.register('service:media-queries', mediaQueriesStub);
this.inject.service('media-queries', {as: 'mediaQueries'});
this.set('tag', tag);
this.set('actions.setProperty', function (property, value) {
// this should be overridden if a call is expected
// eslint-disable-next-line no-console
console.error(`setProperty called '${property}: ${value}'`);
});
it('renders', function () {
this.render(hbs`
{{gh-tag-settings-form tag=tag setProperty=(action 'setProperty')}}
`);
expect(this.$()).to.have.length(1);
this.register('service:config', configStub);
this.inject.service('config', {as: 'config'});
this.register('service:media-queries', mediaQueriesStub);
this.inject.service('media-queries', {as: 'mediaQueries'});
});
it('renders', function () {
this.render(hbs`
{{gh-tag-settings-form tag=tag setProperty=(action 'setProperty')}}
`);
expect(this.$()).to.have.length(1);
});
it('has the correct title', function () {
this.render(hbs`
{{gh-tag-settings-form tag=tag setProperty=(action 'setProperty')}}
`);
expect(this.$('.tag-settings-pane h4').text(), 'existing tag title').to.equal('Tag Settings');
this.set('tag.isNew', true);
expect(this.$('.tag-settings-pane h4').text(), 'new tag title').to.equal('New Tag');
});
it('renders main settings', function () {
this.render(hbs`
{{gh-tag-settings-form tag=tag setProperty=(action 'setProperty')}}
`);
expect(this.$('.gh-image-uploader').length, 'displays image uploader').to.equal(1);
expect(this.$('input[name="name"]').val(), 'name field value').to.equal('Test');
expect(this.$('input[name="slug"]').val(), 'slug field value').to.equal('test');
expect(this.$('textarea[name="description"]').val(), 'description field value').to.equal('Description.');
expect(this.$('input[name="metaTitle"]').val(), 'metaTitle field value').to.equal('Meta Title');
expect(this.$('textarea[name="metaDescription"]').val(), 'metaDescription field value').to.equal('Meta description');
});
it('can switch between main/meta settings', function () {
this.render(hbs`
{{gh-tag-settings-form tag=tag setProperty=(action 'setProperty')}}
`);
expect(this.$('.tag-settings-pane').hasClass('settings-menu-pane-in'), 'main settings are displayed by default').to.be.true;
expect(this.$('.tag-meta-settings-pane').hasClass('settings-menu-pane-out-right'), 'meta settings are hidden by default').to.be.true;
run(() => {
this.$('.meta-data-button').click();
});
it('has the correct title', function () {
this.render(hbs`
{{gh-tag-settings-form tag=tag setProperty=(action 'setProperty')}}
`);
expect(this.$('.tag-settings-pane h4').text(), 'existing tag title').to.equal('Tag Settings');
expect(this.$('.tag-settings-pane').hasClass('settings-menu-pane-out-left'), 'main settings are hidden after clicking Meta Data button').to.be.true;
expect(this.$('.tag-meta-settings-pane').hasClass('settings-menu-pane-in'), 'meta settings are displayed after clicking Meta Data button').to.be.true;
this.set('tag.isNew', true);
expect(this.$('.tag-settings-pane h4').text(), 'new tag title').to.equal('New Tag');
run(() => {
this.$('.back').click();
});
it('renders main settings', function () {
this.render(hbs`
{{gh-tag-settings-form tag=tag setProperty=(action 'setProperty')}}
`);
expect(this.$('.tag-settings-pane').hasClass('settings-menu-pane-in'), 'main settings are displayed after clicking "back"').to.be.true;
expect(this.$('.tag-meta-settings-pane').hasClass('settings-menu-pane-out-right'), 'meta settings are hidden after clicking "back"').to.be.true;
});
expect(this.$('.gh-image-uploader').length, 'displays image uploader').to.equal(1);
expect(this.$('input[name="name"]').val(), 'name field value').to.equal('Test');
expect(this.$('input[name="slug"]').val(), 'slug field value').to.equal('test');
expect(this.$('textarea[name="description"]').val(), 'description field value').to.equal('Description.');
expect(this.$('input[name="metaTitle"]').val(), 'metaTitle field value').to.equal('Meta Title');
expect(this.$('textarea[name="metaDescription"]').val(), 'metaDescription field value').to.equal('Meta description');
it('has one-way binding for properties', function () {
this.set('actions.setProperty', function () {
// noop
});
it('can switch between main/meta settings', function () {
this.render(hbs`
{{gh-tag-settings-form tag=tag setProperty=(action 'setProperty')}}
`);
this.render(hbs`
{{gh-tag-settings-form tag=tag setProperty=(action 'setProperty')}}
`);
expect(this.$('.tag-settings-pane').hasClass('settings-menu-pane-in'), 'main settings are displayed by default').to.be.true;
expect(this.$('.tag-meta-settings-pane').hasClass('settings-menu-pane-out-right'), 'meta settings are hidden by default').to.be.true;
run(() => {
this.$('.meta-data-button').click();
});
expect(this.$('.tag-settings-pane').hasClass('settings-menu-pane-out-left'), 'main settings are hidden after clicking Meta Data button').to.be.true;
expect(this.$('.tag-meta-settings-pane').hasClass('settings-menu-pane-in'), 'meta settings are displayed after clicking Meta Data button').to.be.true;
run(() => {
this.$('.back').click();
});
expect(this.$('.tag-settings-pane').hasClass('settings-menu-pane-in'), 'main settings are displayed after clicking "back"').to.be.true;
expect(this.$('.tag-meta-settings-pane').hasClass('settings-menu-pane-out-right'), 'meta settings are hidden after clicking "back"').to.be.true;
run(() => {
this.$('input[name="name"]').val('New name');
this.$('input[name="slug"]').val('new-slug');
this.$('textarea[name="description"]').val('New description');
this.$('input[name="metaTitle"]').val('New metaTitle');
this.$('textarea[name="metaDescription"]').val('New metaDescription');
});
it('has one-way binding for properties', function () {
this.set('actions.setProperty', function () {
// noop
});
expect(this.get('tag.name'), 'tag name').to.equal('Test');
expect(this.get('tag.slug'), 'tag slug').to.equal('test');
expect(this.get('tag.description'), 'tag description').to.equal('Description.');
expect(this.get('tag.metaTitle'), 'tag metaTitle').to.equal('Meta Title');
expect(this.get('tag.metaDescription'), 'tag metaDescription').to.equal('Meta description');
});
this.render(hbs`
{{gh-tag-settings-form tag=tag setProperty=(action 'setProperty')}}
`);
it('triggers setProperty action on blur of all fields', function () {
let expectedProperty = '';
let expectedValue = '';
run(() => {
this.$('input[name="name"]').val('New name');
this.$('input[name="slug"]').val('new-slug');
this.$('textarea[name="description"]').val('New description');
this.$('input[name="metaTitle"]').val('New metaTitle');
this.$('textarea[name="metaDescription"]').val('New metaDescription');
});
expect(this.get('tag.name'), 'tag name').to.equal('Test');
expect(this.get('tag.slug'), 'tag slug').to.equal('test');
expect(this.get('tag.description'), 'tag description').to.equal('Description.');
expect(this.get('tag.metaTitle'), 'tag metaTitle').to.equal('Meta Title');
expect(this.get('tag.metaDescription'), 'tag metaDescription').to.equal('Meta description');
this.set('actions.setProperty', function (property, value) {
expect(property, 'property').to.equal(expectedProperty);
expect(value, 'value').to.equal(expectedValue);
});
it('triggers setProperty action on blur of all fields', function () {
let expectedProperty = '';
let expectedValue = '';
this.render(hbs`
{{gh-tag-settings-form tag=tag setProperty=(action 'setProperty')}}
`);
this.set('actions.setProperty', function (property, value) {
expect(property, 'property').to.equal(expectedProperty);
expect(value, 'value').to.equal(expectedValue);
});
this.render(hbs`
{{gh-tag-settings-form tag=tag setProperty=(action 'setProperty')}}
`);
expectedProperty = 'name';
expectedValue = 'new-slug';
run(() => {
this.$('input[name="name"]').val('New name');
});
expectedProperty = 'url';
expectedValue = 'new-slug';
run(() => {
this.$('input[name="slug"]').val('new-slug');
});
expectedProperty = 'description';
expectedValue = 'New description';
run(() => {
this.$('textarea[name="description"]').val('New description');
});
expectedProperty = 'metaTitle';
expectedValue = 'New metaTitle';
run(() => {
this.$('input[name="metaTitle"]').val('New metaTitle');
});
expectedProperty = 'metaDescription';
expectedValue = 'New metaDescription';
run(() => {
this.$('textarea[name="metaDescription"]').val('New metaDescription');
});
expectedProperty = 'name';
expectedValue = 'new-slug';
run(() => {
this.$('input[name="name"]').val('New name');
});
it('displays error messages for validated fields', function () {
let errors = this.get('tag.errors');
let hasValidated = this.get('tag.hasValidated');
errors.add('name', 'must be present');
hasValidated.push('name');
errors.add('slug', 'must be present');
hasValidated.push('slug');
errors.add('description', 'is too long');
hasValidated.push('description');
errors.add('metaTitle', 'is too long');
hasValidated.push('metaTitle');
errors.add('metaDescription', 'is too long');
hasValidated.push('metaDescription');
this.render(hbs`
{{gh-tag-settings-form tag=tag setProperty=(action 'setProperty')}}
`);
let nameFormGroup = this.$('input[name="name"]').closest('.form-group');
expect(nameFormGroup.hasClass('error'), 'name form group has error state').to.be.true;
expect(nameFormGroup.find('.response').length, 'name form group has error message').to.equal(1);
let slugFormGroup = this.$('input[name="slug"]').closest('.form-group');
expect(slugFormGroup.hasClass('error'), 'slug form group has error state').to.be.true;
expect(slugFormGroup.find('.response').length, 'slug form group has error message').to.equal(1);
let descriptionFormGroup = this.$('textarea[name="description"]').closest('.form-group');
expect(descriptionFormGroup.hasClass('error'), 'description form group has error state').to.be.true;
let metaTitleFormGroup = this.$('input[name="metaTitle"]').closest('.form-group');
expect(metaTitleFormGroup.hasClass('error'), 'metaTitle form group has error state').to.be.true;
expect(metaTitleFormGroup.find('.response').length, 'metaTitle form group has error message').to.equal(1);
let metaDescriptionFormGroup = this.$('textarea[name="metaDescription"]').closest('.form-group');
expect(metaDescriptionFormGroup.hasClass('error'), 'metaDescription form group has error state').to.be.true;
expect(metaDescriptionFormGroup.find('.response').length, 'metaDescription form group has error message').to.equal(1);
expectedProperty = 'url';
expectedValue = 'new-slug';
run(() => {
this.$('input[name="slug"]').val('new-slug');
});
it('displays char count for text fields', function () {
this.render(hbs`
{{gh-tag-settings-form tag=tag setProperty=(action 'setProperty')}}
`);
let descriptionFormGroup = this.$('textarea[name="description"]').closest('.form-group');
expect(descriptionFormGroup.find('.word-count').text(), 'description char count').to.equal('12');
let metaDescriptionFormGroup = this.$('textarea[name="metaDescription"]').closest('.form-group');
expect(metaDescriptionFormGroup.find('.word-count').text(), 'description char count').to.equal('16');
expectedProperty = 'description';
expectedValue = 'New description';
run(() => {
this.$('textarea[name="description"]').val('New description');
});
it('renders SEO title preview', function () {
this.render(hbs`
{{gh-tag-settings-form tag=tag setProperty=(action 'setProperty')}}
`);
expect(this.$('.seo-preview-title').text(), 'displays meta title if present').to.equal('Meta Title');
run(() => {
this.set('tag.metaTitle', '');
});
expect(this.$('.seo-preview-title').text(), 'falls back to tag name without metaTitle').to.equal('Test');
run(() => {
this.set('tag.name', (new Array(151).join('x')));
});
let expectedLength = 70 + '…'.length;
expect(this.$('.seo-preview-title').text().length, 'cuts title to max 70 chars').to.equal(expectedLength);
expectedProperty = 'metaTitle';
expectedValue = 'New metaTitle';
run(() => {
this.$('input[name="metaTitle"]').val('New metaTitle');
});
it('renders SEO URL preview', function () {
this.render(hbs`
{{gh-tag-settings-form tag=tag setProperty=(action 'setProperty')}}
`);
expect(this.$('.seo-preview-link').text(), 'adds url and tag prefix').to.equal('http://localhost:2368/tag/test/');
expectedProperty = 'metaDescription';
expectedValue = 'New metaDescription';
run(() => {
this.$('textarea[name="metaDescription"]').val('New metaDescription');
});
});
run(() => {
this.set('tag.slug', (new Array(151).join('x')));
});
let expectedLength = 70 + '…'.length;
expect(this.$('.seo-preview-link').text().length, 'cuts slug to max 70 chars').to.equal(expectedLength);
it('displays error messages for validated fields', function () {
let errors = this.get('tag.errors');
let hasValidated = this.get('tag.hasValidated');
errors.add('name', 'must be present');
hasValidated.push('name');
errors.add('slug', 'must be present');
hasValidated.push('slug');
errors.add('description', 'is too long');
hasValidated.push('description');
errors.add('metaTitle', 'is too long');
hasValidated.push('metaTitle');
errors.add('metaDescription', 'is too long');
hasValidated.push('metaDescription');
this.render(hbs`
{{gh-tag-settings-form tag=tag setProperty=(action 'setProperty')}}
`);
let nameFormGroup = this.$('input[name="name"]').closest('.form-group');
expect(nameFormGroup.hasClass('error'), 'name form group has error state').to.be.true;
expect(nameFormGroup.find('.response').length, 'name form group has error message').to.equal(1);
let slugFormGroup = this.$('input[name="slug"]').closest('.form-group');
expect(slugFormGroup.hasClass('error'), 'slug form group has error state').to.be.true;
expect(slugFormGroup.find('.response').length, 'slug form group has error message').to.equal(1);
let descriptionFormGroup = this.$('textarea[name="description"]').closest('.form-group');
expect(descriptionFormGroup.hasClass('error'), 'description form group has error state').to.be.true;
let metaTitleFormGroup = this.$('input[name="metaTitle"]').closest('.form-group');
expect(metaTitleFormGroup.hasClass('error'), 'metaTitle form group has error state').to.be.true;
expect(metaTitleFormGroup.find('.response').length, 'metaTitle form group has error message').to.equal(1);
let metaDescriptionFormGroup = this.$('textarea[name="metaDescription"]').closest('.form-group');
expect(metaDescriptionFormGroup.hasClass('error'), 'metaDescription form group has error state').to.be.true;
expect(metaDescriptionFormGroup.find('.response').length, 'metaDescription form group has error message').to.equal(1);
});
it('displays char count for text fields', function () {
this.render(hbs`
{{gh-tag-settings-form tag=tag setProperty=(action 'setProperty')}}
`);
let descriptionFormGroup = this.$('textarea[name="description"]').closest('.form-group');
expect(descriptionFormGroup.find('.word-count').text(), 'description char count').to.equal('12');
let metaDescriptionFormGroup = this.$('textarea[name="metaDescription"]').closest('.form-group');
expect(metaDescriptionFormGroup.find('.word-count').text(), 'description char count').to.equal('16');
});
it('renders SEO title preview', function () {
this.render(hbs`
{{gh-tag-settings-form tag=tag setProperty=(action 'setProperty')}}
`);
expect(this.$('.seo-preview-title').text(), 'displays meta title if present').to.equal('Meta Title');
run(() => {
this.set('tag.metaTitle', '');
});
expect(this.$('.seo-preview-title').text(), 'falls back to tag name without metaTitle').to.equal('Test');
run(() => {
this.set('tag.name', (new Array(151).join('x')));
});
let expectedLength = 70 + '…'.length;
expect(this.$('.seo-preview-title').text().length, 'cuts title to max 70 chars').to.equal(expectedLength);
});
it('renders SEO URL preview', function () {
this.render(hbs`
{{gh-tag-settings-form tag=tag setProperty=(action 'setProperty')}}
`);
expect(this.$('.seo-preview-link').text(), 'adds url and tag prefix').to.equal('http://localhost:2368/tag/test/');
run(() => {
this.set('tag.slug', (new Array(151).join('x')));
});
let expectedLength = 70 + '…'.length;
expect(this.$('.seo-preview-link').text().length, 'cuts slug to max 70 chars').to.equal(expectedLength);
});
it('renders SEO description preview', function () {
this.render(hbs`
{{gh-tag-settings-form tag=tag setProperty=(action 'setProperty')}}
`);
expect(this.$('.seo-preview-description').text(), 'displays meta description if present').to.equal('Meta description');
run(() => {
this.set('tag.metaDescription', '');
});
expect(this.$('.seo-preview-description').text(), 'falls back to tag description without metaDescription').to.equal('Description.');
run(() => {
this.set('tag.description', (new Array(200).join('x')));
});
let expectedLength = 156 + '…'.length;
expect(this.$('.seo-preview-description').text().length, 'cuts description to max 156 chars').to.equal(expectedLength);
});
it('resets if a new tag is received', function () {
this.render(hbs`
{{gh-tag-settings-form tag=tag setProperty=(action 'setProperty')}}
`);
run(() => {
this.$('.meta-data-button').click();
});
expect(this.$('.tag-meta-settings-pane').hasClass('settings-menu-pane-in'), 'meta data pane is shown').to.be.true;
run(() => {
this.set('tag', EmberObject.create({id: '2'}));
});
expect(this.$('.tag-settings-pane').hasClass('settings-menu-pane-in'), 'resets to main settings').to.be.true;
});
it('triggers delete tag modal on delete click', function (done) {
// TODO: will time out if this isn't hit, there's probably a better
// way of testing this
this.set('actions.openModal', () => {
done();
});
it('renders SEO description preview', function () {
this.render(hbs`
{{gh-tag-settings-form tag=tag setProperty=(action 'setProperty')}}
`);
expect(this.$('.seo-preview-description').text(), 'displays meta description if present').to.equal('Meta description');
this.render(hbs`
{{gh-tag-settings-form tag=tag setProperty=(action 'setProperty') showDeleteTagModal=(action 'openModal')}}
`);
run(() => {
this.set('tag.metaDescription', '');
});
expect(this.$('.seo-preview-description').text(), 'falls back to tag description without metaDescription').to.equal('Description.');
run(() => {
this.set('tag.description', (new Array(200).join('x')));
});
let expectedLength = 156 + '…'.length;
expect(this.$('.seo-preview-description').text().length, 'cuts description to max 156 chars').to.equal(expectedLength);
run(() => {
this.$('.tag-delete-button').click();
});
});
it('resets if a new tag is received', function () {
this.render(hbs`
{{gh-tag-settings-form tag=tag setProperty=(action 'setProperty')}}
`);
run(() => {
this.$('.meta-data-button').click();
});
expect(this.$('.tag-meta-settings-pane').hasClass('settings-menu-pane-in'), 'meta data pane is shown').to.be.true;
it('shows settings.tags arrow link on mobile', function () {
this.set('mediaQueries.maxWidth600', true);
run(() => {
this.set('tag', EmberObject.create({id: '2'}));
});
expect(this.$('.tag-settings-pane').hasClass('settings-menu-pane-in'), 'resets to main settings').to.be.true;
});
this.render(hbs`
{{gh-tag-settings-form tag=tag setProperty=(action 'setProperty')}}
`);
it('triggers delete tag modal on delete click', function (done) {
// TODO: will time out if this isn't hit, there's probably a better
// way of testing this
this.set('actions.openModal', () => {
done();
});
this.render(hbs`
{{gh-tag-settings-form tag=tag setProperty=(action 'setProperty') showDeleteTagModal=(action 'openModal')}}
`);
run(() => {
this.$('.tag-delete-button').click();
});
});
it('shows settings.tags arrow link on mobile', function () {
this.set('mediaQueries.maxWidth600', true);
this.render(hbs`
{{gh-tag-settings-form tag=tag setProperty=(action 'setProperty')}}
`);
expect(this.$('.tag-settings-pane .settings-menu-header .settings-menu-header-action').length, 'settings.tags link is shown').to.equal(1);
});
}
);
expect(this.$('.tag-settings-pane .settings-menu-header .settings-menu-header-action').length, 'settings.tags link is shown').to.equal(1);
});
});

View File

@ -1,32 +1,27 @@
/* jshint expr:true */
import {expect} from 'chai';
import {
describeComponent,
it
} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupComponentTest} from 'ember-mocha';
import hbs from 'htmlbars-inline-precompile';
describeComponent(
'gh-tags-management-container',
'Integration: Component: gh-tags-management-container',
{
describe('Integration: Component: gh-tags-management-container', function () {
setupComponentTest('gh-tags-management-container', {
integration: true
},
function () {
it('renders', function () {
this.set('tags', []);
this.set('selectedTag', null);
this.on('enteredMobile', function () {
// noop
});
this.on('leftMobile', function () {
// noop
});
});
this.render(hbs`
{{#gh-tags-management-container tags=tags selectedTag=selectedTag enteredMobile="enteredMobile" leftMobile="leftMobile"}}{{/gh-tags-management-container}}
`);
expect(this.$()).to.have.length(1);
it('renders', function () {
this.set('tags', []);
this.set('selectedTag', null);
this.on('enteredMobile', function () {
// noop
});
}
);
this.on('leftMobile', function () {
// noop
});
this.render(hbs`
{{#gh-tags-management-container tags=tags selectedTag=selectedTag enteredMobile="enteredMobile" leftMobile="leftMobile"}}{{/gh-tags-management-container}}
`);
expect(this.$()).to.have.length(1);
});
});

View File

@ -1,24 +1,19 @@
/* jshint expr:true */
import {expect} from 'chai';
import {
describeComponent,
it
} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupComponentTest} from 'ember-mocha';
import hbs from 'htmlbars-inline-precompile';
describeComponent(
'gh-task-button',
'Integration: Component: gh-task-button',
{
describe('Integration: Component: gh-task-button', function() {
setupComponentTest('gh-task-button', {
integration: true
},
function() {
it('renders', function () {
this.render(hbs`{{#gh-task-button}}Test{{/gh-task-button}}`);
expect(this.$()).to.have.length(1);
expect(this.$().text().trim()).to.equal('Test');
});
});
// TODO: figure out how to test concurrency behavior
}
);
it('renders', function () {
this.render(hbs`{{#gh-task-button}}Test{{/gh-task-button}}`);
expect(this.$()).to.have.length(1);
expect(this.$().text().trim()).to.equal('Test');
});
// TODO: figure out how to test concurrency behavior
});

View File

@ -1,201 +1,196 @@
/* jshint expr:true */
import {expect} from 'chai';
import {
describeComponent,
it
} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupComponentTest} from 'ember-mocha';
import hbs from 'htmlbars-inline-precompile';
import $ from 'jquery';
import sinon from 'sinon';
import run from 'ember-runloop';
describeComponent(
'gh-theme-table',
'Integration: Component: gh-theme-table',
{
describe('Integration: Component: gh-theme-table', function() {
setupComponentTest('gh-theme-table', {
integration: true
},
function() {
it('renders', function() {
this.set('availableThemes', [
{name: 'Daring', package: {name: 'Daring', version: '0.1.4'}, active: true},
{name: 'casper', package: {name: 'Casper', version: '1.3.1'}},
{name: 'oscar-ghost-1.1.0', package: {name: 'Lanyon', version: '1.1.0'}},
{name: 'foo'}
]);
this.set('actionHandler', sinon.spy());
});
this.render(hbs`{{gh-theme-table
availableThemes=availableThemes
activateTheme=(action actionHandler)
downloadTheme=(action actionHandler)
deleteTheme=(action actionHandler)
}}`);
it('renders', function() {
this.set('availableThemes', [
{name: 'Daring', package: {name: 'Daring', version: '0.1.4'}, active: true},
{name: 'casper', package: {name: 'Casper', version: '1.3.1'}},
{name: 'oscar-ghost-1.1.0', package: {name: 'Lanyon', version: '1.1.0'}},
{name: 'foo'}
]);
this.set('actionHandler', sinon.spy());
expect(this.$('.theme-list').length, '.theme-list is present').to.equal(1);
expect(this.$('.theme-list-item').length, 'number of rows').to.equal(4);
this.render(hbs`{{gh-theme-table
availableThemes=availableThemes
activateTheme=(action actionHandler)
downloadTheme=(action actionHandler)
deleteTheme=(action actionHandler)
}}`);
let packageNames = this.$('.theme-list-item-body .name').map((i, name) => {
return $(name).text().trim();
}).toArray();
expect(this.$('.theme-list').length, '.theme-list is present').to.equal(1);
expect(this.$('.theme-list-item').length, 'number of rows').to.equal(4);
expect(
packageNames,
'themes are ordered by label, casper has "default", package versions are shown'
).to.deep.equal([
'Casper - 1.3.1 (default)',
'Daring - 0.1.4',
'foo',
'Lanyon - 1.1.0'
]);
let packageNames = this.$('.theme-list-item-body .name').map((i, name) => {
return $(name).text().trim();
}).toArray();
expect(
this.$('.theme-list-item:contains("Daring")').hasClass('theme-list-item--active'),
'active theme is highlighted'
).to.be.true;
expect(
packageNames,
'themes are ordered by label, casper has "default", package versions are shown'
).to.deep.equal([
'Casper - 1.3.1 (default)',
'Daring - 0.1.4',
'foo',
'Lanyon - 1.1.0'
]);
expect(
this.$('.theme-list-item:not(:contains("Daring"))').find('a:contains("Activate")').length === 3,
'non-active themes have an activate link'
).to.be.true;
expect(
this.$('.theme-list-item:contains("Daring")').hasClass('theme-list-item--active'),
'active theme is highlighted'
).to.be.true;
expect(
this.$('.theme-list-item:contains("Daring")').find('a:contains("Activate")').length === 0,
'active theme doesn\'t have an activate link'
).to.be.true;
expect(
this.$('.theme-list-item:not(:contains("Daring"))').find('a:contains("Activate")').length === 3,
'non-active themes have an activate link'
).to.be.true;
expect(
this.$('a:contains("Download")').length,
'all themes have a download link'
).to.equal(4);
expect(
this.$('.theme-list-item:contains("Daring")').find('a:contains("Activate")').length === 0,
'active theme doesn\'t have an activate link'
).to.be.true;
expect(
this.$('.theme-list-item:contains("foo")').find('a:contains("Delete")').length === 1,
'non-active, non-casper theme has delete link'
).to.be.true;
expect(
this.$('a:contains("Download")').length,
'all themes have a download link'
).to.equal(4);
expect(
this.$('.theme-list-item:contains("Casper")').find('a:contains("Delete")').length === 0,
'casper doesn\'t have delete link'
).to.be.true;
expect(
this.$('.theme-list-item:contains("foo")').find('a:contains("Delete")').length === 1,
'non-active, non-casper theme has delete link'
).to.be.true;
expect(
this.$('.theme-list-item--active').find('a:contains("Delete")').length === 0,
'active theme doesn\'t have delete link'
).to.be.true;
expect(
this.$('.theme-list-item:contains("Casper")').find('a:contains("Delete")').length === 0,
'casper doesn\'t have delete link'
).to.be.true;
expect(
this.$('.theme-list-item--active').find('a:contains("Delete")').length === 0,
'active theme doesn\'t have delete link'
).to.be.true;
});
it('delete link triggers passed in action', function () {
let deleteAction = sinon.spy();
let actionHandler = sinon.spy();
this.set('availableThemes', [
{name: 'Foo', active: true},
{name: 'Bar'}
]);
this.set('deleteAction', deleteAction);
this.set('actionHandler', actionHandler);
this.render(hbs`{{gh-theme-table
availableThemes=availableThemes
activateTheme=(action actionHandler)
downloadTheme=(action actionHandler)
deleteTheme=(action deleteAction)
}}`);
run(() => {
this.$('.theme-list-item:contains("Bar") a:contains("Delete")').click();
});
it('delete link triggers passed in action', function () {
let deleteAction = sinon.spy();
let actionHandler = sinon.spy();
expect(deleteAction.calledOnce).to.be.true;
expect(deleteAction.firstCall.args[0].name).to.equal('Bar');
});
this.set('availableThemes', [
{name: 'Foo', active: true},
{name: 'Bar'}
]);
this.set('deleteAction', deleteAction);
this.set('actionHandler', actionHandler);
it('download link triggers passed in action', function () {
let downloadAction = sinon.spy();
let actionHandler = sinon.spy();
this.render(hbs`{{gh-theme-table
availableThemes=availableThemes
activateTheme=(action actionHandler)
downloadTheme=(action actionHandler)
deleteTheme=(action deleteAction)
}}`);
this.set('availableThemes', [
{name: 'Foo', active: true},
{name: 'Bar'}
]);
this.set('downloadAction', downloadAction);
this.set('actionHandler', actionHandler);
run(() => {
this.$('.theme-list-item:contains("Bar") a:contains("Delete")').click();
});
this.render(hbs`{{gh-theme-table
availableThemes=availableThemes
activateTheme=(action actionHandler)
downloadTheme=(action downloadAction)
deleteTheme=(action actionHandler)
}}`);
expect(deleteAction.calledOnce).to.be.true;
expect(deleteAction.firstCall.args[0].name).to.equal('Bar');
run(() => {
this.$('.theme-list-item:contains("Foo") a:contains("Download")').click();
});
it('download link triggers passed in action', function () {
let downloadAction = sinon.spy();
let actionHandler = sinon.spy();
expect(downloadAction.calledOnce).to.be.true;
expect(downloadAction.firstCall.args[0].name).to.equal('Foo');
});
this.set('availableThemes', [
{name: 'Foo', active: true},
{name: 'Bar'}
]);
this.set('downloadAction', downloadAction);
this.set('actionHandler', actionHandler);
it('activate link triggers passed in action', function () {
let activateAction = sinon.spy();
let actionHandler = sinon.spy();
this.render(hbs`{{gh-theme-table
availableThemes=availableThemes
activateTheme=(action actionHandler)
downloadTheme=(action downloadAction)
deleteTheme=(action actionHandler)
}}`);
this.set('availableThemes', [
{name: 'Foo', active: true},
{name: 'Bar'}
]);
this.set('activateAction', activateAction);
this.set('actionHandler', actionHandler);
run(() => {
this.$('.theme-list-item:contains("Foo") a:contains("Download")').click();
});
this.render(hbs`{{gh-theme-table
availableThemes=availableThemes
activateTheme=(action activateAction)
downloadTheme=(action actionHandler)
deleteTheme=(action actionHandler)
}}`);
expect(downloadAction.calledOnce).to.be.true;
expect(downloadAction.firstCall.args[0].name).to.equal('Foo');
run(() => {
this.$('.theme-list-item:contains("Bar") a:contains("Activate")').click();
});
it('activate link triggers passed in action', function () {
let activateAction = sinon.spy();
let actionHandler = sinon.spy();
expect(activateAction.calledOnce).to.be.true;
expect(activateAction.firstCall.args[0].name).to.equal('Bar');
});
this.set('availableThemes', [
{name: 'Foo', active: true},
{name: 'Bar'}
]);
this.set('activateAction', activateAction);
this.set('actionHandler', actionHandler);
it('displays folder names if there are duplicate package names', function () {
this.set('availableThemes', [
{name: 'daring', package: {name: 'Daring', version: '0.1.4'}, active: true},
{name: 'daring-0.1.5', package: {name: 'Daring', version: '0.1.4'}},
{name: 'casper', package: {name: 'Casper', version: '1.3.1'}},
{name: 'another', package: {name: 'Casper', version: '1.3.1'}},
{name: 'mine', package: {name: 'Casper', version: '1.3.1'}},
{name: 'foo'}
]);
this.set('actionHandler', sinon.spy());
this.render(hbs`{{gh-theme-table
availableThemes=availableThemes
activateTheme=(action activateAction)
downloadTheme=(action actionHandler)
deleteTheme=(action actionHandler)
}}`);
this.render(hbs`{{gh-theme-table
availableThemes=availableThemes
activateTheme=(action actionHandler)
downloadTheme=(action actionHandler)
deleteTheme=(action actionHandler)
}}`);
run(() => {
this.$('.theme-list-item:contains("Bar") a:contains("Activate")').click();
});
let packageNames = this.$('.theme-list-item-body .name').map((i, name) => {
return $(name).text().trim();
}).toArray();
expect(activateAction.calledOnce).to.be.true;
expect(activateAction.firstCall.args[0].name).to.equal('Bar');
});
it('displays folder names if there are duplicate package names', function () {
this.set('availableThemes', [
{name: 'daring', package: {name: 'Daring', version: '0.1.4'}, active: true},
{name: 'daring-0.1.5', package: {name: 'Daring', version: '0.1.4'}},
{name: 'casper', package: {name: 'Casper', version: '1.3.1'}},
{name: 'another', package: {name: 'Casper', version: '1.3.1'}},
{name: 'mine', package: {name: 'Casper', version: '1.3.1'}},
{name: 'foo'}
]);
this.set('actionHandler', sinon.spy());
this.render(hbs`{{gh-theme-table
availableThemes=availableThemes
activateTheme=(action actionHandler)
downloadTheme=(action actionHandler)
deleteTheme=(action actionHandler)
}}`);
let packageNames = this.$('.theme-list-item-body .name').map((i, name) => {
return $(name).text().trim();
}).toArray();
expect(
packageNames,
'themes are ordered by label, folder names shown for duplicates'
).to.deep.equal([
'Casper - 1.3.1 (another)',
'Casper - 1.3.1 (default)',
'Casper - 1.3.1 (mine)',
'Daring - 0.1.4 (daring)',
'Daring - 0.1.4 (daring-0.1.5)',
'foo'
]);
});
}
);
expect(
packageNames,
'themes are ordered by label, folder names shown for duplicates'
).to.deep.equal([
'Casper - 1.3.1 (another)',
'Casper - 1.3.1 (default)',
'Casper - 1.3.1 (mine)',
'Daring - 0.1.4 (daring)',
'Daring - 0.1.4 (daring-0.1.5)',
'foo'
]);
});
});

View File

@ -1,78 +1,73 @@
/* jshint expr:true */
import {expect} from 'chai';
import {
describeComponent,
it
} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupComponentTest} from 'ember-mocha';
import hbs from 'htmlbars-inline-precompile';
import run from 'ember-runloop';
import wait from 'ember-test-helpers/wait';
import sinon from 'sinon';
describeComponent(
'gh-timezone-select',
'Integration: Component: gh-timezone-select',
{
describe('Integration: Component: gh-timezone-select', function() {
setupComponentTest('gh-timezone-select', {
integration: true
},
function() {
beforeEach(function () {
this.set('availableTimezones', [
{name: 'Pacific/Pago_Pago', label: '(GMT -11:00) Midway Island, Samoa'},
{name: 'Etc/UTC', label: '(GMT) UTC'},
{name: 'Pacific/Kwajalein', label: '(GMT +12:00) International Date Line West'}
]);
this.set('activeTimezone', 'Etc/UTC');
});
beforeEach(function () {
this.set('availableTimezones', [
{name: 'Pacific/Pago_Pago', label: '(GMT -11:00) Midway Island, Samoa'},
{name: 'Etc/UTC', label: '(GMT) UTC'},
{name: 'Pacific/Kwajalein', label: '(GMT +12:00) International Date Line West'}
]);
this.set('activeTimezone', 'Etc/UTC');
});
it('renders', function () {
this.render(hbs`{{gh-timezone-select
availableTimezones=availableTimezones
activeTimezone=activeTimezone}}`);
expect(this.$(), 'top-level elements').to.have.length(1);
expect(this.$('option'), 'number of options').to.have.length(3);
expect(this.$('select').val(), 'selected option value').to.equal('Etc/UTC');
});
it('handles an unknown timezone', function () {
this.set('activeTimezone', 'Europe/London');
this.render(hbs`{{gh-timezone-select
availableTimezones=availableTimezones
activeTimezone=activeTimezone}}`);
// we have an additional blank option at the top
expect(this.$('option'), 'number of options').to.have.length(4);
// blank option is selected
expect(this.$('select').val(), 'selected option value').to.equal('');
// we indicate the manual override
expect(this.$('p').text()).to.match(/Your timezone has been automatically set to Europe\/London/);
});
it('triggers update action on change', function (done) {
let update = sinon.spy();
this.set('update', update);
this.render(hbs`{{gh-timezone-select
availableTimezones=availableTimezones
activeTimezone=activeTimezone
update=(action update)}}`);
run(() => {
this.$('select').val('Pacific/Pago_Pago').change();
});
it('renders', function () {
this.render(hbs`{{gh-timezone-select
availableTimezones=availableTimezones
activeTimezone=activeTimezone}}`);
expect(this.$(), 'top-level elements').to.have.length(1);
expect(this.$('option'), 'number of options').to.have.length(3);
expect(this.$('select').val(), 'selected option value').to.equal('Etc/UTC');
wait().then(() => {
expect(update.calledOnce, 'update was called once').to.be.true;
expect(update.firstCall.args[0].name, 'update was passed new timezone')
.to.equal('Pacific/Pago_Pago');
done();
});
});
it('handles an unknown timezone', function () {
this.set('activeTimezone', 'Europe/London');
this.render(hbs`{{gh-timezone-select
availableTimezones=availableTimezones
activeTimezone=activeTimezone}}`);
// we have an additional blank option at the top
expect(this.$('option'), 'number of options').to.have.length(4);
// blank option is selected
expect(this.$('select').val(), 'selected option value').to.equal('');
// we indicate the manual override
expect(this.$('p').text()).to.match(/Your timezone has been automatically set to Europe\/London/);
});
it('triggers update action on change', function (done) {
let update = sinon.spy();
this.set('update', update);
this.render(hbs`{{gh-timezone-select
availableTimezones=availableTimezones
activeTimezone=activeTimezone
update=(action update)}}`);
run(() => {
this.$('select').val('Pacific/Pago_Pago').change();
});
wait().then(() => {
expect(update.calledOnce, 'update was called once').to.be.true;
expect(update.firstCall.args[0].name, 'update was passed new timezone')
.to.equal('Pacific/Pago_Pago');
done();
});
});
// TODO: mock clock service, fake the time, test we have the correct
// local time and it changes alongside selection changes
it('renders local time');
}
);
// TODO: mock clock service, fake the time, test we have the correct
// local time and it changes alongside selection changes
it('renders local time');
});

View File

@ -1,51 +1,46 @@
import {expect} from 'chai';
import {
describeComponent,
it
} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupComponentTest} from 'ember-mocha';
import run from 'ember-runloop';
import hbs from 'htmlbars-inline-precompile';
describeComponent(
'gh-trim-focus-input',
'Integration: Component: gh-trim-focus-input',
{
describe('Integration: Component: gh-trim-focus-input', function () {
setupComponentTest('gh-trim-focus-input', {
integration: true
},
function () {
it('trims value on focusOut', function () {
this.set('text', 'some random stuff ');
this.render(hbs`{{gh-trim-focus-input text update=(action (mut text))}}`);
});
run(() => {
this.$('.gh-input').trigger('focusout');
});
it('trims value on focusOut', function () {
this.set('text', 'some random stuff ');
this.render(hbs`{{gh-trim-focus-input text update=(action (mut text))}}`);
expect(this.get('text')).to.equal('some random stuff');
run(() => {
this.$('.gh-input').trigger('focusout');
});
it('does not have the autofocus attribute if not set to focus', function () {
this.set('text', 'some text');
this.render(hbs`{{gh-trim-focus-input text shouldFocus=false}}`);
expect(this.$('.gh-input').attr('autofocus')).to.not.be.ok;
});
expect(this.get('text')).to.equal('some random stuff');
});
it('has the autofocus attribute if set to focus', function () {
this.set('text', 'some text');
this.render(hbs`{{gh-trim-focus-input text shouldFocus=true}}`);
expect(this.$('.gh-input').attr('autofocus')).to.be.ok;
});
it('does not have the autofocus attribute if not set to focus', function () {
this.set('text', 'some text');
this.render(hbs`{{gh-trim-focus-input text shouldFocus=false}}`);
expect(this.$('.gh-input').attr('autofocus')).to.not.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('has the autofocus attribute if set to focus', function () {
this.set('text', 'some text');
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');
});
}
);
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');
});
});

View File

@ -1,74 +1,69 @@
/* jshint expr:true */
import {expect} from 'chai';
import {
describeComponent,
it
} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupComponentTest} from 'ember-mocha';
import hbs from 'htmlbars-inline-precompile';
import EmberObject from 'ember-object';
import DS from 'ember-data';
const {Errors} = DS;
describeComponent(
'gh-validation-status-container',
'Integration: Component: gh-validation-status-container',
{
describe('Integration: Component: gh-validation-status-container', function () {
setupComponentTest('gh-validation-status-container', {
integration: true
},
function () {
beforeEach(function () {
let testObject = EmberObject.create();
testObject.set('name', 'Test');
testObject.set('hasValidated', []);
testObject.set('errors', Errors.create());
});
this.set('testObject', testObject);
});
beforeEach(function () {
let testObject = EmberObject.create();
testObject.set('name', 'Test');
testObject.set('hasValidated', []);
testObject.set('errors', Errors.create());
it('has no success/error class by default', function () {
this.render(hbs`
{{#gh-validation-status-container class="gh-test" property="name" errors=testObject.errors hasValidated=testObject.hasValidated}}
{{/gh-validation-status-container}}
`);
expect(this.$('.gh-test')).to.have.length(1);
expect(this.$('.gh-test').hasClass('success')).to.be.false;
expect(this.$('.gh-test').hasClass('error')).to.be.false;
});
this.set('testObject', testObject);
});
it('has success class when valid', function () {
this.get('testObject.hasValidated').push('name');
it('has no success/error class by default', function () {
this.render(hbs`
{{#gh-validation-status-container class="gh-test" property="name" errors=testObject.errors hasValidated=testObject.hasValidated}}
{{/gh-validation-status-container}}
`);
expect(this.$('.gh-test')).to.have.length(1);
expect(this.$('.gh-test').hasClass('success')).to.be.false;
expect(this.$('.gh-test').hasClass('error')).to.be.false;
});
this.render(hbs`
{{#gh-validation-status-container class="gh-test" property="name" errors=testObject.errors hasValidated=testObject.hasValidated}}
{{/gh-validation-status-container}}
`);
expect(this.$('.gh-test')).to.have.length(1);
expect(this.$('.gh-test').hasClass('success')).to.be.true;
expect(this.$('.gh-test').hasClass('error')).to.be.false;
});
it('has success class when valid', function () {
this.get('testObject.hasValidated').push('name');
it('has error class when invalid', function () {
this.get('testObject.hasValidated').push('name');
this.get('testObject.errors').add('name', 'has error');
this.render(hbs`
{{#gh-validation-status-container class="gh-test" property="name" errors=testObject.errors hasValidated=testObject.hasValidated}}
{{/gh-validation-status-container}}
`);
expect(this.$('.gh-test')).to.have.length(1);
expect(this.$('.gh-test').hasClass('success')).to.be.true;
expect(this.$('.gh-test').hasClass('error')).to.be.false;
});
this.render(hbs`
{{#gh-validation-status-container class="gh-test" property="name" errors=testObject.errors hasValidated=testObject.hasValidated}}
{{/gh-validation-status-container}}
`);
expect(this.$('.gh-test')).to.have.length(1);
expect(this.$('.gh-test').hasClass('success')).to.be.false;
expect(this.$('.gh-test').hasClass('error')).to.be.true;
});
it('has error class when invalid', function () {
this.get('testObject.hasValidated').push('name');
this.get('testObject.errors').add('name', 'has error');
it('still renders if hasValidated is undefined', function () {
this.set('testObject.hasValidated', undefined);
this.render(hbs`
{{#gh-validation-status-container class="gh-test" property="name" errors=testObject.errors hasValidated=testObject.hasValidated}}
{{/gh-validation-status-container}}
`);
expect(this.$('.gh-test')).to.have.length(1);
expect(this.$('.gh-test').hasClass('success')).to.be.false;
expect(this.$('.gh-test').hasClass('error')).to.be.true;
});
this.render(hbs`
{{#gh-validation-status-container class="gh-test" property="name" errors=testObject.errors hasValidated=testObject.hasValidated}}
{{/gh-validation-status-container}}
`);
expect(this.$('.gh-test')).to.have.length(1);
});
}
);
it('still renders if hasValidated is undefined', function () {
this.set('testObject.hasValidated', undefined);
this.render(hbs`
{{#gh-validation-status-container class="gh-test" property="name" errors=testObject.errors hasValidated=testObject.hasValidated}}
{{/gh-validation-status-container}}
`);
expect(this.$('.gh-test')).to.have.length(1);
});
});

View File

@ -1,30 +1,25 @@
/* jshint expr:true */
import {expect} from 'chai';
import {
describeComponent,
it
} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupComponentTest} from 'ember-mocha';
import hbs from 'htmlbars-inline-precompile';
describeComponent(
'modals/delete-subscriber',
'Integration: Component: modals/delete-subscriber',
{
describe('Integration: Component: modals/delete-subscriber', function() {
setupComponentTest('modals/delete-subscriber', {
integration: true
},
function() {
it('renders', function() {
// Set any properties with this.set('myProperty', 'value');
// Handle any actions with this.on('myAction', function(val) { ... });
// Template block usage:
// this.render(hbs`
// {{#modals/delete-subscriber}}
// template content
// {{/modals/delete-subscriber}}
// `);
});
this.render(hbs`{{modals/delete-subscriber}}`);
expect(this.$()).to.have.length(1);
});
}
);
it('renders', function() {
// Set any properties with this.set('myProperty', 'value');
// Handle any actions with this.on('myAction', function(val) { ... });
// Template block usage:
// this.render(hbs`
// {{#modals/delete-subscriber}}
// template content
// {{/modals/delete-subscriber}}
// `);
this.render(hbs`{{modals/delete-subscriber}}`);
expect(this.$()).to.have.length(1);
});
});

View File

@ -1,30 +1,25 @@
/* jshint expr:true */
import {expect} from 'chai';
import {
describeComponent,
it
} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupComponentTest} from 'ember-mocha';
import hbs from 'htmlbars-inline-precompile';
describeComponent(
'modals/import-subscribers',
'Integration: Component: modals/import-subscribers',
{
describe('Integration: Component: modals/import-subscribers', function() {
setupComponentTest('modals/import-subscribers', {
integration: true
},
function() {
it('renders', function() {
// Set any properties with this.set('myProperty', 'value');
// Handle any actions with this.on('myAction', function(val) { ... });
// Template block usage:
// this.render(hbs`
// {{#modals/import-subscribers}}
// template content
// {{/modals/import-subscribers}}
// `);
});
this.render(hbs`{{modals/import-subscribers}}`);
expect(this.$()).to.have.length(1);
});
}
);
it('renders', function() {
// Set any properties with this.set('myProperty', 'value');
// Handle any actions with this.on('myAction', function(val) { ... });
// Template block usage:
// this.render(hbs`
// {{#modals/import-subscribers}}
// template content
// {{/modals/import-subscribers}}
// `);
this.render(hbs`{{modals/import-subscribers}}`);
expect(this.$()).to.have.length(1);
});
});

View File

@ -1,30 +1,25 @@
/* jshint expr:true */
import {expect} from 'chai';
import {
describeComponent,
it
} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupComponentTest} from 'ember-mocha';
import hbs from 'htmlbars-inline-precompile';
describeComponent(
'modals/new-subscriber',
'Integration: Component: modals/new-subscriber',
{
describe('Integration: Component: modals/new-subscriber', function() {
setupComponentTest('modals/new-subscriber', {
integration: true
},
function() {
it('renders', function() {
// Set any properties with this.set('myProperty', 'value');
// Handle any actions with this.on('myAction', function(val) { ... });
// Template block usage:
// this.render(hbs`
// {{#modals/new-subscriber}}
// template content
// {{/modals/new-subscriber}}
// `);
});
this.render(hbs`{{modals/new-subscriber}}`);
expect(this.$()).to.have.length(1);
});
}
);
it('renders', function() {
// Set any properties with this.set('myProperty', 'value');
// Handle any actions with this.on('myAction', function(val) { ... });
// Template block usage:
// this.render(hbs`
// {{#modals/new-subscriber}}
// template content
// {{/modals/new-subscriber}}
// `);
this.render(hbs`{{modals/new-subscriber}}`);
expect(this.$()).to.have.length(1);
});
});

View File

@ -1,30 +1,25 @@
/* jshint expr:true */
import {expect} from 'chai';
import {
describeComponent,
it
} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupComponentTest} from 'ember-mocha';
import hbs from 'htmlbars-inline-precompile';
describeComponent(
'modals/upload-theme',
'Integration: Component: modals/upload-theme',
{
describe('Integration: Component: modals/upload-theme', function() {
setupComponentTest('modals/upload-theme', {
integration: true
},
function() {
it('renders', function() {
// Set any properties with this.set('myProperty', 'value');
// Handle any actions with this.on('myAction', function(val) { ... });
// Template block usage:
// this.render(hbs`
// {{#modals/upload-theme}}
// template content
// {{/modals/upload-theme}}
// `);
});
this.render(hbs`{{modals/upload-theme}}`);
expect(this.$()).to.have.length(1);
});
}
);
it('renders', function() {
// Set any properties with this.set('myProperty', 'value');
// Handle any actions with this.on('myAction', function(val) { ... });
// Template block usage:
// this.render(hbs`
// {{#modals/upload-theme}}
// template content
// {{/modals/upload-theme}}
// `);
this.render(hbs`{{modals/upload-theme}}`);
expect(this.$()).to.have.length(1);
});
});

View File

@ -1,38 +1,33 @@
/* jshint expr:true */
import {expect} from 'chai';
import {
describeComponent,
it
} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupComponentTest} from 'ember-mocha';
import hbs from 'htmlbars-inline-precompile';
import run from 'ember-runloop';
import RSVP from 'rsvp';
import sinon from 'sinon';
describeComponent(
'transfer-owner',
'Integration: Component: modals/transfer-owner',
{
describe('Integration: Component: modals/transfer-owner', function() {
setupComponentTest('transfer-owner', {
integration: true
},
function() {
it('triggers confirm action', function() {
let confirm = sinon.stub();
let closeModal = sinon.spy();
});
confirm.returns(RSVP.resolve({}));
it('triggers confirm action', function() {
let confirm = sinon.stub();
let closeModal = sinon.spy();
this.on('confirm', confirm);
this.on('closeModal', closeModal);
confirm.returns(RSVP.resolve({}));
this.render(hbs`{{modals/transfer-owner confirm=(action 'confirm') closeModal=(action 'closeModal')}}`);
this.on('confirm', confirm);
this.on('closeModal', closeModal);
run(() => {
this.$('.btn.btn-red').click();
});
this.render(hbs`{{modals/transfer-owner confirm=(action 'confirm') closeModal=(action 'closeModal')}}`);
expect(confirm.calledOnce, 'confirm called').to.be.true;
expect(closeModal.calledOnce, 'closeModal called').to.be.true;
run(() => {
this.$('.btn.btn-red').click();
});
}
);
expect(confirm.calledOnce, 'confirm called').to.be.true;
expect(closeModal.calledOnce, 'closeModal called').to.be.true;
});
});

View File

@ -1,8 +1,6 @@
import {expect} from 'chai';
import {
describeModule,
it
} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupTest} from 'ember-mocha';
import Pretender from 'pretender';
import {
isAjaxError,
@ -27,248 +25,245 @@ function stubAjaxEndpoint(server, response = {}, code = 200) {
});
}
describeModule(
'service:ajax',
'Integration: Service: ajax',
{
describe('Integration: Service: ajax', function () {
setupTest('service:ajax', {
integration: true
},
function () {
let server;
});
let server;
beforeEach(function () {
server = new Pretender();
});
afterEach(function () {
server.shutdown();
});
it('adds Ghost version header to requests', function (done) {
let {version} = config.APP;
let ajax = this.subject();
stubAjaxEndpoint(server, {});
ajax.request('/test/').then(() => {
let [request] = server.handledRequests;
expect(request.requestHeaders['X-Ghost-Version']).to.equal(version);
done();
});
});
it('correctly parses single message response text', function (done) {
let error = {message: 'Test Error'};
stubAjaxEndpoint(server, error, 500);
let ajax = this.subject();
ajax.request('/test/').then(() => {
expect(false).to.be.true();
}).catch((error) => {
expect(error.errors.length).to.equal(1);
expect(error.errors[0].message).to.equal('Test Error');
done();
});
});
it('correctly parses single error response text', function (done) {
let error = {error: 'Test Error'};
stubAjaxEndpoint(server, error, 500);
let ajax = this.subject();
ajax.request('/test/').then(() => {
expect(false).to.be.true();
}).catch((error) => {
expect(error.errors.length).to.equal(1);
expect(error.errors[0].message).to.equal('Test Error');
done();
});
});
it('correctly parses multiple error messages', function (done) {
let error = {errors: ['First Error', 'Second Error']};
stubAjaxEndpoint(server, error, 500);
let ajax = this.subject();
ajax.request('/test/').then(() => {
expect(false).to.be.true();
}).catch((error) => {
expect(error.errors.length).to.equal(2);
expect(error.errors[0].message).to.equal('First Error');
expect(error.errors[1].message).to.equal('Second Error');
done();
});
});
it('returns default error object for non built-in error', function (done) {
stubAjaxEndpoint(server, {}, 500);
let ajax = this.subject();
ajax.request('/test/').then(() => {
expect(false).to.be.true;
}).catch((error) => {
expect(isAjaxError(error)).to.be.true;
done();
});
});
it('handles error checking for built-in errors', function (done) {
stubAjaxEndpoint(server, '', 401);
let ajax = this.subject();
ajax.request('/test/').then(() => {
expect(false).to.be.true;
}).catch((error) => {
expect(isUnauthorizedError(error)).to.be.true;
done();
});
});
it('handles error checking for VersionMismatchError', function (done) {
server.get('/test/', function () {
return [
400,
{'Content-Type': 'application/json'},
JSON.stringify({
errors: [{
errorType: 'VersionMismatchError',
statusCode: 400
}]
})
];
});
let ajax = this.subject();
ajax.request('/test/').then(() => {
expect(false).to.be.true;
}).catch((error) => {
expect(isVersionMismatchError(error)).to.be.true;
done();
});
});
it('handles error checking for RequestEntityTooLargeError on 413 errors', function (done) {
stubAjaxEndpoint(server, {}, 413);
let ajax = this.subject();
ajax.request('/test/').then(() => {
expect(false).to.be.true;
}).catch((error) => {
expect(isRequestEntityTooLargeError(error)).to.be.true;
done();
});
});
it('handles error checking for UnsupportedMediaTypeError on 415 errors', function (done) {
stubAjaxEndpoint(server, {}, 415);
let ajax = this.subject();
ajax.request('/test/').then(() => {
expect(false).to.be.true;
}).catch((error) => {
expect(isUnsupportedMediaTypeError(error)).to.be.true;
done();
});
});
/* eslint-disable camelcase */
describe('session handling', function () {
let successfulRequest = false;
let sessionStub = Service.extend({
isAuthenticated: true,
restoreCalled: false,
authenticated: null,
init() {
this.authenticated = {
expires_at: (new Date()).getTime() - 10000,
refresh_token: 'RefreshMe123'
};
},
restore() {
this.restoreCalled = true;
this.authenticated.expires_at = (new Date()).getTime() + 10000;
return RSVP.resolve();
},
authorize() {
}
});
beforeEach(function () {
server = new Pretender();
});
afterEach(function () {
server.shutdown();
});
it('adds Ghost version header to requests', function (done) {
let {version} = config.APP;
let ajax = this.subject();
stubAjaxEndpoint(server, {});
ajax.request('/test/').then(() => {
let [request] = server.handledRequests;
expect(request.requestHeaders['X-Ghost-Version']).to.equal(version);
done();
});
});
it('correctly parses single message response text', function (done) {
let error = {message: 'Test Error'};
stubAjaxEndpoint(server, error, 500);
let ajax = this.subject();
ajax.request('/test/').then(() => {
expect(false).to.be.true();
}).catch((error) => {
expect(error.errors.length).to.equal(1);
expect(error.errors[0].message).to.equal('Test Error');
done();
});
});
it('correctly parses single error response text', function (done) {
let error = {error: 'Test Error'};
stubAjaxEndpoint(server, error, 500);
let ajax = this.subject();
ajax.request('/test/').then(() => {
expect(false).to.be.true();
}).catch((error) => {
expect(error.errors.length).to.equal(1);
expect(error.errors[0].message).to.equal('Test Error');
done();
});
});
it('correctly parses multiple error messages', function (done) {
let error = {errors: ['First Error', 'Second Error']};
stubAjaxEndpoint(server, error, 500);
let ajax = this.subject();
ajax.request('/test/').then(() => {
expect(false).to.be.true();
}).catch((error) => {
expect(error.errors.length).to.equal(2);
expect(error.errors[0].message).to.equal('First Error');
expect(error.errors[1].message).to.equal('Second Error');
done();
});
});
it('returns default error object for non built-in error', function (done) {
stubAjaxEndpoint(server, {}, 500);
let ajax = this.subject();
ajax.request('/test/').then(() => {
expect(false).to.be.true;
}).catch((error) => {
expect(isAjaxError(error)).to.be.true;
done();
});
});
it('handles error checking for built-in errors', function (done) {
stubAjaxEndpoint(server, '', 401);
let ajax = this.subject();
ajax.request('/test/').then(() => {
expect(false).to.be.true;
}).catch((error) => {
expect(isUnauthorizedError(error)).to.be.true;
done();
});
});
it('handles error checking for VersionMismatchError', function (done) {
server.get('/test/', function () {
server.get('/ghost/api/v0.1/test/', function () {
return [
400,
200,
{'Content-Type': 'application/json'},
JSON.stringify({
errors: [{
errorType: 'VersionMismatchError',
statusCode: 400
}]
success: true
})
];
});
let ajax = this.subject();
server.post('/ghost/api/v0.1/authentication/token', function () {
return [
401,
{'Content-Type': 'application/json'},
JSON.stringify({})
];
});
});
ajax.request('/test/').then(() => {
expect(false).to.be.true;
}).catch((error) => {
expect(isVersionMismatchError(error)).to.be.true;
it('can restore an expired session', function (done) {
let ajax = this.subject();
ajax.set('session', sessionStub.create());
ajax.request('/ghost/api/v0.1/test/');
ajax.request('/ghost/api/v0.1/test/').then((result) => {
expect(ajax.get('session.restoreCalled'), 'restoreCalled').to.be.true;
expect(result.success, 'result.success').to.be.true;
done();
}).catch(() => {
expect(true, 'request failed').to.be.false;
done();
});
});
it('handles error checking for RequestEntityTooLargeError on 413 errors', function (done) {
stubAjaxEndpoint(server, {}, 413);
it('errors correctly when session restoration fails', function (done) {
let ajax = this.subject();
let invalidateCalled = false;
ajax.request('/test/').then(() => {
expect(false).to.be.true;
}).catch((error) => {
expect(isRequestEntityTooLargeError(error)).to.be.true;
ajax.set('session', sessionStub.create());
ajax.set('session.restore', function () {
this.set('restoreCalled', true);
return ajax.post('/ghost/api/v0.1/authentication/token');
});
ajax.set('session.invalidate', function () {
invalidateCalled = true;
});
stubAjaxEndpoint(server, {}, 401);
ajax.request('/ghost/api/v0.1/test/').then(() => {
expect(true, 'request was successful').to.be.false;
done();
}).catch(() => {
// TODO: fix the error return when a session restore fails
// expect(isUnauthorizedError(error)).to.be.true;
expect(ajax.get('session.restoreCalled'), 'restoreCalled').to.be.true;
expect(successfulRequest, 'successfulRequest').to.be.false;
expect(invalidateCalled, 'invalidateCalled').to.be.true;
done();
});
});
it('handles error checking for UnsupportedMediaTypeError on 415 errors', function (done) {
stubAjaxEndpoint(server, {}, 415);
let ajax = this.subject();
ajax.request('/test/').then(() => {
expect(false).to.be.true;
}).catch((error) => {
expect(isUnsupportedMediaTypeError(error)).to.be.true;
done();
});
});
/* eslint-disable camelcase */
describe('session handling', function () {
let successfulRequest = false;
let sessionStub = Service.extend({
isAuthenticated: true,
restoreCalled: false,
authenticated: null,
init() {
this.authenticated = {
expires_at: (new Date()).getTime() - 10000,
refresh_token: 'RefreshMe123'
};
},
restore() {
this.restoreCalled = true;
this.authenticated.expires_at = (new Date()).getTime() + 10000;
return RSVP.resolve();
},
authorize() {
}
});
beforeEach(function () {
server.get('/ghost/api/v0.1/test/', function () {
return [
200,
{'Content-Type': 'application/json'},
JSON.stringify({
success: true
})
];
});
server.post('/ghost/api/v0.1/authentication/token', function () {
return [
401,
{'Content-Type': 'application/json'},
JSON.stringify({})
];
});
});
it('can restore an expired session', function (done) {
let ajax = this.subject();
ajax.set('session', sessionStub.create());
ajax.request('/ghost/api/v0.1/test/');
ajax.request('/ghost/api/v0.1/test/').then((result) => {
expect(ajax.get('session.restoreCalled'), 'restoreCalled').to.be.true;
expect(result.success, 'result.success').to.be.true;
done();
}).catch(() => {
expect(true, 'request failed').to.be.false;
done();
});
});
it('errors correctly when session restoration fails', function (done) {
let ajax = this.subject();
let invalidateCalled = false;
ajax.set('session', sessionStub.create());
ajax.set('session.restore', function () {
this.set('restoreCalled', true);
return ajax.post('/ghost/api/v0.1/authentication/token');
});
ajax.set('session.invalidate', function () {
invalidateCalled = true;
});
stubAjaxEndpoint(server, {}, 401);
ajax.request('/ghost/api/v0.1/test/').then(() => {
expect(true, 'request was successful').to.be.false;
done();
}).catch(() => {
// TODO: fix the error return when a session restore fails
// expect(isUnauthorizedError(error)).to.be.true;
expect(ajax.get('session.restoreCalled'), 'restoreCalled').to.be.true;
expect(successfulRequest, 'successfulRequest').to.be.false;
expect(invalidateCalled, 'invalidateCalled').to.be.true;
done();
});
});
});
}
);
});
});

View File

@ -1,8 +1,6 @@
import {expect} from 'chai';
import {
describeModule,
it
} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupTest} from 'ember-mocha';
import Pretender from 'pretender';
function stubAvailableTimezonesEndpoint(server) {
@ -28,35 +26,32 @@ function stubAvailableTimezonesEndpoint(server) {
});
}
describeModule(
'service:config',
'Integration: Service: config',
{
describe('Integration: Service: config', function () {
setupTest('service:config', {
integration: true
},
function () {
let server;
});
beforeEach(function () {
server = new Pretender();
let server;
beforeEach(function () {
server = new Pretender();
});
afterEach(function () {
server.shutdown();
});
it('returns a list of timezones in the expected format', function (done) {
let service = this.subject();
stubAvailableTimezonesEndpoint(server);
service.get('availableTimezones').then(function (timezones) {
expect(timezones.length).to.equal(2);
expect(timezones[0].name).to.equal('Pacific/Pago_Pago');
expect(timezones[0].label).to.equal('(GMT -11:00) Midway Island, Samoa');
expect(timezones[1].name).to.equal('Europe/Dublin');
expect(timezones[1].label).to.equal('(GMT) Greenwich Mean Time : Dublin, Edinburgh, London');
done();
});
afterEach(function () {
server.shutdown();
});
it('returns a list of timezones in the expected format', function (done) {
let service = this.subject();
stubAvailableTimezonesEndpoint(server);
service.get('availableTimezones').then(function (timezones) {
expect(timezones.length).to.equal(2);
expect(timezones[0].name).to.equal('Pacific/Pago_Pago');
expect(timezones[0].label).to.equal('(GMT -11:00) Midway Island, Samoa');
expect(timezones[1].name).to.equal('Europe/Dublin');
expect(timezones[1].label).to.equal('(GMT) Greenwich Mean Time : Dublin, Edinburgh, London');
done();
});
});
}
);
});
});

View File

@ -1,7 +1,5 @@
import {
describeModule,
it
} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupTest} from 'ember-mocha';
import Pretender from 'pretender';
import wait from 'ember-test-helpers/wait';
import FeatureService, {feature} from 'ghost-admin/services/feature';
@ -51,167 +49,164 @@ function addTestFlag() {
});
}
describeModule(
'service:feature',
'Integration: Service: feature',
{
describe('Integration: Service: feature', function () {
setupTest('service:feature', {
integration: true
},
function () {
let server;
});
beforeEach(function () {
server = new Pretender();
let server;
beforeEach(function () {
server = new Pretender();
});
afterEach(function () {
server.shutdown();
});
it('loads labs settings correctly', function (done) {
stubSettings(server, {testFlag: true});
addTestFlag();
let service = this.subject();
service.fetch().then(() => {
expect(service.get('testFlag')).to.be.true;
done();
});
});
afterEach(function () {
server.shutdown();
it('returns false for set flag with config false and labs false', function (done) {
stubSettings(server, {testFlag: false});
addTestFlag();
let service = this.subject();
service.get('config').set('testFlag', false);
service.fetch().then(() => {
expect(service.get('labs.testFlag')).to.be.false;
expect(service.get('testFlag')).to.be.false;
done();
});
});
it('loads labs settings correctly', function (done) {
stubSettings(server, {testFlag: true});
addTestFlag();
it('returns true for set flag with config true and labs false', function (done) {
stubSettings(server, {testFlag: false});
addTestFlag();
let service = this.subject();
let service = this.subject();
service.get('config').set('testFlag', true);
service.fetch().then(() => {
service.fetch().then(() => {
expect(service.get('labs.testFlag')).to.be.false;
expect(service.get('testFlag')).to.be.true;
done();
});
});
it('returns true for set flag with config false and labs true', function (done) {
stubSettings(server, {testFlag: true});
addTestFlag();
let service = this.subject();
service.get('config').set('testFlag', false);
service.fetch().then(() => {
expect(service.get('labs.testFlag')).to.be.true;
expect(service.get('testFlag')).to.be.true;
done();
});
});
it('returns true for set flag with config true and labs true', function (done) {
stubSettings(server, {testFlag: true});
addTestFlag();
let service = this.subject();
service.get('config').set('testFlag', true);
service.fetch().then(() => {
expect(service.get('labs.testFlag')).to.be.true;
expect(service.get('testFlag')).to.be.true;
done();
});
});
it('saves correctly', function (done) {
stubSettings(server, {testFlag: false});
addTestFlag();
let service = this.subject();
service.get('config').set('testFlag', false);
service.fetch().then(() => {
expect(service.get('testFlag')).to.be.false;
run(() => {
service.set('testFlag', true);
});
return wait().then(() => {
expect(server.handlers[1].numberOfCalls).to.equal(1);
expect(service.get('testFlag')).to.be.true;
done();
});
});
});
it('returns false for set flag with config false and labs false', function (done) {
stubSettings(server, {testFlag: false});
addTestFlag();
it('notifies for server errors', function (done) {
stubSettings(server, {testFlag: false}, false);
addTestFlag();
let service = this.subject();
service.get('config').set('testFlag', false);
let service = this.subject();
service.get('config').set('testFlag', false);
service.fetch().then(() => {
expect(service.get('testFlag')).to.be.false;
run(() => {
service.set('testFlag', true);
});
return wait().then(() => {
expect(
server.handlers[1].numberOfCalls,
'PUT call is made'
).to.equal(1);
expect(
service.get('notifications.alerts').length,
'number of alerts shown'
).to.equal(1);
service.fetch().then(() => {
expect(service.get('labs.testFlag')).to.be.false;
expect(service.get('testFlag')).to.be.false;
done();
});
});
});
it('returns true for set flag with config true and labs false', function (done) {
stubSettings(server, {testFlag: false});
addTestFlag();
it('notifies for validation errors', function (done) {
stubSettings(server, {testFlag: false}, true, false);
addTestFlag();
let service = this.subject();
service.get('config').set('testFlag', true);
let service = this.subject();
service.get('config').set('testFlag', false);
service.fetch().then(() => {
expect(service.get('labs.testFlag')).to.be.false;
expect(service.get('testFlag')).to.be.true;
done();
});
});
service.fetch().then(() => {
expect(service.get('testFlag')).to.be.false;
it('returns true for set flag with config false and labs true', function (done) {
stubSettings(server, {testFlag: true});
addTestFlag();
let service = this.subject();
service.get('config').set('testFlag', false);
service.fetch().then(() => {
expect(service.get('labs.testFlag')).to.be.true;
expect(service.get('testFlag')).to.be.true;
done();
});
});
it('returns true for set flag with config true and labs true', function (done) {
stubSettings(server, {testFlag: true});
addTestFlag();
let service = this.subject();
service.get('config').set('testFlag', true);
service.fetch().then(() => {
expect(service.get('labs.testFlag')).to.be.true;
expect(service.get('testFlag')).to.be.true;
done();
});
});
it('saves correctly', function (done) {
stubSettings(server, {testFlag: false});
addTestFlag();
let service = this.subject();
service.get('config').set('testFlag', false);
service.fetch().then(() => {
expect(service.get('testFlag')).to.be.false;
run(() => {
run(() => {
expect(() => {
service.set('testFlag', true);
});
return wait().then(() => {
expect(server.handlers[1].numberOfCalls).to.equal(1);
expect(service.get('testFlag')).to.be.true;
done();
});
}, EmberError, 'threw validation error');
});
});
it('notifies for server errors', function (done) {
stubSettings(server, {testFlag: false}, false);
addTestFlag();
let service = this.subject();
service.get('config').set('testFlag', false);
service.fetch().then(() => {
return wait().then(() => {
// ensure validation is happening before the API is hit
expect(server.handlers[1].numberOfCalls).to.equal(0);
expect(service.get('testFlag')).to.be.false;
run(() => {
service.set('testFlag', true);
});
return wait().then(() => {
expect(
server.handlers[1].numberOfCalls,
'PUT call is made'
).to.equal(1);
expect(
service.get('notifications.alerts').length,
'number of alerts shown'
).to.equal(1);
expect(service.get('testFlag')).to.be.false;
done();
});
done();
});
});
it('notifies for validation errors', function (done) {
stubSettings(server, {testFlag: false}, true, false);
addTestFlag();
let service = this.subject();
service.get('config').set('testFlag', false);
service.fetch().then(() => {
expect(service.get('testFlag')).to.be.false;
run(() => {
expect(() => {
service.set('testFlag', true);
}, EmberError, 'threw validation error');
});
return wait().then(() => {
// ensure validation is happening before the API is hit
expect(server.handlers[1].numberOfCalls).to.equal(0);
expect(service.get('testFlag')).to.be.false;
done();
});
});
});
}
);
});
});

View File

@ -1,66 +1,60 @@
/* jshint expr:true */
import {expect} from 'chai';
import {
describeModule,
it
} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupTest} from 'ember-mocha';
import Pretender from 'pretender';
import $ from 'jquery';
describeModule(
'service:lazy-loader',
'Integration: Service: lazy-loader',
{integration: true},
function() {
let server;
let ghostPaths = {
adminRoot: '/assets/'
};
describe('Integration: Service: lazy-loader', function() {
setupTest('service:lazy-loader', {integration: true});
let server;
let ghostPaths = {
adminRoot: '/assets/'
};
beforeEach(function () {
server = new Pretender();
beforeEach(function () {
server = new Pretender();
});
afterEach(function () {
server.shutdown();
});
it('loads a script correctly and only once', function (done) {
let subject = this.subject({
ghostPaths,
scriptPromises: {},
testing: false
});
afterEach(function () {
server.shutdown();
server.get('/assets/test.js', function ({requestHeaders}) {
expect(requestHeaders.Accept).to.match(/text\/javascript/);
return [200, {'Content-Type': 'text/javascript'}, 'window.testLoadScript = \'testvalue\''];
});
it('loads a script correctly and only once', function (done) {
let subject = this.subject({
ghostPaths,
scriptPromises: {},
testing: false
});
subject.loadScript('test-script', 'test.js').then(() => {
expect(subject.get('scriptPromises.test-script')).to.exist;
expect(window.testLoadScript).to.equal('testvalue');
expect(server.handlers[0].numberOfCalls).to.equal(1);
server.get('/assets/test.js', function ({requestHeaders}) {
expect(requestHeaders.Accept).to.match(/text\/javascript/);
return subject.loadScript('test-script', 'test.js');
}).then(() => {
expect(server.handlers[0].numberOfCalls).to.equal(1);
return [200, {'Content-Type': 'text/javascript'}, 'window.testLoadScript = \'testvalue\''];
});
done();
});
});
subject.loadScript('test-script', 'test.js').then(() => {
expect(subject.get('scriptPromises.test-script')).to.exist;
expect(window.testLoadScript).to.equal('testvalue');
expect(server.handlers[0].numberOfCalls).to.equal(1);
return subject.loadScript('test-script', 'test.js');
}).then(() => {
expect(server.handlers[0].numberOfCalls).to.equal(1);
done();
});
it('loads styles correctly', function () {
let subject = this.subject({
ghostPaths,
testing: false
});
it('loads styles correctly', function () {
let subject = this.subject({
ghostPaths,
testing: false
});
subject.loadStyle('testing', 'style.css');
subject.loadStyle('testing', 'style.css');
expect($('#testing-styles').length).to.equal(1);
expect($('#testing-styles').attr('href')).to.equal('/assets/style.css');
});
}
);
expect($('#testing-styles').length).to.equal(1);
expect($('#testing-styles').attr('href')).to.equal('/assets/style.css');
});
});

View File

@ -1,8 +1,6 @@
import {expect} from 'chai';
import {
describeModule,
it
} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupTest} from 'ember-mocha';
import Pretender from 'pretender';
import {dasherize} from 'ember-string';
@ -19,42 +17,39 @@ function stubSlugEndpoint(server, type, slug) {
});
}
describeModule(
'service:slug-generator',
'Integration: Service: slug-generator',
{
describe('Integration: Service: slug-generator', function () {
setupTest('service:slug-generator', {
integration: true
},
function () {
let server;
});
beforeEach(function () {
server = new Pretender();
let server;
beforeEach(function () {
server = new Pretender();
});
afterEach(function () {
server.shutdown();
});
it('returns empty if no slug is provided', function (done) {
let service = this.subject();
service.generateSlug('post', '').then(function (slug) {
expect(slug).to.equal('');
done();
});
});
afterEach(function () {
server.shutdown();
it('calls correct endpoint and returns correct data', function (done) {
let rawSlug = 'a test post';
stubSlugEndpoint(server, 'post', rawSlug);
let service = this.subject();
service.generateSlug('post', rawSlug).then(function (slug) {
expect(slug).to.equal(dasherize(rawSlug));
done();
});
it('returns empty if no slug is provided', function (done) {
let service = this.subject();
service.generateSlug('post', '').then(function (slug) {
expect(slug).to.equal('');
done();
});
});
it('calls correct endpoint and returns correct data', function (done) {
let rawSlug = 'a test post';
stubSlugEndpoint(server, 'post', rawSlug);
let service = this.subject();
service.generateSlug('post', rawSlug).then(function (slug) {
expect(slug).to.equal(dasherize(rawSlug));
done();
});
});
}
);
});
});

View File

@ -1,45 +1,40 @@
import {expect} from 'chai';
import {
describeModule,
it
} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupTest} from 'ember-mocha';
import Pretender from 'pretender';
import config from 'ghost-admin/config/environment';
describeModule(
'service:store',
'Integration: Service: store',
{
describe('Integration: Service: store', function () {
setupTest('service:store', {
integration: true
},
function () {
let server;
});
beforeEach(function () {
server = new Pretender();
let server;
beforeEach(function () {
server = new Pretender();
});
afterEach(function () {
server.shutdown();
});
it('adds Ghost version header to requests', function (done) {
let {version} = config.APP;
let store = this.subject();
server.get('/ghost/api/v0.1/posts/1/', function () {
return [
404,
{'Content-Type': 'application/json'},
JSON.stringify({})
];
});
afterEach(function () {
server.shutdown();
store.find('post', 1).catch(() => {
let [request] = server.handledRequests;
expect(request.requestHeaders['X-Ghost-Version']).to.equal(version);
done();
});
it('adds Ghost version header to requests', function (done) {
let {version} = config.APP;
let store = this.subject();
server.get('/ghost/api/v0.1/posts/1/', function () {
return [
404,
{'Content-Type': 'application/json'},
JSON.stringify({})
];
});
store.find('post', 1).catch(() => {
let [request] = server.handledRequests;
expect(request.requestHeaders['X-Ghost-Version']).to.equal(version);
done();
});
});
}
);
});
});

View File

@ -1,8 +1,6 @@
import {expect} from 'chai';
import {
describeModule,
it
} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupTest} from 'ember-mocha';
import Pretender from 'pretender';
function settingsStub(server) {
@ -20,32 +18,29 @@ function settingsStub(server) {
});
}
describeModule(
'service:time-zone',
'Integration: Service: time-zone',
{
describe('Integration: Service: time-zone', function () {
setupTest('service:time-zone', {
integration: true
},
function () {
let server;
});
beforeEach(function () {
server = new Pretender();
let server;
beforeEach(function () {
server = new Pretender();
});
afterEach(function () {
server.shutdown();
});
it('should return the blogs timezone', function (done) {
let service = this.subject();
settingsStub(server);
service.get('blogTimezone').then(function (blogTimezone) {
expect(blogTimezone).to.equal('Africa/Cairo');
done();
});
afterEach(function () {
server.shutdown();
});
it('should return the blogs timezone', function (done) {
let service = this.subject();
settingsStub(server);
service.get('blogTimezone').then(function (blogTimezone) {
expect(blogTimezone).to.equal('Africa/Cairo');
done();
});
});
}
);
});
});

View File

@ -1,33 +1,27 @@
/* jshint expr:true */
import {expect} from 'chai';
import {
describeComponent,
it
}
from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupComponentTest} from 'ember-mocha';
import sinon from 'sinon';
describeComponent(
'gh-alert',
'Unit: Component: gh-alert',
{
describe('Unit: Component: gh-alert', function () {
setupComponentTest('gh-alert', {
unit: true
// specify the other units that are required for this test
// needs: ['component:foo', 'helper:bar']
},
function () {
it('closes notification through notifications service', function () {
let component = this.subject();
let notifications = {};
let notification = {message: 'Test close', type: 'success'};
});
notifications.closeNotification = sinon.spy();
component.set('notifications', notifications);
component.set('message', notification);
it('closes notification through notifications service', function () {
let component = this.subject();
let notifications = {};
let notification = {message: 'Test close', type: 'success'};
this.$().find('button').click();
notifications.closeNotification = sinon.spy();
component.set('notifications', notifications);
component.set('message', notification);
expect(notifications.closeNotification.calledWith(notification)).to.be.true;
});
}
);
this.$().find('button').click();
expect(notifications.closeNotification.calledWith(notification)).to.be.true;
});
});

View File

@ -1,28 +1,23 @@
/* jshint expr:true */
import {expect} from 'chai';
import {
describeComponent,
it
} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupComponentTest} from 'ember-mocha';
describeComponent(
'gh-app',
'Unit: Component: gh-app',
{
describe('Unit: Component: gh-app', function () {
setupComponentTest('gh-app', {
unit: true
// specify the other units that are required for this test
// needs: ['component:foo', 'helper:bar']
},
function () {
it('renders', function () {
// creates the component instance
let component = this.subject();
});
expect(component._state).to.equal('preRender');
it('renders', function () {
// creates the component instance
let component = this.subject();
// renders the component on the page
this.render();
expect(component._state).to.equal('inDOM');
});
}
);
expect(component._state).to.equal('preRender');
// renders the component on the page
this.render();
expect(component._state).to.equal('inDOM');
});
});

View File

@ -1,28 +1,23 @@
/* jshint expr:true */
import {expect} from 'chai';
import {
describeComponent,
it
} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupComponentTest} from 'ember-mocha';
describeComponent(
'gh-content-preview-content',
'Unit: Component: gh-content-preview-content',
{
describe('Unit: Component: gh-content-preview-content', function () {
setupComponentTest('gh-content-preview-content', {
unit: true
// specify the other units that are required for this test
// needs: ['component:foo', 'helper:bar']
},
function () {
it('renders', function () {
// creates the component instance
let component = this.subject();
});
expect(component._state).to.equal('preRender');
it('renders', function () {
// creates the component instance
let component = this.subject();
// renders the component on the page
this.render();
expect(component._state).to.equal('inDOM');
});
}
);
expect(component._state).to.equal('preRender');
// renders the component on the page
this.render();
expect(component._state).to.equal('inDOM');
});
});

View File

@ -1,14 +1,10 @@
/* jshint expr:true */
import {expect} from 'chai';
import {
describeComponent,
it
} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupComponentTest} from 'ember-mocha';
describeComponent(
'gh-editor-save-button',
'Unit: Component: gh-editor-save-button',
{
describe('Unit: Component: gh-editor-save-button', function () {
setupComponentTest('gh-editor-save-button', {
unit: true,
needs: [
'component:gh-dropdown-button',
@ -16,17 +12,16 @@ describeComponent(
'component:gh-spin-button',
'service:dropdown'
]
},
function () {
it('renders', function () {
// creates the component instance
let component = this.subject();
});
expect(component._state).to.equal('preRender');
it('renders', function () {
// creates the component instance
let component = this.subject();
// renders the component on the page
this.render();
expect(component._state).to.equal('inDOM');
});
}
);
expect(component._state).to.equal('preRender');
// renders the component on the page
this.render();
expect(component._state).to.equal('inDOM');
});
});

View File

@ -1,28 +1,23 @@
/* jshint expr:true */
import {expect} from 'chai';
import {
describeComponent,
it
} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupComponentTest} from 'ember-mocha';
describeComponent(
'gh-infinite-scroll',
'Unit: Component: gh-infinite-scroll',
{
describe('Unit: Component: gh-infinite-scroll', function () {
setupComponentTest('gh-infinite-scroll', {
unit: true
// specify the other units that are required for this test
// needs: ['component:foo', 'helper:bar']
},
function () {
it('renders', function () {
// creates the component instance
let component = this.subject();
});
expect(component._state).to.equal('preRender');
it('renders', function () {
// creates the component instance
let component = this.subject();
// renders the component on the page
this.render();
expect(component._state).to.equal('inDOM');
});
}
);
expect(component._state).to.equal('preRender');
// renders the component on the page
this.render();
expect(component._state).to.equal('inDOM');
});
});

View File

@ -1,37 +1,32 @@
/* jshint expr:true */
import run from 'ember-runloop';
import {expect} from 'chai';
import {
describeComponent,
it
} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupComponentTest} from 'ember-mocha';
describeComponent(
'gh-navitem-url-input',
'Unit: Component: gh-navitem-url-input',
{
describe('Unit: Component: gh-navitem-url-input', function () {
setupComponentTest('gh-navitem-url-input', {
unit: true
},
function () {
it('identifies a URL as the base URL', function () {
let component = this.subject({
url: '',
baseUrl: 'http://example.com/'
});
});
this.render();
run(function () {
component.set('value', 'http://example.com/');
});
expect(component.get('isBaseUrl')).to.be.ok;
run(function () {
component.set('value', 'http://example.com/go/');
});
expect(component.get('isBaseUrl')).to.not.be.ok;
it('identifies a URL as the base URL', function () {
let component = this.subject({
url: '',
baseUrl: 'http://example.com/'
});
}
);
this.render();
run(function () {
component.set('value', 'http://example.com/');
});
expect(component.get('isBaseUrl')).to.be.ok;
run(function () {
component.set('value', 'http://example.com/go/');
});
expect(component.get('isBaseUrl')).to.not.be.ok;
});
});

View File

@ -1,50 +1,44 @@
/* jshint expr:true */
import {expect} from 'chai';
import {
describeComponent,
it
}
from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupComponentTest} from 'ember-mocha';
import sinon from 'sinon';
describeComponent(
'gh-notification',
'Unit: Component: gh-notification',
{
describe('Unit: Component: gh-notification', function () {
setupComponentTest('gh-notification', {
unit: true
// specify the other units that are required for this test
// needs: ['component:foo', 'helper:bar']
},
function () {
it('closes notification through notifications service', function () {
let component = this.subject();
let notifications = {};
let notification = {message: 'Test close', type: 'success'};
});
notifications.closeNotification = sinon.spy();
component.set('notifications', notifications);
component.set('message', notification);
it('closes notification through notifications service', function () {
let component = this.subject();
let notifications = {};
let notification = {message: 'Test close', type: 'success'};
this.$().find('button').click();
notifications.closeNotification = sinon.spy();
component.set('notifications', notifications);
component.set('message', notification);
this.$().find('button').click();
expect(notifications.closeNotification.calledWith(notification)).to.be.true;
});
it('closes notification when animationend event is triggered', function (done) {
let component = this.subject();
let notifications = {};
let notification = {message: 'Test close', type: 'success'};
notifications.closeNotification = sinon.spy();
component.set('notifications', notifications);
component.set('message', notification);
// shorten the animation delay to speed up test
this.$().css('animation-delay', '0.1s');
setTimeout(function () {
expect(notifications.closeNotification.calledWith(notification)).to.be.true;
});
it('closes notification when animationend event is triggered', function (done) {
let component = this.subject();
let notifications = {};
let notification = {message: 'Test close', type: 'success'};
notifications.closeNotification = sinon.spy();
component.set('notifications', notifications);
component.set('message', notification);
// shorten the animation delay to speed up test
this.$().css('animation-delay', '0.1s');
setTimeout(function () {
expect(notifications.closeNotification.calledWith(notification)).to.be.true;
done();
}, 150);
});
}
);
done();
}, 150);
});
});

View File

@ -1,38 +1,33 @@
/* jshint expr:true */
import {expect} from 'chai';
import {
describeComponent,
it
} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupComponentTest} from 'ember-mocha';
import {A as emberA} from 'ember-array/utils';
import run from 'ember-runloop';
describeComponent(
'gh-selectize',
'Unit: Component: gh-selectize',
{
describe('Unit: Component: gh-selectize', function () {
setupComponentTest('gh-selectize', {
// Specify the other units that are required for this test
// needs: ['component:foo', 'helper:bar'],
unit: true
},
function () {
it('re-orders selection when selectize order is changed', function () {
let component = this.subject();
});
run(() => {
component.set('content', emberA(['item 1', 'item 2', 'item 3']));
component.set('selection', emberA(['item 2', 'item 3']));
component.set('multiple', true);
});
it('re-orders selection when selectize order is changed', function () {
let component = this.subject();
this.render();
run(() => {
component._selectize.setValue(['item 3', 'item 2']);
});
expect(component.get('value').toArray(), 'component value').to.deep.equal(['item 3', 'item 2']);
expect(component.get('selection').toArray(), 'component selection').to.deep.equal(['item 3', 'item 2']);
run(() => {
component.set('content', emberA(['item 1', 'item 2', 'item 3']));
component.set('selection', emberA(['item 2', 'item 3']));
component.set('multiple', true);
});
}
);
this.render();
run(() => {
component._selectize.setValue(['item 3', 'item 2']);
});
expect(component.get('value').toArray(), 'component value').to.deep.equal(['item 3', 'item 2']);
expect(component.get('selection').toArray(), 'component selection').to.deep.equal(['item 3', 'item 2']);
});
});

View File

@ -1,28 +1,23 @@
/* jshint expr:true */
import {expect} from 'chai';
import {
describeComponent,
it
} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupComponentTest} from 'ember-mocha';
describeComponent(
'gh-spin-button',
'Unit: Component: gh-spin-button',
{
describe('Unit: Component: gh-spin-button', function () {
setupComponentTest('gh-spin-button', {
unit: true
// specify the other units that are required for this test
// needs: ['component:foo', 'helper:bar']
},
function () {
it('renders', function () {
// creates the component instance
let component = this.subject();
});
expect(component._state).to.equal('preRender');
it('renders', function () {
// creates the component instance
let component = this.subject();
// renders the component on the page
this.render();
expect(component._state).to.equal('inDOM');
});
}
);
expect(component._state).to.equal('preRender');
// renders the component on the page
this.render();
expect(component._state).to.equal('inDOM');
});
});

View File

@ -1,36 +1,30 @@
/* jshint expr:true */
import {expect} from 'chai';
import {
describeComponent,
it
}
from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupComponentTest} from 'ember-mocha';
describeComponent(
'gh-upgrade-notification',
'GhUpgradeNotificationComponent',
{
describe('GhUpgradeNotificationComponent', function() {
setupComponentTest('gh-upgrade-notification', {
needs: ['helper:gh-format-html']
},
function() {
beforeEach(function() {
let upgradeMessage = {'content': 'Ghost 10.02.91 is available! Hot Damn. <a href="http://support.ghost.org/how-to-upgrade/" target="_blank">Click here</a> to upgrade.'};
this.subject().set('upgradeNotification', upgradeMessage);
});
});
it('renders', function() {
// creates the component instance
let component = this.subject();
expect(component._state).to.equal('preRender');
beforeEach(function() {
let upgradeMessage = {'content': 'Ghost 10.02.91 is available! Hot Damn. <a href="http://support.ghost.org/how-to-upgrade/" target="_blank">Click here</a> to upgrade.'};
this.subject().set('upgradeNotification', upgradeMessage);
});
// renders the component on the page
this.render();
expect(component._state).to.equal('inDOM');
it('renders', function() {
// creates the component instance
let component = this.subject();
expect(component._state).to.equal('preRender');
expect(this.$().prop('tagName')).to.equal('SECTION');
expect(this.$().hasClass('gh-upgrade-notification')).to.be.true;
// caja tools sanitize target='_blank' attribute
expect(this.$().html()).to.contain('Hot Damn. <a href="http://support.ghost.org/how-to-upgrade/">Click here</a>');
});
}
);
// renders the component on the page
this.render();
expect(component._state).to.equal('inDOM');
expect(this.$().prop('tagName')).to.equal('SECTION');
expect(this.$().hasClass('gh-upgrade-notification')).to.be.true;
// caja tools sanitize target='_blank' attribute
expect(this.$().html()).to.contain('Hot Damn. <a href="http://support.ghost.org/how-to-upgrade/">Click here</a>');
});
});

View File

@ -1,42 +1,37 @@
import {
describeComponent,
it
} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupComponentTest} from 'ember-mocha';
describeComponent(
'gh-url-preview',
'Unit: Component: gh-url-preview',
{
describe('Unit: Component: gh-url-preview', function () {
setupComponentTest('gh-url-preview', {
unit: true
},
function () {
it('generates the correct preview URL with a prefix', function () {
let component = this.subject({
prefix: 'tag',
slug: 'test-slug',
tagName: 'p',
classNames: 'test-class',
});
config: {blogUrl: 'http://my-ghost-blog.com'}
});
it('generates the correct preview URL with a prefix', function () {
let component = this.subject({
prefix: 'tag',
slug: 'test-slug',
tagName: 'p',
classNames: 'test-class',
this.render();
expect(component.get('url')).to.equal('my-ghost-blog.com/tag/test-slug/');
config: {blogUrl: 'http://my-ghost-blog.com'}
});
it('generates the correct preview URL without a prefix', function () {
let component = this.subject({
slug: 'test-slug',
tagName: 'p',
classNames: 'test-class',
this.render();
config: {blogUrl: 'http://my-ghost-blog.com'}
});
expect(component.get('url')).to.equal('my-ghost-blog.com/tag/test-slug/');
});
this.render();
it('generates the correct preview URL without a prefix', function () {
let component = this.subject({
slug: 'test-slug',
tagName: 'p',
classNames: 'test-class',
expect(component.get('url')).to.equal('my-ghost-blog.com/test-slug/');
config: {blogUrl: 'http://my-ghost-blog.com'}
});
}
);
this.render();
expect(component.get('url')).to.equal('my-ghost-blog.com/test-slug/');
});
});

View File

@ -1,28 +1,23 @@
/* jshint expr:true */
import {expect} from 'chai';
import {
describeComponent,
it
} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupComponentTest} from 'ember-mocha';
describeComponent(
'gh-user-active',
'Unit: Component: gh-user-active',
{
describe('Unit: Component: gh-user-active', function () {
setupComponentTest('gh-user-active', {
unit: true
// specify the other units that are required for this test
// needs: ['component:foo', 'helper:bar']
},
function () {
it('renders', function () {
// creates the component instance
let component = this.subject();
});
expect(component._state).to.equal('preRender');
it('renders', function () {
// creates the component instance
let component = this.subject();
// renders the component on the page
this.render();
expect(component._state).to.equal('inDOM');
});
}
);
expect(component._state).to.equal('preRender');
// renders the component on the page
this.render();
expect(component._state).to.equal('inDOM');
});
});

View File

@ -1,28 +1,23 @@
/* jshint expr:true */
import {expect} from 'chai';
import {
describeComponent,
it
} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupComponentTest} from 'ember-mocha';
describeComponent(
'gh-user-invited',
'Unit: Component: gh-user-invited',
{
describe('Unit: Component: gh-user-invited', function () {
setupComponentTest('gh-user-invited', {
unit: true
// specify the other units that are required for this test
// needs: ['component:foo', 'helper:bar']
},
function () {
it('renders', function () {
// creates the component instance
let component = this.subject();
});
expect(component._state).to.equal('preRender');
it('renders', function () {
// creates the component instance
let component = this.subject();
// renders the component on the page
this.render();
expect(component._state).to.equal('inDOM');
});
}
);
expect(component._state).to.equal('preRender');
// renders the component on the page
this.render();
expect(component._state).to.equal('inDOM');
});
});

File diff suppressed because it is too large Load Diff

View File

@ -1,58 +1,52 @@
import Ember from 'ember';
import {
describeModule,
it
} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupTest} from 'ember-mocha';
const {
run,
Object: EmberObject
} = Ember;
describeModule(
'controller:settings/general',
'Unit: Controller: settings/general',
{
describe('Unit: Controller: settings/general', function () {
setupTest('controller:settings/general', {
needs: ['service:notifications']
},
});
function () {
it('isDatedPermalinks should be correct', function () {
let controller = this.subject({
model: EmberObject.create({
permalinks: '/:year/:month/:day/:slug/'
})
});
it('isDatedPermalinks should be correct', function () {
let controller = this.subject({
model: EmberObject.create({
permalinks: '/:year/:month/:day/:slug/'
})
});
expect(controller.get('isDatedPermalinks')).to.be.ok;
run(function () {
controller.set('model.permalinks', '/:slug/');
expect(controller.get('isDatedPermalinks')).to.not.be.ok;
});
});
it('setting isDatedPermalinks should switch between dated and slug', function () {
let controller = this.subject({
model: EmberObject.create({
permalinks: '/:year/:month/:day/:slug/'
})
});
run(function () {
controller.set('isDatedPermalinks', false);
expect(controller.get('isDatedPermalinks')).to.not.be.ok;
expect(controller.get('model.permalinks')).to.equal('/:slug/');
});
run(function () {
controller.set('isDatedPermalinks', true);
expect(controller.get('isDatedPermalinks')).to.be.ok;
run(function () {
controller.set('model.permalinks', '/:slug/');
expect(controller.get('isDatedPermalinks')).to.not.be.ok;
});
expect(controller.get('model.permalinks')).to.equal('/:year/:month/:day/:slug/');
});
it('setting isDatedPermalinks should switch between dated and slug', function () {
let controller = this.subject({
model: EmberObject.create({
permalinks: '/:year/:month/:day/:slug/'
})
});
run(function () {
controller.set('isDatedPermalinks', false);
expect(controller.get('isDatedPermalinks')).to.not.be.ok;
expect(controller.get('model.permalinks')).to.equal('/:slug/');
});
run(function () {
controller.set('isDatedPermalinks', true);
expect(controller.get('isDatedPermalinks')).to.be.ok;
expect(controller.get('model.permalinks')).to.equal('/:year/:month/:day/:slug/');
});
});
}
);
});
});

View File

@ -1,6 +1,7 @@
/* jshint expr:true */
import {expect, assert} from 'chai';
import {describeModule, it} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupTest} from 'ember-mocha';
import Ember from 'ember';
import NavItem from 'ghost-admin/models/navigation-item';
@ -20,10 +21,8 @@ const {
// {"label":"No Protocol","url":"//example.com"}
// ]`;
describeModule(
'controller:settings/navigation',
'Unit: Controller: settings/navigation',
{
describe('Unit: Controller: settings/navigation', function () {
setupTest('controller:settings/navigation', {
// Specify the other units that are required for this test.
needs: [
'service:config',
@ -33,159 +32,158 @@ describeModule(
'service:ghostPaths',
'service:upgrade-status'
]
},
function () {
it('blogUrl: captures config and ensures trailing slash', function () {
let ctrl = this.subject();
ctrl.set('config.blogUrl', 'http://localhost:2368/blog');
expect(ctrl.get('blogUrl')).to.equal('http://localhost:2368/blog/');
});
});
it('init: creates a new navigation item', function () {
let ctrl = this.subject();
it('blogUrl: captures config and ensures trailing slash', function () {
let ctrl = this.subject();
ctrl.set('config.blogUrl', 'http://localhost:2368/blog');
expect(ctrl.get('blogUrl')).to.equal('http://localhost:2368/blog/');
});
run(() => {
expect(ctrl.get('newNavItem')).to.exist;
expect(ctrl.get('newNavItem.isNew')).to.be.true;
});
});
it('init: creates a new navigation item', function () {
let ctrl = this.subject();
it('blogUrl: captures config and ensures trailing slash', function () {
let ctrl = this.subject();
ctrl.set('config.blogUrl', 'http://localhost:2368/blog');
expect(ctrl.get('blogUrl')).to.equal('http://localhost:2368/blog/');
});
it('save: validates nav items', function (done) {
let ctrl = this.subject();
run(() => {
ctrl.set('model', EmberObject.create({navigation: [
NavItem.create({label: 'First', url: '/'}),
NavItem.create({label: '', url: '/second'}),
NavItem.create({label: 'Third', url: ''})
]}));
// blank item won't get added because the last item is incomplete
expect(ctrl.get('model.navigation.length')).to.equal(3);
ctrl.save().then(function passedValidation() {
assert(false, 'navigationItems weren\'t validated on save');
done();
}).catch(function failedValidation() {
let navItems = ctrl.get('model.navigation');
expect(navItems[0].get('errors').toArray()).to.be.empty;
expect(navItems[1].get('errors.firstObject.attribute')).to.equal('label');
expect(navItems[2].get('errors.firstObject.attribute')).to.equal('url');
done();
});
});
});
it('save: ignores blank last item when saving', function (done) {
let ctrl = this.subject();
run(() => {
ctrl.set('model', EmberObject.create({navigation: [
NavItem.create({label: 'First', url: '/'}),
NavItem.create({label: '', url: ''})
]}));
expect(ctrl.get('model.navigation.length')).to.equal(2);
ctrl.save().then(function passedValidation() {
assert(false, 'navigationItems weren\'t validated on save');
done();
}).catch(function failedValidation() {
let navItems = ctrl.get('model.navigation');
expect(navItems[0].get('errors').toArray()).to.be.empty;
done();
});
});
});
it('action - addItem: adds item to navigationItems', function () {
let ctrl = this.subject();
run(() => {
ctrl.set('model', EmberObject.create({navigation: [
NavItem.create({label: 'First', url: '/first', last: true})
]}));
});
expect(ctrl.get('model.navigation.length')).to.equal(1);
ctrl.set('newNavItem.label', 'New');
ctrl.set('newNavItem.url', '/new');
run(() => {
ctrl.send('addItem');
});
expect(ctrl.get('model.navigation.length')).to.equal(2);
expect(ctrl.get('model.navigation.lastObject.label')).to.equal('New');
expect(ctrl.get('model.navigation.lastObject.url')).to.equal('/new');
expect(ctrl.get('model.navigation.lastObject.isNew')).to.be.false;
expect(ctrl.get('newNavItem.label')).to.be.blank;
expect(ctrl.get('newNavItem.url')).to.be.blank;
run(() => {
expect(ctrl.get('newNavItem')).to.exist;
expect(ctrl.get('newNavItem.isNew')).to.be.true;
});
});
it('action - addItem: doesn\'t insert new item if last object is incomplete', function () {
let ctrl = this.subject();
it('blogUrl: captures config and ensures trailing slash', function () {
let ctrl = this.subject();
ctrl.set('config.blogUrl', 'http://localhost:2368/blog');
expect(ctrl.get('blogUrl')).to.equal('http://localhost:2368/blog/');
});
run(() => {
ctrl.set('model', EmberObject.create({navigation: [
NavItem.create({label: '', url: '', last: true})
]}));
expect(ctrl.get('model.navigation.length')).to.equal(1);
ctrl.send('addItem');
expect(ctrl.get('model.navigation.length')).to.equal(1);
it('save: validates nav items', function (done) {
let ctrl = this.subject();
run(() => {
ctrl.set('model', EmberObject.create({navigation: [
NavItem.create({label: 'First', url: '/'}),
NavItem.create({label: '', url: '/second'}),
NavItem.create({label: 'Third', url: ''})
]}));
// blank item won't get added because the last item is incomplete
expect(ctrl.get('model.navigation.length')).to.equal(3);
ctrl.save().then(function passedValidation() {
assert(false, 'navigationItems weren\'t validated on save');
done();
}).catch(function failedValidation() {
let navItems = ctrl.get('model.navigation');
expect(navItems[0].get('errors').toArray()).to.be.empty;
expect(navItems[1].get('errors.firstObject.attribute')).to.equal('label');
expect(navItems[2].get('errors.firstObject.attribute')).to.equal('url');
done();
});
});
});
it('action - deleteItem: removes item from navigationItems', function () {
let ctrl = this.subject();
let navItems = [
NavItem.create({label: 'First', url: '/first'}),
NavItem.create({label: 'Second', url: '/second', last: true})
];
it('save: ignores blank last item when saving', function (done) {
let ctrl = this.subject();
run(() => {
ctrl.set('model', EmberObject.create({navigation: navItems}));
expect(ctrl.get('model.navigation').mapBy('label')).to.deep.equal(['First', 'Second']);
ctrl.send('deleteItem', ctrl.get('model.navigation.firstObject'));
expect(ctrl.get('model.navigation').mapBy('label')).to.deep.equal(['Second']);
run(() => {
ctrl.set('model', EmberObject.create({navigation: [
NavItem.create({label: 'First', url: '/'}),
NavItem.create({label: '', url: ''})
]}));
expect(ctrl.get('model.navigation.length')).to.equal(2);
ctrl.save().then(function passedValidation() {
assert(false, 'navigationItems weren\'t validated on save');
done();
}).catch(function failedValidation() {
let navItems = ctrl.get('model.navigation');
expect(navItems[0].get('errors').toArray()).to.be.empty;
done();
});
});
});
it('action - reorderItems: updates navigationItems list', function () {
let ctrl = this.subject();
let navItems = [
NavItem.create({label: 'First', url: '/first'}),
NavItem.create({label: 'Second', url: '/second', last: true})
];
it('action - addItem: adds item to navigationItems', function () {
let ctrl = this.subject();
run(() => {
ctrl.set('model', EmberObject.create({navigation: navItems}));
expect(ctrl.get('model.navigation').mapBy('label')).to.deep.equal(['First', 'Second']);
ctrl.send('reorderItems', navItems.reverseObjects());
expect(ctrl.get('model.navigation').mapBy('label')).to.deep.equal(['Second', 'First']);
});
run(() => {
ctrl.set('model', EmberObject.create({navigation: [
NavItem.create({label: 'First', url: '/first', last: true})
]}));
});
it('action - updateUrl: updates URL on navigationItem', function () {
let ctrl = this.subject();
let navItems = [
NavItem.create({label: 'First', url: '/first'}),
NavItem.create({label: 'Second', url: '/second', last: true})
];
expect(ctrl.get('model.navigation.length')).to.equal(1);
run(() => {
ctrl.set('model', EmberObject.create({navigation: navItems}));
expect(ctrl.get('model.navigation').mapBy('url')).to.deep.equal(['/first', '/second']);
ctrl.send('updateUrl', '/new', ctrl.get('model.navigation.firstObject'));
expect(ctrl.get('model.navigation').mapBy('url')).to.deep.equal(['/new', '/second']);
});
ctrl.set('newNavItem.label', 'New');
ctrl.set('newNavItem.url', '/new');
run(() => {
ctrl.send('addItem');
});
}
);
expect(ctrl.get('model.navigation.length')).to.equal(2);
expect(ctrl.get('model.navigation.lastObject.label')).to.equal('New');
expect(ctrl.get('model.navigation.lastObject.url')).to.equal('/new');
expect(ctrl.get('model.navigation.lastObject.isNew')).to.be.false;
expect(ctrl.get('newNavItem.label')).to.be.blank;
expect(ctrl.get('newNavItem.url')).to.be.blank;
expect(ctrl.get('newNavItem.isNew')).to.be.true;
});
it('action - addItem: doesn\'t insert new item if last object is incomplete', function () {
let ctrl = this.subject();
run(() => {
ctrl.set('model', EmberObject.create({navigation: [
NavItem.create({label: '', url: '', last: true})
]}));
expect(ctrl.get('model.navigation.length')).to.equal(1);
ctrl.send('addItem');
expect(ctrl.get('model.navigation.length')).to.equal(1);
});
});
it('action - deleteItem: removes item from navigationItems', function () {
let ctrl = this.subject();
let navItems = [
NavItem.create({label: 'First', url: '/first'}),
NavItem.create({label: 'Second', url: '/second', last: true})
];
run(() => {
ctrl.set('model', EmberObject.create({navigation: navItems}));
expect(ctrl.get('model.navigation').mapBy('label')).to.deep.equal(['First', 'Second']);
ctrl.send('deleteItem', ctrl.get('model.navigation.firstObject'));
expect(ctrl.get('model.navigation').mapBy('label')).to.deep.equal(['Second']);
});
});
it('action - reorderItems: updates navigationItems list', function () {
let ctrl = this.subject();
let navItems = [
NavItem.create({label: 'First', url: '/first'}),
NavItem.create({label: 'Second', url: '/second', last: true})
];
run(() => {
ctrl.set('model', EmberObject.create({navigation: navItems}));
expect(ctrl.get('model.navigation').mapBy('label')).to.deep.equal(['First', 'Second']);
ctrl.send('reorderItems', navItems.reverseObjects());
expect(ctrl.get('model.navigation').mapBy('label')).to.deep.equal(['Second', 'First']);
});
});
it('action - updateUrl: updates URL on navigationItem', function () {
let ctrl = this.subject();
let navItems = [
NavItem.create({label: 'First', url: '/first'}),
NavItem.create({label: 'Second', url: '/second', last: true})
];
run(() => {
ctrl.set('model', EmberObject.create({navigation: navItems}));
expect(ctrl.get('model.navigation').mapBy('url')).to.deep.equal(['/first', '/second']);
ctrl.send('updateUrl', '/new', ctrl.get('model.navigation.firstObject'));
expect(ctrl.get('model.navigation').mapBy('url')).to.deep.equal(['/new', '/second']);
});
});
});

View File

@ -1,21 +1,16 @@
/* jshint expr:true */
import {expect} from 'chai';
import {
describeModule,
it
} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupTest} from 'ember-mocha';
describeModule(
'controller:subscribers',
'Unit: Controller: subscribers',
{
describe('Unit: Controller: subscribers', function() {
setupTest('controller:subscribers', {
needs: ['service:notifications']
},
function() {
// Replace this with your real tests.
it('exists', function() {
let controller = this.subject();
expect(controller).to.be.ok;
});
}
);
});
// Replace this with your real tests.
it('exists', function() {
let controller = this.subject();
expect(controller).to.be.ok;
});
});

View File

@ -1,6 +1,4 @@
import {
it
} from 'ember-mocha';
import {it} from 'mocha';
import {ghUserCanAdmin} from 'ghost-admin/helpers/gh-user-can-admin';
describe('Unit: Helper: gh-user-can-admin', function () {

View File

@ -1,12 +1,11 @@
import {expect} from 'chai';
import {describeModel, it} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupModelTest} from 'ember-mocha';
import run from 'ember-runloop';
import Pretender from 'pretender';
describeModel(
'invite',
'Unit: Model: invite',
{
describe('Unit: Model: invite', function() {
setupModelTest('invite', {
needs: [
'model:role',
'serializer:application',
@ -17,52 +16,51 @@ describeModel(
'service:session',
'service:feature'
]
},
function() {
describe('with network', function () {
let server;
});
beforeEach(function () {
server = new Pretender();
});
describe('with network', function () {
let server;
afterEach(function () {
server.shutdown();
});
it('resend hits correct endpoint', function () {
let model = this.subject();
let role;
server.post('/ghost/api/v0.1/invites/', function () {
return [200, {}, '{}'];
});
run(() => {
role = this.store().push({data: {id: 1, type: 'role', attributes: {name: 'Editor'}}});
model.set('email', 'resend-test@example.com');
model.set('role', role);
model.resend();
});
expect(
server.handledRequests.length,
'number of requests'
).to.equal(1);
let [lastRequest] = server.handledRequests;
let requestBody = JSON.parse(lastRequest.requestBody);
let [invite] = requestBody.invites;
expect(
requestBody.invites.length,
'number of invites in request body'
).to.equal(1);
expect(invite.email).to.equal('resend-test@example.com');
// eslint-disable-next-line camelcase
expect(invite.role_id, 'role ID').to.equal('1');
});
beforeEach(function () {
server = new Pretender();
});
}
);
afterEach(function () {
server.shutdown();
});
it('resend hits correct endpoint', function () {
let model = this.subject();
let role;
server.post('/ghost/api/v0.1/invites/', function () {
return [200, {}, '{}'];
});
run(() => {
role = this.store().push({data: {id: 1, type: 'role', attributes: {name: 'Editor'}}});
model.set('email', 'resend-test@example.com');
model.set('role', role);
model.resend();
});
expect(
server.handledRequests.length,
'number of requests'
).to.equal(1);
let [lastRequest] = server.handledRequests;
let requestBody = JSON.parse(lastRequest.requestBody);
let [invite] = requestBody.invites;
expect(
requestBody.invites.length,
'number of invites in request body'
).to.equal(1);
expect(invite.email).to.equal('resend-test@example.com');
// eslint-disable-next-line camelcase
expect(invite.role_id, 'role ID').to.equal('1');
});
});
});

View File

@ -1,67 +1,65 @@
/* jshint expr:true */
import {expect} from 'chai';
import {describeModule, it} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupTest} from 'ember-mocha';
describeModule(
'model:navigation-item',
'Unit: Model: navigation-item',
{
describe('Unit: Model: navigation-item', function() {
setupTest('model:navigation-item', {
// Specify the other units that are required for this test.
needs: []
},
function() {
it('isComplete is true when label and url are filled', function () {
let model = this.subject();
});
model.set('label', 'test');
model.set('url', 'test');
it('isComplete is true when label and url are filled', function () {
let model = this.subject();
expect(model.get('isComplete')).to.be.true;
});
model.set('label', 'test');
model.set('url', 'test');
it('isComplete is false when label is blank', function () {
let model = this.subject();
expect(model.get('isComplete')).to.be.true;
});
model.set('label', '');
model.set('url', 'test');
it('isComplete is false when label is blank', function () {
let model = this.subject();
expect(model.get('isComplete')).to.be.false;
});
model.set('label', '');
model.set('url', 'test');
it('isComplete is false when url is blank', function () {
let model = this.subject();
expect(model.get('isComplete')).to.be.false;
});
model.set('label', 'test');
model.set('url', '');
it('isComplete is false when url is blank', function () {
let model = this.subject();
expect(model.get('isComplete')).to.be.false;
});
model.set('label', 'test');
model.set('url', '');
it('isBlank is true when label and url are blank', function () {
let model = this.subject();
expect(model.get('isComplete')).to.be.false;
});
model.set('label', '');
model.set('url', '');
it('isBlank is true when label and url are blank', function () {
let model = this.subject();
expect(model.get('isBlank')).to.be.true;
});
model.set('label', '');
model.set('url', '');
it('isBlank is false when label is present', function () {
let model = this.subject();
expect(model.get('isBlank')).to.be.true;
});
model.set('label', 'test');
model.set('url', '');
it('isBlank is false when label is present', function () {
let model = this.subject();
expect(model.get('isBlank')).to.be.false;
});
model.set('label', 'test');
model.set('url', '');
it('isBlank is false when url is present', function () {
let model = this.subject();
expect(model.get('isBlank')).to.be.false;
});
model.set('label', '');
model.set('url', 'test');
it('isBlank is false when url is present', function () {
let model = this.subject();
expect(model.get('isBlank')).to.be.false;
});
}
);
model.set('label', '');
model.set('url', 'test');
expect(model.get('isBlank')).to.be.false;
});
});

View File

@ -1,93 +1,87 @@
import run from 'ember-runloop';
import EmberObject from 'ember-object';
import {
describeModel,
it
} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupModelTest} from 'ember-mocha';
describeModel(
'post',
'Unit: Model: post',
{
describe('Unit: Model: post', function () {
setupModelTest('post', {
needs: ['model:user', 'model:tag', 'model:role']
},
});
function () {
it('has a validation type of "post"', function () {
let model = this.subject();
it('has a validation type of "post"', function () {
let model = this.subject();
expect(model.validationType).to.equal('post');
expect(model.validationType).to.equal('post');
});
it('isPublished, isDraft and isScheduled are correct', function () {
let model = this.subject({
status: 'published'
});
it('isPublished, isDraft and isScheduled are correct', function () {
let model = this.subject({
status: 'published'
});
expect(model.get('isPublished')).to.be.ok;
expect(model.get('isDraft')).to.not.be.ok;
expect(model.get('isScheduled')).to.not.be.ok;
expect(model.get('isPublished')).to.be.ok;
expect(model.get('isDraft')).to.not.be.ok;
run(function () {
model.set('status', 'draft');
expect(model.get('isPublished')).to.not.be.ok;
expect(model.get('isDraft')).to.be.ok;
expect(model.get('isScheduled')).to.not.be.ok;
run(function () {
model.set('status', 'draft');
expect(model.get('isPublished')).to.not.be.ok;
expect(model.get('isDraft')).to.be.ok;
expect(model.get('isScheduled')).to.not.be.ok;
});
run(function () {
model.set('status', 'scheduled');
expect(model.get('isScheduled')).to.be.ok;
expect(model.get('isPublished')).to.not.be.ok;
expect(model.get('isDraft')).to.not.be.ok;
});
});
it('isAuthoredByUser is correct', function () {
let model = this.subject({
authorId: 'abcd1234'
});
let user = EmberObject.create({id: 'abcd1234'});
run(function () {
model.set('status', 'scheduled');
expect(model.isAuthoredByUser(user)).to.be.ok;
run(function () {
model.set('authorId', 'wxyz9876');
expect(model.isAuthoredByUser(user)).to.not.be.ok;
});
expect(model.get('isScheduled')).to.be.ok;
expect(model.get('isPublished')).to.not.be.ok;
expect(model.get('isDraft')).to.not.be.ok;
});
});
it('updateTags removes and deletes old tags', function () {
let model = this.subject();
run(this, function () {
let modelTags = model.get('tags');
let tag1 = this.store().createRecord('tag', {id: '1'});
let tag2 = this.store().createRecord('tag', {id: '2'});
let tag3 = this.store().createRecord('tag');
// During testing a record created without an explicit id will get
// an id of 'fixture-n' instead of null
tag3.set('id', null);
modelTags.pushObject(tag1);
modelTags.pushObject(tag2);
modelTags.pushObject(tag3);
expect(model.get('tags.length')).to.equal(3);
model.updateTags();
expect(model.get('tags.length')).to.equal(2);
expect(model.get('tags.firstObject.id')).to.equal('1');
expect(model.get('tags').objectAt(1).get('id')).to.equal('2');
expect(tag1.get('isDeleted')).to.not.be.ok;
expect(tag2.get('isDeleted')).to.not.be.ok;
expect(tag3.get('isDeleted')).to.be.ok;
});
it('isAuthoredByUser is correct', function () {
let model = this.subject({
authorId: 'abcd1234'
});
}
);
let user = EmberObject.create({id: 'abcd1234'});
expect(model.isAuthoredByUser(user)).to.be.ok;
run(function () {
model.set('authorId', 'wxyz9876');
expect(model.isAuthoredByUser(user)).to.not.be.ok;
});
});
it('updateTags removes and deletes old tags', function () {
let model = this.subject();
run(this, function () {
let modelTags = model.get('tags');
let tag1 = this.store().createRecord('tag', {id: '1'});
let tag2 = this.store().createRecord('tag', {id: '2'});
let tag3 = this.store().createRecord('tag');
// During testing a record created without an explicit id will get
// an id of 'fixture-n' instead of null
tag3.set('id', null);
modelTags.pushObject(tag1);
modelTags.pushObject(tag2);
modelTags.pushObject(tag3);
expect(model.get('tags.length')).to.equal(3);
model.updateTags();
expect(model.get('tags.length')).to.equal(2);
expect(model.get('tags.firstObject.id')).to.equal('1');
expect(model.get('tags').objectAt(1).get('id')).to.equal('2');
expect(tag1.get('isDeleted')).to.not.be.ok;
expect(tag2.get('isDeleted')).to.not.be.ok;
expect(tag3.get('isDeleted')).to.be.ok;
});
});
});

View File

@ -1,10 +1,9 @@
import run from 'ember-runloop';
import {
describeModel,
it
} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupModelTest} from 'ember-mocha';
describeModel('role', 'Unit: Model: role', function () {
describe('Unit: Model: role', function () {
setupModelTest('role');
it('provides a lowercase version of the name', function () {
let model = this.subject({
name: 'Author'

View File

@ -1,9 +1,8 @@
import {
describeModel,
it
} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupModelTest} from 'ember-mocha';
describeModel('setting', 'Unit: Model: setting', function () {
describe('Unit: Model: setting', function () {
setupModelTest('setting');
it('has a validation type of "setting"', function () {
let model = this.subject();

View File

@ -1,20 +1,18 @@
/* jshint expr:true */
import {expect} from 'chai';
import {describeModel, it} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupModelTest} from 'ember-mocha';
describeModel(
'subscriber',
'Unit: Model: subscriber',
{
describe('Unit: Model: subscriber', function() {
setupModelTest('subscriber', {
// Specify the other units that are required for this test.
needs: ['model:post']
},
function() {
// Replace this with your real tests.
it('exists', function() {
let model = this.subject();
// var store = this.store();
expect(model).to.be.ok;
});
}
);
});
// Replace this with your real tests.
it('exists', function() {
let model = this.subject();
// var store = this.store();
expect(model).to.be.ok;
});
});

View File

@ -1,9 +1,8 @@
import {
describeModel,
it
} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupModelTest} from 'ember-mocha';
describeModel('tag', 'Unit: Model: tag', function () {
describe('Unit: Model: tag', function () {
setupModelTest('tag');
it('has a validation type of "tag"', function () {
let model = this.subject();

View File

@ -1,114 +1,108 @@
import run from 'ember-runloop';
import {
describeModel,
it
} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupModelTest} from 'ember-mocha';
describeModel(
'user',
'Unit: Model: user',
{
describe('Unit: Model: user', function () {
setupModelTest('user', {
needs: ['model:role', 'serializer:application', 'serializer:user']
},
});
function () {
it('has a validation type of "user"', function () {
let model = this.subject();
it('has a validation type of "user"', function () {
let model = this.subject();
expect(model.get('validationType')).to.equal('user');
expect(model.get('validationType')).to.equal('user');
});
it('active property is correct', function () {
let model = this.subject({
status: 'active'
});
it('active property is correct', function () {
let model = this.subject({
status: 'active'
});
expect(model.get('active')).to.be.ok;
['warn-1', 'warn-2', 'warn-3', 'warn-4', 'locked'].forEach(function (status) {
run(() => {
model.set('status', status);
});
expect(model.get('status')).to.be.ok;
});
expect(model.get('active')).to.be.ok;
['warn-1', 'warn-2', 'warn-3', 'warn-4', 'locked'].forEach(function (status) {
run(() => {
model.set('status', 'inactive');
model.set('status', status);
});
expect(model.get('active')).to.not.be.ok;
run(() => {
model.set('status', 'invited');
});
expect(model.get('active')).to.not.be.ok;
expect(model.get('status')).to.be.ok;
});
it('role property is correct', function () {
let model = this.subject();
run(() => {
let role = this.store().push({data: {id: 1, type: 'role', attributes: {name: 'Author'}}});
model.get('roles').pushObject(role);
});
expect(model.get('role.name')).to.equal('Author');
run(() => {
let role = this.store().push({data: {id: 1, type: 'role', attributes: {name: 'Editor'}}});
model.set('role', role);
});
expect(model.get('role.name')).to.equal('Editor');
run(() => {
model.set('status', 'inactive');
});
expect(model.get('active')).to.not.be.ok;
it('isAuthor property is correct', function () {
let model = this.subject();
run(() => {
let role = this.store().push({data: {id: 1, type: 'role', attributes: {name: 'Author'}}});
model.set('role', role);
});
expect(model.get('isAuthor')).to.be.ok;
expect(model.get('isEditor')).to.not.be.ok;
expect(model.get('isAdmin')).to.not.be.ok;
expect(model.get('isOwner')).to.not.be.ok;
run(() => {
model.set('status', 'invited');
});
expect(model.get('active')).to.not.be.ok;
});
it('isEditor property is correct', function () {
let model = this.subject();
it('role property is correct', function () {
let model = this.subject();
run(() => {
let role = this.store().push({data: {id: 1, type: 'role', attributes: {name: 'Editor'}}});
model.set('role', role);
});
expect(model.get('isEditor')).to.be.ok;
expect(model.get('isAuthor')).to.not.be.ok;
expect(model.get('isAdmin')).to.not.be.ok;
expect(model.get('isOwner')).to.not.be.ok;
run(() => {
let role = this.store().push({data: {id: 1, type: 'role', attributes: {name: 'Author'}}});
model.get('roles').pushObject(role);
});
expect(model.get('role.name')).to.equal('Author');
it('isAdmin property is correct', function () {
let model = this.subject();
run(() => {
let role = this.store().push({data: {id: 1, type: 'role', attributes: {name: 'Administrator'}}});
model.set('role', role);
});
expect(model.get('isAdmin')).to.be.ok;
expect(model.get('isAuthor')).to.not.be.ok;
expect(model.get('isEditor')).to.not.be.ok;
expect(model.get('isOwner')).to.not.be.ok;
run(() => {
let role = this.store().push({data: {id: 1, type: 'role', attributes: {name: 'Editor'}}});
model.set('role', role);
});
expect(model.get('role.name')).to.equal('Editor');
});
it('isOwner property is correct', function () {
let model = this.subject();
it('isAuthor property is correct', function () {
let model = this.subject();
run(() => {
let role = this.store().push({data: {id: 1, type: 'role', attributes: {name: 'Owner'}}});
model.set('role', role);
});
expect(model.get('isOwner')).to.be.ok;
expect(model.get('isAuthor')).to.not.be.ok;
expect(model.get('isAdmin')).to.not.be.ok;
expect(model.get('isEditor')).to.not.be.ok;
run(() => {
let role = this.store().push({data: {id: 1, type: 'role', attributes: {name: 'Author'}}});
model.set('role', role);
});
}
);
expect(model.get('isAuthor')).to.be.ok;
expect(model.get('isEditor')).to.not.be.ok;
expect(model.get('isAdmin')).to.not.be.ok;
expect(model.get('isOwner')).to.not.be.ok;
});
it('isEditor property is correct', function () {
let model = this.subject();
run(() => {
let role = this.store().push({data: {id: 1, type: 'role', attributes: {name: 'Editor'}}});
model.set('role', role);
});
expect(model.get('isEditor')).to.be.ok;
expect(model.get('isAuthor')).to.not.be.ok;
expect(model.get('isAdmin')).to.not.be.ok;
expect(model.get('isOwner')).to.not.be.ok;
});
it('isAdmin property is correct', function () {
let model = this.subject();
run(() => {
let role = this.store().push({data: {id: 1, type: 'role', attributes: {name: 'Administrator'}}});
model.set('role', role);
});
expect(model.get('isAdmin')).to.be.ok;
expect(model.get('isAuthor')).to.not.be.ok;
expect(model.get('isEditor')).to.not.be.ok;
expect(model.get('isOwner')).to.not.be.ok;
});
it('isOwner property is correct', function () {
let model = this.subject();
run(() => {
let role = this.store().push({data: {id: 1, type: 'role', attributes: {name: 'Owner'}}});
model.set('role', role);
});
expect(model.get('isOwner')).to.be.ok;
expect(model.get('isAuthor')).to.not.be.ok;
expect(model.get('isAdmin')).to.not.be.ok;
expect(model.get('isEditor')).to.not.be.ok;
});
});

View File

@ -1,20 +1,15 @@
/* jshint expr:true */
import {expect} from 'chai';
import {
describeModule,
it
} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupTest} from 'ember-mocha';
describeModule(
'route:subscribers',
'Unit: Route: subscribers',
{
describe('Unit: Route: subscribers', function() {
setupTest('route:subscribers', {
needs: ['service:notifications']
},
function() {
it('exists', function() {
let route = this.subject();
expect(route).to.be.ok;
});
}
);
});
it('exists', function() {
let route = this.subject();
expect(route).to.be.ok;
});
});

View File

@ -1,21 +1,16 @@
/* jshint expr:true */
import {expect} from 'chai';
import {
describeModule,
it
} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupTest} from 'ember-mocha';
describeModule(
'route:subscribers/import',
'Unit: Route: subscribers/import',
{
describe('Unit: Route: subscribers/import', function() {
setupTest('route:subscribers/import', {
// Specify the other units that are required for this test.
needs: ['service:notifications']
},
function() {
it('exists', function() {
let route = this.subject();
expect(route).to.be.ok;
});
}
);
});
it('exists', function() {
let route = this.subject();
expect(route).to.be.ok;
});
});

View File

@ -1,20 +1,15 @@
/* jshint expr:true */
import {expect} from 'chai';
import {
describeModule,
it
} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupTest} from 'ember-mocha';
describeModule(
'route:subscribers/new',
'Unit: Route: subscribers/new',
{
describe('Unit: Route: subscribers/new', function() {
setupTest('route:subscribers/new', {
needs: ['service:notifications']
},
function() {
it('exists', function() {
let route = this.subject();
expect(route).to.be.ok;
});
}
);
});
it('exists', function() {
let route = this.subject();
expect(route).to.be.ok;
});
});

View File

@ -1,46 +1,43 @@
import {expect} from 'chai';
import {describeModel, it} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupModelTest} from 'ember-mocha';
import Pretender from 'pretender';
describeModel(
'notification',
'Unit: Serializer: notification',
{
describe('Unit: Serializer: notification', function () {
setupModelTest('notification', {
// Specify the other units that are required for this test.
needs: ['serializer:notification']
},
});
function () {
let server;
let server;
beforeEach(function () {
server = new Pretender();
beforeEach(function () {
server = new Pretender();
});
afterEach(function () {
server.shutdown();
});
it('converts location->key when deserializing', function () {
server.get('/notifications', function () {
let response = {
notifications: [{
id: 1,
dismissible: false,
status: 'alert',
type: 'info',
location: 'test.foo',
message: 'This is a test'
}]
};
return [200, {'Content-Type': 'application/json'}, JSON.stringify(response)];
});
afterEach(function () {
server.shutdown();
return this.store().findAll('notification').then((notifications) => {
expect(notifications.get('length')).to.equal(1);
expect(notifications.get('firstObject.key')).to.equal('test.foo');
});
it('converts location->key when deserializing', function () {
server.get('/notifications', function () {
let response = {
notifications: [{
id: 1,
dismissible: false,
status: 'alert',
type: 'info',
location: 'test.foo',
message: 'This is a test'
}]
};
return [200, {'Content-Type': 'application/json'}, JSON.stringify(response)];
});
return this.store().findAll('notification').then((notifications) => {
expect(notifications.get('length')).to.equal(1);
expect(notifications.get('firstObject.key')).to.equal('test.foo');
});
});
}
);
});
});

View File

@ -1,23 +1,20 @@
/* jshint expr:true */
import {expect} from 'chai';
import {describeModel, it} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupModelTest} from 'ember-mocha';
describeModel(
'post',
'Unit:Serializer: post',
{
describe('Unit:Serializer: post', function() {
setupModelTest('post', {
// Specify the other units that are required for this test.
needs: ['transform:moment-utc', 'transform:json-string', 'model:user', 'model:tag']
},
});
function() {
// Replace this with your real tests.
it('serializes records', function() {
let record = this.subject();
// Replace this with your real tests.
it('serializes records', function() {
let record = this.subject();
let serializedRecord = record.serialize();
let serializedRecord = record.serialize();
expect(serializedRecord).to.be.ok;
});
}
);
expect(serializedRecord).to.be.ok;
});
});

View File

@ -1,23 +1,20 @@
/* jshint expr:true */
import {expect} from 'chai';
import {describeModel, it} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupModelTest} from 'ember-mocha';
describeModel(
'role',
'Unit:Serializer: role',
{
describe('Unit:Serializer: role', function() {
setupModelTest('role', {
// Specify the other units that are required for this test.
needs: ['transform:moment-utc']
},
});
function() {
// Replace this with your real tests.
it('serializes records', function() {
let record = this.subject();
// Replace this with your real tests.
it('serializes records', function() {
let record = this.subject();
let serializedRecord = record.serialize();
let serializedRecord = record.serialize();
expect(serializedRecord).to.be.ok;
});
}
);
expect(serializedRecord).to.be.ok;
});
});

View File

@ -1,11 +1,10 @@
/* jshint expr:true */
import {expect} from 'chai';
import {describeModel, it} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupModelTest} from 'ember-mocha';
describeModel(
'setting',
'Unit:Serializer: setting',
{
describe('Unit:Serializer: setting', function() {
setupModelTest('setting', {
// Specify the other units that are required for this test.
needs: [
'transform:moment-utc',
@ -14,16 +13,14 @@ describeModel(
'transform:navigation-settings',
'transform:slack-settings'
]
},
});
function() {
// Replace this with your real tests.
it('serializes records', function() {
let record = this.subject();
// Replace this with your real tests.
it('serializes records', function() {
let record = this.subject();
let serializedRecord = record.serialize();
let serializedRecord = record.serialize();
expect(serializedRecord).to.be.ok;
});
}
);
expect(serializedRecord).to.be.ok;
});
});

View File

@ -1,23 +1,20 @@
/* jshint expr:true */
import {expect} from 'chai';
import {describeModel, it} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupModelTest} from 'ember-mocha';
describeModel(
'subscriber',
'Unit:Serializer: subscriber',
{
describe('Unit:Serializer: subscriber', function() {
setupModelTest('subscriber', {
// Specify the other units that are required for this test.
needs: ['model:post', 'transform:moment-utc']
},
});
function() {
// Replace this with your real tests.
it('serializes records', function() {
let record = this.subject();
// Replace this with your real tests.
it('serializes records', function() {
let record = this.subject();
let serializedRecord = record.serialize();
let serializedRecord = record.serialize();
expect(serializedRecord).to.be.ok;
});
}
);
expect(serializedRecord).to.be.ok;
});
});

View File

@ -1,23 +1,20 @@
/* jshint expr:true */
import {expect} from 'chai';
import {describeModel, it} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupModelTest} from 'ember-mocha';
describeModel(
'tag',
'Unit:Serializer: tag',
{
describe('Unit:Serializer: tag', function() {
setupModelTest('tag', {
// Specify the other units that are required for this test.
needs: ['transform:moment-utc', 'transform:raw']
},
});
function() {
// Replace this with your real tests.
it('serializes records', function() {
let record = this.subject();
// Replace this with your real tests.
it('serializes records', function() {
let record = this.subject();
let serializedRecord = record.serialize();
let serializedRecord = record.serialize();
expect(serializedRecord).to.be.ok;
});
}
);
expect(serializedRecord).to.be.ok;
});
});

View File

@ -1,11 +1,10 @@
/* jshint expr:true */
import {expect} from 'chai';
import {describeModel, it} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupModelTest} from 'ember-mocha';
describeModel(
'user',
'Unit:Serializer: user',
{
describe('Unit:Serializer: user', function() {
setupModelTest('user', {
// Specify the other units that are required for this test.
needs: [
'transform:moment-utc',
@ -14,16 +13,14 @@ describeModel(
'transform:twitter-url-user',
'model:role'
]
},
});
function() {
// Replace this with your real tests.
it('serializes records', function() {
let record = this.subject();
// Replace this with your real tests.
it('serializes records', function() {
let record = this.subject();
let serializedRecord = record.serialize();
let serializedRecord = record.serialize();
expect(serializedRecord).to.be.ok;
});
}
);
expect(serializedRecord).to.be.ok;
});
});

View File

@ -1,19 +1,13 @@
/* jshint expr:true */
import {expect} from 'chai';
import {
describeModule,
it
} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupTest} from 'ember-mocha';
describeModule(
'service:config',
'Unit: Service: config',
{},
function () {
// Replace this with your real tests.
it('exists', function () {
let service = this.subject();
expect(service).to.be.ok;
});
}
);
describe('Unit: Service: config', function () {
setupTest('service:config', {});
// Replace this with your real tests.
it('exists', function () {
let service = this.subject();
expect(service).to.be.ok;
});
});

View File

@ -1,37 +1,31 @@
/* jshint expr:true */
import {expect} from 'chai';
import {
describeModule,
it
} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupTest} from 'ember-mocha';
import sinon from 'sinon';
describeModule(
'service:event-bus',
'Unit: Service: event-bus',
{},
function() {
it('works', function () {
let service = this.subject();
let eventHandler = sinon.spy();
describe('Unit: Service: event-bus', function() {
setupTest('service:event-bus', {});
it('works', function () {
let service = this.subject();
let eventHandler = sinon.spy();
service.subscribe('test-event', eventHandler);
service.subscribe('test-event', eventHandler);
service.publish('test-event', 'test');
service.publish('test-event', 'test');
service.unsubscribe('test-event', eventHandler);
service.unsubscribe('test-event', eventHandler);
service.publish('test-event', 'test two');
service.publish('test-event', 'test two');
expect(
eventHandler.calledOnce,
'event handler only triggered once'
).to.be.true;
expect(
eventHandler.calledOnce,
'event handler only triggered once'
).to.be.true;
expect(
eventHandler.calledWith('test'),
'event handler was passed correct arguments'
).to.be.true;
});
}
);
expect(
eventHandler.calledWith('test'),
'event handler was passed correct arguments'
).to.be.true;
});
});

View File

@ -5,421 +5,415 @@ import {A as emberA} from 'ember-array/utils';
import EmberObject from 'ember-object';
import sinon from 'sinon';
import {expect} from 'chai';
import {
describeModule,
it
} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupTest} from 'ember-mocha';
import {AjaxError, InvalidError} from 'ember-ajax/errors';
import {ServerUnreachableError} from 'ghost-admin/services/ajax';
describeModule(
'service:notifications',
'Unit: Service: notifications',
{},
function () {
beforeEach(function () {
this.subject().set('content', emberA());
this.subject().set('delayedNotifications', emberA());
describe('Unit: Service: notifications', function () {
setupTest('service:notifications', {});
beforeEach(function () {
this.subject().set('content', emberA());
this.subject().set('delayedNotifications', emberA());
});
it('filters alerts/notifications', function () {
let notifications = this.subject();
// wrapped in run-loop to enure alerts/notifications CPs are updated
run(() => {
notifications.showAlert('Alert');
notifications.showNotification('Notification');
});
it('filters alerts/notifications', function () {
let notifications = this.subject();
expect(notifications.get('alerts.length')).to.equal(1);
expect(notifications.get('alerts.firstObject.message')).to.equal('Alert');
// wrapped in run-loop to enure alerts/notifications CPs are updated
run(() => {
notifications.showAlert('Alert');
notifications.showNotification('Notification');
});
expect(notifications.get('notifications.length')).to.equal(1);
expect(notifications.get('notifications.firstObject.message')).to.equal('Notification');
});
expect(notifications.get('alerts.length')).to.equal(1);
expect(notifications.get('alerts.firstObject.message')).to.equal('Alert');
it('#handleNotification deals with DS.Notification notifications', function () {
let notifications = this.subject();
let notification = EmberObject.create({message: '<h1>Test</h1>', status: 'alert'});
expect(notifications.get('notifications.length')).to.equal(1);
expect(notifications.get('notifications.firstObject.message')).to.equal('Notification');
notification.toJSON = function () {};
notifications.handleNotification(notification);
notification = notifications.get('alerts')[0];
// alerts received from the server should be marked html safe
expect(notification.get('message')).to.have.property('toHTML');
});
it('#handleNotification defaults to notification if no status supplied', function () {
let notifications = this.subject();
notifications.handleNotification({message: 'Test'}, false);
expect(notifications.get('content'))
.to.deep.include({message: 'Test', status: 'notification'});
});
it('#showAlert adds POJO alerts', function () {
let notifications = this.subject();
run(() => {
notifications.showAlert('Test Alert', {type: 'error'});
});
it('#handleNotification deals with DS.Notification notifications', function () {
let notifications = this.subject();
let notification = EmberObject.create({message: '<h1>Test</h1>', status: 'alert'});
expect(notifications.get('alerts'))
.to.deep.include({message: 'Test Alert', status: 'alert', type: 'error', key: undefined});
});
notification.toJSON = function () {};
it('#showAlert adds delayed notifications', function () {
let notifications = this.subject();
run(() => {
notifications.showNotification('Test Alert', {type: 'error', delayed: true});
});
expect(notifications.get('delayedNotifications'))
.to.deep.include({message: 'Test Alert', status: 'notification', type: 'error', key: undefined});
});
// in order to cater for complex keys that are suitable for i18n
// we split on the second period and treat the resulting base as
// the key for duplicate checking
it('#showAlert clears duplicates', function () {
let notifications = this.subject();
run(() => {
notifications.showAlert('Kept');
notifications.showAlert('Duplicate', {key: 'duplicate.key.fail'});
});
expect(notifications.get('alerts.length')).to.equal(2);
run(() => {
notifications.showAlert('Duplicate with new message', {key: 'duplicate.key.success'});
});
expect(notifications.get('alerts.length')).to.equal(2);
expect(notifications.get('alerts.lastObject.message')).to.equal('Duplicate with new message');
});
it('#showNotification adds POJO notifications', function () {
let notifications = this.subject();
run(() => {
notifications.showNotification('Test Notification', {type: 'success'});
});
expect(notifications.get('notifications'))
.to.deep.include({message: 'Test Notification', status: 'notification', type: 'success', key: undefined});
});
it('#showNotification adds delayed notifications', function () {
let notifications = this.subject();
run(() => {
notifications.showNotification('Test Notification', {delayed: true});
});
expect(notifications.get('delayedNotifications'))
.to.deep.include({message: 'Test Notification', status: 'notification', type: undefined, key: undefined});
});
it('#showNotification clears existing notifications', function () {
let notifications = this.subject();
run(() => {
notifications.showNotification('First');
notifications.showNotification('Second');
});
expect(notifications.get('notifications.length')).to.equal(1);
expect(notifications.get('notifications'))
.to.deep.equal([{message: 'Second', status: 'notification', type: undefined, key: undefined}]);
});
it('#showNotification keeps existing notifications if doNotCloseNotifications option passed', function () {
let notifications = this.subject();
run(() => {
notifications.showNotification('First');
notifications.showNotification('Second', {doNotCloseNotifications: true});
});
expect(notifications.get('notifications.length')).to.equal(2);
});
it('#showAPIError handles single json response error', function () {
let notifications = this.subject();
let error = new AjaxError([{message: 'Single error'}]);
run(() => {
notifications.showAPIError(error);
});
let alert = notifications.get('alerts.firstObject');
expect(get(alert, 'message')).to.equal('Single error');
expect(get(alert, 'status')).to.equal('alert');
expect(get(alert, 'type')).to.equal('error');
expect(get(alert, 'key')).to.equal('api-error');
});
it('#showAPIError handles multiple json response errors', function () {
let notifications = this.subject();
let error = new AjaxError([
{title: 'First error', message: 'First error message'},
{title: 'Second error', message: 'Second error message'}
]);
run(() => {
notifications.showAPIError(error);
});
expect(notifications.get('alerts.length')).to.equal(2);
let [alert1, alert2] = notifications.get('alerts');
expect(alert1).to.deep.equal({message: 'First error message', status: 'alert', type: 'error', key: 'api-error.first-error'});
expect(alert2).to.deep.equal({message: 'Second error message', status: 'alert', type: 'error', key: 'api-error.second-error'});
});
it('#showAPIError displays default error text if response has no error/message', function () {
let notifications = this.subject();
let resp = false;
run(() => {
notifications.showAPIError(resp);
});
expect(notifications.get('content').toArray()).to.deep.equal([
{message: 'There was a problem on the server, please try again.', status: 'alert', type: 'error', key: 'api-error'}
]);
notifications.set('content', emberA());
run(() => {
notifications.showAPIError(resp, {defaultErrorText: 'Overridden default'});
});
expect(notifications.get('content').toArray()).to.deep.equal([
{message: 'Overridden default', status: 'alert', type: 'error', key: 'api-error'}
]);
});
it('#showAPIError sets correct key when passed a base key', function () {
let notifications = this.subject();
run(() => {
notifications.showAPIError('Test', {key: 'test.alert'});
});
expect(notifications.get('alerts.firstObject.key')).to.equal('api-error.test.alert');
});
it('#showAPIError sets correct key when not passed a key', function () {
let notifications = this.subject();
run(() => {
notifications.showAPIError('Test');
});
expect(notifications.get('alerts.firstObject.key')).to.equal('api-error');
});
it('#showAPIError parses default ember-ajax errors correctly', function () {
let notifications = this.subject();
let error = new InvalidError();
run(() => {
notifications.showAPIError(error);
});
let notification = notifications.get('alerts.firstObject');
expect(get(notification, 'message')).to.equal('Request was rejected because it was invalid');
expect(get(notification, 'status')).to.equal('alert');
expect(get(notification, 'type')).to.equal('error');
expect(get(notification, 'key')).to.equal('api-error.ajax-error');
});
it('#showAPIError parses custom ember-ajax errors correctly', function () {
let notifications = this.subject();
let error = new ServerUnreachableError();
run(() => {
notifications.showAPIError(error);
});
let notification = notifications.get('alerts.firstObject');
expect(get(notification, 'message')).to.equal('Server was unreachable');
expect(get(notification, 'status')).to.equal('alert');
expect(get(notification, 'type')).to.equal('error');
expect(get(notification, 'key')).to.equal('api-error.ajax-error');
});
it('#displayDelayed moves delayed notifications into content', function () {
let notifications = this.subject();
run(() => {
notifications.showNotification('First', {delayed: true});
notifications.showNotification('Second', {delayed: true});
notifications.showNotification('Third', {delayed: false});
notifications.displayDelayed();
});
expect(notifications.get('notifications')).to.deep.equal([
{message: 'Third', status: 'notification', type: undefined, key: undefined},
{message: 'First', status: 'notification', type: undefined, key: undefined},
{message: 'Second', status: 'notification', type: undefined, key: undefined}
]);
});
it('#closeNotification removes POJO notifications', function () {
let notification = {message: 'Close test', status: 'notification'};
let notifications = this.subject();
run(() => {
notifications.handleNotification(notification);
notification = notifications.get('alerts')[0];
// alerts received from the server should be marked html safe
expect(notification.get('message')).to.have.property('toHTML');
});
it('#handleNotification defaults to notification if no status supplied', function () {
let notifications = this.subject();
expect(notifications.get('notifications'))
.to.include(notification);
notifications.handleNotification({message: 'Test'}, false);
expect(notifications.get('content'))
.to.deep.include({message: 'Test', status: 'notification'});
run(() => {
notifications.closeNotification(notification);
});
it('#showAlert adds POJO alerts', function () {
let notifications = this.subject();
expect(notifications.get('notifications'))
.to.not.include(notification);
});
run(() => {
notifications.showAlert('Test Alert', {type: 'error'});
});
it('#closeNotification removes and deletes DS.Notification records', function () {
let notification = EmberObject.create({message: 'Close test', status: 'alert'});
let notifications = this.subject();
expect(notifications.get('alerts'))
.to.deep.include({message: 'Test Alert', status: 'alert', type: 'error', key: undefined});
});
it('#showAlert adds delayed notifications', function () {
let notifications = this.subject();
run(() => {
notifications.showNotification('Test Alert', {type: 'error', delayed: true});
});
expect(notifications.get('delayedNotifications'))
.to.deep.include({message: 'Test Alert', status: 'notification', type: 'error', key: undefined});
});
// in order to cater for complex keys that are suitable for i18n
// we split on the second period and treat the resulting base as
// the key for duplicate checking
it('#showAlert clears duplicates', function () {
let notifications = this.subject();
run(() => {
notifications.showAlert('Kept');
notifications.showAlert('Duplicate', {key: 'duplicate.key.fail'});
});
expect(notifications.get('alerts.length')).to.equal(2);
run(() => {
notifications.showAlert('Duplicate with new message', {key: 'duplicate.key.success'});
});
expect(notifications.get('alerts.length')).to.equal(2);
expect(notifications.get('alerts.lastObject.message')).to.equal('Duplicate with new message');
});
it('#showNotification adds POJO notifications', function () {
let notifications = this.subject();
run(() => {
notifications.showNotification('Test Notification', {type: 'success'});
});
expect(notifications.get('notifications'))
.to.deep.include({message: 'Test Notification', status: 'notification', type: 'success', key: undefined});
});
it('#showNotification adds delayed notifications', function () {
let notifications = this.subject();
run(() => {
notifications.showNotification('Test Notification', {delayed: true});
});
expect(notifications.get('delayedNotifications'))
.to.deep.include({message: 'Test Notification', status: 'notification', type: undefined, key: undefined});
});
it('#showNotification clears existing notifications', function () {
let notifications = this.subject();
run(() => {
notifications.showNotification('First');
notifications.showNotification('Second');
});
expect(notifications.get('notifications.length')).to.equal(1);
expect(notifications.get('notifications'))
.to.deep.equal([{message: 'Second', status: 'notification', type: undefined, key: undefined}]);
});
it('#showNotification keeps existing notifications if doNotCloseNotifications option passed', function () {
let notifications = this.subject();
run(() => {
notifications.showNotification('First');
notifications.showNotification('Second', {doNotCloseNotifications: true});
});
expect(notifications.get('notifications.length')).to.equal(2);
});
it('#showAPIError handles single json response error', function () {
let notifications = this.subject();
let error = new AjaxError([{message: 'Single error'}]);
run(() => {
notifications.showAPIError(error);
});
let alert = notifications.get('alerts.firstObject');
expect(get(alert, 'message')).to.equal('Single error');
expect(get(alert, 'status')).to.equal('alert');
expect(get(alert, 'type')).to.equal('error');
expect(get(alert, 'key')).to.equal('api-error');
});
it('#showAPIError handles multiple json response errors', function () {
let notifications = this.subject();
let error = new AjaxError([
{title: 'First error', message: 'First error message'},
{title: 'Second error', message: 'Second error message'}
]);
run(() => {
notifications.showAPIError(error);
});
expect(notifications.get('alerts.length')).to.equal(2);
let [alert1, alert2] = notifications.get('alerts');
expect(alert1).to.deep.equal({message: 'First error message', status: 'alert', type: 'error', key: 'api-error.first-error'});
expect(alert2).to.deep.equal({message: 'Second error message', status: 'alert', type: 'error', key: 'api-error.second-error'});
});
it('#showAPIError displays default error text if response has no error/message', function () {
let notifications = this.subject();
let resp = false;
run(() => {
notifications.showAPIError(resp);
});
expect(notifications.get('content').toArray()).to.deep.equal([
{message: 'There was a problem on the server, please try again.', status: 'alert', type: 'error', key: 'api-error'}
]);
notifications.set('content', emberA());
run(() => {
notifications.showAPIError(resp, {defaultErrorText: 'Overridden default'});
});
expect(notifications.get('content').toArray()).to.deep.equal([
{message: 'Overridden default', status: 'alert', type: 'error', key: 'api-error'}
]);
});
it('#showAPIError sets correct key when passed a base key', function () {
let notifications = this.subject();
run(() => {
notifications.showAPIError('Test', {key: 'test.alert'});
});
expect(notifications.get('alerts.firstObject.key')).to.equal('api-error.test.alert');
});
it('#showAPIError sets correct key when not passed a key', function () {
let notifications = this.subject();
run(() => {
notifications.showAPIError('Test');
});
expect(notifications.get('alerts.firstObject.key')).to.equal('api-error');
});
it('#showAPIError parses default ember-ajax errors correctly', function () {
let notifications = this.subject();
let error = new InvalidError();
run(() => {
notifications.showAPIError(error);
});
let notification = notifications.get('alerts.firstObject');
expect(get(notification, 'message')).to.equal('Request was rejected because it was invalid');
expect(get(notification, 'status')).to.equal('alert');
expect(get(notification, 'type')).to.equal('error');
expect(get(notification, 'key')).to.equal('api-error.ajax-error');
});
it('#showAPIError parses custom ember-ajax errors correctly', function () {
let notifications = this.subject();
let error = new ServerUnreachableError();
run(() => {
notifications.showAPIError(error);
});
let notification = notifications.get('alerts.firstObject');
expect(get(notification, 'message')).to.equal('Server was unreachable');
expect(get(notification, 'status')).to.equal('alert');
expect(get(notification, 'type')).to.equal('error');
expect(get(notification, 'key')).to.equal('api-error.ajax-error');
});
it('#displayDelayed moves delayed notifications into content', function () {
let notifications = this.subject();
run(() => {
notifications.showNotification('First', {delayed: true});
notifications.showNotification('Second', {delayed: true});
notifications.showNotification('Third', {delayed: false});
notifications.displayDelayed();
});
expect(notifications.get('notifications')).to.deep.equal([
{message: 'Third', status: 'notification', type: undefined, key: undefined},
{message: 'First', status: 'notification', type: undefined, key: undefined},
{message: 'Second', status: 'notification', type: undefined, key: undefined}
]);
});
it('#closeNotification removes POJO notifications', function () {
let notification = {message: 'Close test', status: 'notification'};
let notifications = this.subject();
run(() => {
notifications.handleNotification(notification);
});
expect(notifications.get('notifications'))
.to.include(notification);
run(() => {
notifications.closeNotification(notification);
});
expect(notifications.get('notifications'))
.to.not.include(notification);
});
it('#closeNotification removes and deletes DS.Notification records', function () {
let notification = EmberObject.create({message: 'Close test', status: 'alert'});
let notifications = this.subject();
notification.toJSON = function () {};
notification.deleteRecord = function () {};
sinon.spy(notification, 'deleteRecord');
notification.save = function () {
return {
finally(callback) {
return callback(notification);
}
};
notification.toJSON = function () {};
notification.deleteRecord = function () {};
sinon.spy(notification, 'deleteRecord');
notification.save = function () {
return {
finally(callback) {
return callback(notification);
}
};
sinon.spy(notification, 'save');
};
sinon.spy(notification, 'save');
run(() => {
notifications.handleNotification(notification);
});
expect(notifications.get('alerts')).to.include(notification);
run(() => {
notifications.closeNotification(notification);
});
expect(notification.deleteRecord.calledOnce).to.be.true;
expect(notification.save.calledOnce).to.be.true;
expect(notifications.get('alerts')).to.not.include(notification);
run(() => {
notifications.handleNotification(notification);
});
it('#closeNotifications only removes notifications', function () {
let notifications = this.subject();
expect(notifications.get('alerts')).to.include(notification);
run(() => {
notifications.showAlert('First alert');
notifications.showNotification('First notification');
notifications.showNotification('Second notification', {doNotCloseNotifications: true});
});
expect(notifications.get('alerts.length'), 'alerts count').to.equal(1);
expect(notifications.get('notifications.length'), 'notifications count').to.equal(2);
run(() => {
notifications.closeNotifications();
});
expect(notifications.get('alerts.length'), 'alerts count').to.equal(1);
expect(notifications.get('notifications.length'), 'notifications count').to.equal(0);
run(() => {
notifications.closeNotification(notification);
});
it('#closeNotifications only closes notifications with specified key', function () {
let notifications = this.subject();
expect(notification.deleteRecord.calledOnce).to.be.true;
expect(notification.save.calledOnce).to.be.true;
run(() => {
notifications.showAlert('First alert');
// using handleNotification as showNotification will auto-prune
// duplicates and keys will be removed if doNotCloseNotifications
// is true
notifications.handleNotification({message: 'First notification', key: 'test.close', status: 'notification'});
notifications.handleNotification({message: 'Second notification', key: 'test.keep', status: 'notification'});
notifications.handleNotification({message: 'Third notification', key: 'test.close', status: 'notification'});
});
expect(notifications.get('alerts')).to.not.include(notification);
});
run(() => {
notifications.closeNotifications('test.close');
});
it('#closeNotifications only removes notifications', function () {
let notifications = this.subject();
expect(notifications.get('notifications.length'), 'notifications count').to.equal(1);
expect(notifications.get('notifications.firstObject.message'), 'notification message').to.equal('Second notification');
expect(notifications.get('alerts.length'), 'alerts count').to.equal(1);
});
it('#clearAll removes everything without deletion', function () {
let notifications = this.subject();
let notificationModel = EmberObject.create({message: 'model'});
notificationModel.toJSON = function () {};
notificationModel.deleteRecord = function () {};
sinon.spy(notificationModel, 'deleteRecord');
notificationModel.save = function () {
return {
finally(callback) {
return callback(notificationModel);
}
};
};
sinon.spy(notificationModel, 'save');
notifications.handleNotification(notificationModel);
notifications.handleNotification({message: 'pojo'});
notifications.clearAll();
expect(notifications.get('content')).to.be.empty;
expect(notificationModel.deleteRecord.called).to.be.false;
expect(notificationModel.save.called).to.be.false;
});
it('#closeAlerts only removes alerts', function () {
let notifications = this.subject();
notifications.showNotification('First notification');
run(() => {
notifications.showAlert('First alert');
notifications.showAlert('Second alert');
run(() => {
notifications.closeAlerts();
});
expect(notifications.get('alerts.length')).to.equal(0);
expect(notifications.get('notifications.length')).to.equal(1);
});
it('#closeAlerts closes only alerts with specified key', function () {
let notifications = this.subject();
notifications.showNotification('First notification');
notifications.showAlert('First alert', {key: 'test.close'});
notifications.showAlert('Second alert', {key: 'test.keep'});
notifications.showAlert('Third alert', {key: 'test.close'});
run(() => {
notifications.closeAlerts('test.close');
});
expect(notifications.get('alerts.length')).to.equal(1);
expect(notifications.get('alerts.firstObject.message')).to.equal('Second alert');
expect(notifications.get('notifications.length')).to.equal(1);
notifications.showNotification('Second notification', {doNotCloseNotifications: true});
});
}
);
expect(notifications.get('alerts.length'), 'alerts count').to.equal(1);
expect(notifications.get('notifications.length'), 'notifications count').to.equal(2);
run(() => {
notifications.closeNotifications();
});
expect(notifications.get('alerts.length'), 'alerts count').to.equal(1);
expect(notifications.get('notifications.length'), 'notifications count').to.equal(0);
});
it('#closeNotifications only closes notifications with specified key', function () {
let notifications = this.subject();
run(() => {
notifications.showAlert('First alert');
// using handleNotification as showNotification will auto-prune
// duplicates and keys will be removed if doNotCloseNotifications
// is true
notifications.handleNotification({message: 'First notification', key: 'test.close', status: 'notification'});
notifications.handleNotification({message: 'Second notification', key: 'test.keep', status: 'notification'});
notifications.handleNotification({message: 'Third notification', key: 'test.close', status: 'notification'});
});
run(() => {
notifications.closeNotifications('test.close');
});
expect(notifications.get('notifications.length'), 'notifications count').to.equal(1);
expect(notifications.get('notifications.firstObject.message'), 'notification message').to.equal('Second notification');
expect(notifications.get('alerts.length'), 'alerts count').to.equal(1);
});
it('#clearAll removes everything without deletion', function () {
let notifications = this.subject();
let notificationModel = EmberObject.create({message: 'model'});
notificationModel.toJSON = function () {};
notificationModel.deleteRecord = function () {};
sinon.spy(notificationModel, 'deleteRecord');
notificationModel.save = function () {
return {
finally(callback) {
return callback(notificationModel);
}
};
};
sinon.spy(notificationModel, 'save');
notifications.handleNotification(notificationModel);
notifications.handleNotification({message: 'pojo'});
notifications.clearAll();
expect(notifications.get('content')).to.be.empty;
expect(notificationModel.deleteRecord.called).to.be.false;
expect(notificationModel.save.called).to.be.false;
});
it('#closeAlerts only removes alerts', function () {
let notifications = this.subject();
notifications.showNotification('First notification');
notifications.showAlert('First alert');
notifications.showAlert('Second alert');
run(() => {
notifications.closeAlerts();
});
expect(notifications.get('alerts.length')).to.equal(0);
expect(notifications.get('notifications.length')).to.equal(1);
});
it('#closeAlerts closes only alerts with specified key', function () {
let notifications = this.subject();
notifications.showNotification('First notification');
notifications.showAlert('First alert', {key: 'test.close'});
notifications.showAlert('Second alert', {key: 'test.keep'});
notifications.showAlert('Third alert', {key: 'test.close'});
run(() => {
notifications.closeAlerts('test.close');
});
expect(notifications.get('alerts.length')).to.equal(1);
expect(notifications.get('alerts.firstObject.message')).to.equal('Second alert');
expect(notifications.get('notifications.length')).to.equal(1);
});
});

View File

@ -1,23 +1,18 @@
/* jshint expr:true */
import {expect} from 'chai';
import {
describeModule,
it
} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupTest} from 'ember-mocha';
describeModule(
'service:upgrade-status',
'UpgradeStatusService',
{
describe('UpgradeStatusService', function() {
setupTest('service:upgrade-status', {
// Specify the other units that are required for this test.
// needs: ['service:foo']
needs: []
},
function() {
// Replace this with your real tests.
it('exists', function() {
let service = this.subject();
expect(service).to.be.ok;
});
}
);
});
// Replace this with your real tests.
it('exists', function() {
let service = this.subject();
expect(service).to.be.ok;
});
});

View File

@ -1,26 +1,23 @@
/* jshint expr:true */
import {expect} from 'chai';
import {describeModule, it} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupTest} from 'ember-mocha';
describeModule(
'transform:facebook-url-user',
'Unit: Transform: facebook-url-user',
{},
function() {
it('deserializes facebook url', function () {
let transform = this.subject();
let serialized = 'testuser';
let result = transform.deserialize(serialized);
describe('Unit: Transform: facebook-url-user', function() {
setupTest('transform:facebook-url-user', {});
it('deserializes facebook url', function () {
let transform = this.subject();
let serialized = 'testuser';
let result = transform.deserialize(serialized);
expect(result).to.equal('https://www.facebook.com/testuser');
});
expect(result).to.equal('https://www.facebook.com/testuser');
});
it('serializes url to facebook username', function () {
let transform = this.subject();
let deserialized = 'https://www.facebook.com/testuser';
let result = transform.serialize(deserialized);
it('serializes url to facebook username', function () {
let transform = this.subject();
let deserialized = 'https://www.facebook.com/testuser';
let result = transform.serialize(deserialized);
expect(result).to.equal('testuser');
});
}
);
expect(result).to.equal('testuser');
});
});

View File

@ -1,26 +1,23 @@
import {expect} from 'chai';
import {describeModule, it} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupTest} from 'ember-mocha';
describeModule(
'transform:json-string',
'Unit: Transform: json-string',
{},
function() {
it('exists', function() {
let transform = this.subject();
expect(transform).to.be.ok;
});
describe('Unit: Transform: json-string', function() {
setupTest('transform:json-string', {});
it('exists', function() {
let transform = this.subject();
expect(transform).to.be.ok;
});
it('serialises an Object to a JSON String', function() {
let transform = this.subject();
let obj = {one: 'one', two: 'two'};
expect(transform.serialize(obj)).to.equal(JSON.stringify(obj));
});
it('serialises an Object to a JSON String', function() {
let transform = this.subject();
let obj = {one: 'one', two: 'two'};
expect(transform.serialize(obj)).to.equal(JSON.stringify(obj));
});
it('deserialises a JSON String to an Object', function() {
let transform = this.subject();
let obj = {one: 'one', two: 'two'};
expect(transform.deserialize(JSON.stringify(obj))).to.deep.equal(obj);
});
}
);
it('deserialises a JSON String to an Object', function() {
let transform = this.subject();
let obj = {one: 'one', two: 'two'};
expect(transform.deserialize(JSON.stringify(obj))).to.deep.equal(obj);
});
});

View File

@ -1,37 +1,34 @@
/* jshint expr:true */
import {expect} from 'chai';
import {describeModule, it} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupTest} from 'ember-mocha';
import {A as emberA} from 'ember-array/utils';
import NavigationItem from 'ghost-admin/models/navigation-item';
describeModule(
'transform:navigation-settings',
'Unit: Transform: navigation-settings',
{},
function() {
it('deserializes navigation json', function () {
let transform = this.subject();
let serialized = '[{"label":"One","url":"/one"},{"label":"Two","url":"/two"}]';
let result = transform.deserialize(serialized);
describe('Unit: Transform: navigation-settings', function() {
setupTest('transform:navigation-settings', {});
it('deserializes navigation json', function () {
let transform = this.subject();
let serialized = '[{"label":"One","url":"/one"},{"label":"Two","url":"/two"}]';
let result = transform.deserialize(serialized);
expect(result.length).to.equal(2);
expect(result[0]).to.be.instanceof(NavigationItem);
expect(result[0].get('label')).to.equal('One');
expect(result[0].get('url')).to.equal('/one');
expect(result[1]).to.be.instanceof(NavigationItem);
expect(result[1].get('label')).to.equal('Two');
expect(result[1].get('url')).to.equal('/two');
});
expect(result.length).to.equal(2);
expect(result[0]).to.be.instanceof(NavigationItem);
expect(result[0].get('label')).to.equal('One');
expect(result[0].get('url')).to.equal('/one');
expect(result[1]).to.be.instanceof(NavigationItem);
expect(result[1].get('label')).to.equal('Two');
expect(result[1].get('url')).to.equal('/two');
});
it('serializes array of NavigationItems', function () {
let transform = this.subject();
let deserialized = emberA([
NavigationItem.create({label: 'One', url: '/one'}),
NavigationItem.create({label: 'Two', url: '/two'})
]);
let result = transform.serialize(deserialized);
it('serializes array of NavigationItems', function () {
let transform = this.subject();
let deserialized = emberA([
NavigationItem.create({label: 'One', url: '/one'}),
NavigationItem.create({label: 'Two', url: '/two'})
]);
let result = transform.serialize(deserialized);
expect(result).to.equal('[{"label":"One","url":"/one"},{"label":"Two","url":"/two"}]');
});
}
);
expect(result).to.equal('[{"label":"One","url":"/one"},{"label":"Two","url":"/two"}]');
});
});

View File

@ -1,32 +1,29 @@
/* jshint expr:true */
import {expect} from 'chai';
import {describeModule, it} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupTest} from 'ember-mocha';
import {A as emberA} from 'ember-array/utils';
import SlackIntegration from 'ghost-admin/models/slack-integration';
describeModule(
'transform:slack-settings',
'Unit: Transform: slack-settings',
{},
function() {
it('deserializes settings json', function () {
let transform = this.subject();
let serialized = '[{"url":"http://myblog.com/blogpost1"}]';
let result = transform.deserialize(serialized);
describe('Unit: Transform: slack-settings', function() {
setupTest('transform:slack-settings', {});
it('deserializes settings json', function () {
let transform = this.subject();
let serialized = '[{"url":"http://myblog.com/blogpost1"}]';
let result = transform.deserialize(serialized);
expect(result.length).to.equal(1);
expect(result[0]).to.be.instanceof(SlackIntegration);
expect(result[0].get('url')).to.equal('http://myblog.com/blogpost1');
});
expect(result.length).to.equal(1);
expect(result[0]).to.be.instanceof(SlackIntegration);
expect(result[0].get('url')).to.equal('http://myblog.com/blogpost1');
});
it('serializes array of Slack settings', function () {
let transform = this.subject();
let deserialized = emberA([
SlackIntegration.create({url: 'http://myblog.com/blogpost1'})
]);
let result = transform.serialize(deserialized);
it('serializes array of Slack settings', function () {
let transform = this.subject();
let deserialized = emberA([
SlackIntegration.create({url: 'http://myblog.com/blogpost1'})
]);
let result = transform.serialize(deserialized);
expect(result).to.equal('[{"url":"http://myblog.com/blogpost1"}]');
});
}
);
expect(result).to.equal('[{"url":"http://myblog.com/blogpost1"}]');
});
});

View File

@ -1,26 +1,23 @@
/* jshint expr:true */
import {expect} from 'chai';
import {describeModule, it} from 'ember-mocha';
import {describe, it} from 'mocha';
import {setupTest} from 'ember-mocha';
describeModule(
'transform:twitter-url-user',
'Unit: Transform: twitter-url-user',
{},
function() {
it('deserializes twitter url', function () {
let transform = this.subject();
let serialized = '@testuser';
let result = transform.deserialize(serialized);
describe('Unit: Transform: twitter-url-user', function() {
setupTest('transform:twitter-url-user', {});
it('deserializes twitter url', function () {
let transform = this.subject();
let serialized = '@testuser';
let result = transform.deserialize(serialized);
expect(result).to.equal('https://twitter.com/testuser');
});
expect(result).to.equal('https://twitter.com/testuser');
});
it('serializes url to twitter username', function () {
let transform = this.subject();
let deserialized = 'https://twitter.com/testuser';
let result = transform.serialize(deserialized);
it('serializes url to twitter username', function () {
let transform = this.subject();
let deserialized = 'https://twitter.com/testuser';
let result = transform.serialize(deserialized);
expect(result).to.equal('@testuser');
});
}
);
expect(result).to.equal('@testuser');
});
});