0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-03-25 02:31:59 -05:00

Migrated notifications tests to Octane patterns

refs e021843e3f

- fixed closing of alerts due to missing `.args` after migrating to glimmer syntax
- updated related tests for glimmer component syntax
This commit is contained in:
Kevin Ansfield 2022-05-25 12:43:02 +01:00
parent e021843e3f
commit 7356bfbcd9
5 changed files with 113 additions and 89 deletions

View file

@ -6,17 +6,16 @@ export default class GhAlert extends Component {
@service notifications;
get typeClass() {
let type = this.args.message.type;
let classes = '';
let typeMapping;
typeMapping = {
const typeMapping = {
success: 'green',
error: 'red',
warn: 'blue',
info: 'blue'
};
const type = this.args.message.type;
let classes = '';
if (typeMapping[type] !== undefined) {
classes += `gh-alert-${typeMapping[type]}`;
}
@ -26,6 +25,6 @@ export default class GhAlert extends Component {
@action
closeNotification() {
this.notifications.closeNotification(this.message);
this.notifications.closeNotification(this.args.message);
}
}

View file

@ -5,8 +5,6 @@ import {inject as service} from '@ember/service';
export default class GhNotification extends Component {
@service notifications;
message = null;
get typeClass() {
const typeMapping = {
error: 'red',

View file

@ -1,17 +1,28 @@
import hbs from 'htmlbars-inline-precompile';
import sinon from 'sinon';
import {click, find, render} from '@ember/test-helpers';
import {click, find, render, settled} from '@ember/test-helpers';
import {describe, it} from 'mocha';
import {expect} from 'chai';
import {setupRenderingTest} from 'ember-mocha';
import {tracked} from '@glimmer/tracking';
class Message {
@tracked message;
@tracked type;
constructor({message, type}) {
this.message = message;
this.type = type;
}
}
describe('Integration: Component: gh-alert', function () {
setupRenderingTest();
it('renders', async function () {
this.set('message', {message: 'Test message', type: 'success'});
this.set('message', new Message({message: 'Test message', type: 'success'}));
await render(hbs`{{gh-alert message=message}}`);
await render(hbs`<GhAlert @message={{this.message}} />`);
let alert = this.element.querySelector('article.gh-alert');
expect(alert).to.exist;
@ -19,29 +30,33 @@ describe('Integration: Component: gh-alert', function () {
});
it('maps message types to CSS classes', async function () {
this.set('message', {message: 'Test message', type: 'success'});
this.set('message', new Message({message: 'Test message', type: 'success'}));
await render(hbs`{{gh-alert message=message}}`);
await render(hbs`<GhAlert @message={{this.message}} />`);
let alert = this.element.querySelector('article.gh-alert');
this.set('message.type', 'success');
this.message.type = 'success';
await settled();
expect(alert, 'success class is green').to.have.class('gh-alert-green');
this.set('message.type', 'error');
this.message.type = 'error';
await settled();
expect(alert, 'error class is red').to.have.class('gh-alert-red');
this.set('message.type', 'warn');
this.message.type = 'warn';
await settled();
expect(alert, 'warn class is yellow').to.have.class('gh-alert-blue');
this.set('message.type', 'info');
this.message.type = 'info';
await settled();
expect(alert, 'info class is blue').to.have.class('gh-alert-blue');
});
it('closes notification through notifications service', async function () {
let message = {message: 'Test close', type: 'success'};
let message = new Message({message: 'Test close', type: 'success'});
this.set('message', message);
await render(hbs`{{gh-alert message=message}}`);
await render(hbs`<GhAlert @message={{this.message}} />`);
expect(find('article.gh-alert')).to.exist;
let notifications = this.owner.lookup('service:notifications');

View file

@ -1,17 +1,28 @@
import hbs from 'htmlbars-inline-precompile';
import sinon from 'sinon';
import {click, find, render} from '@ember/test-helpers';
import {click, find, render, settled} from '@ember/test-helpers';
import {describe, it} from 'mocha';
import {expect} from 'chai';
import {setupRenderingTest} from 'ember-mocha';
import {tracked} from '@glimmer/tracking';
class Message {
@tracked message;
@tracked type;
constructor({message, type}) {
this.message = message;
this.type = type;
}
}
describe('Integration: Component: gh-notification', function () {
setupRenderingTest();
it('renders', async function () {
this.set('message', {message: 'Test message', type: 'success'});
this.set('message', new Message({message: 'Test message', type: 'success'}));
await render(hbs`{{gh-notification message=message}}`);
await render(hbs`<GhNotification @message={{this.message}} />`);
expect(find('article.gh-notification')).to.exist;
@ -21,28 +32,30 @@ describe('Integration: Component: gh-notification', function () {
});
it('maps message types to CSS classes', async function () {
this.set('message', {message: 'Test message', type: 'success'});
this.set('message', new Message({message: 'Test message', type: 'success'}));
await render(hbs`{{gh-notification message=message}}`);
await render(hbs`<GhNotification @message={{this.message}} />`);
let notification = find('.gh-notification');
this.set('message.type', 'error');
this.message.type = 'error';
await settled();
expect(notification, 'success class is red')
.to.have.class('gh-notification-red');
this.set('message.type', 'warn');
this.message.type = 'warn';
await settled();
expect(notification, 'success class is yellow')
.to.have.class('gh-notification-yellow');
});
it('closes notification through notifications service', async function () {
let message = {message: 'Test close', type: 'success'};
let message = new Message({message: 'Test close', type: 'success'});
this.set('message', message);
let notifications = this.owner.lookup('service:notifications');
notifications.closeNotification = sinon.stub();
await render(hbs`{{gh-notification message=message}}`);
await render(hbs`<GhNotification @message={{this.message}} />`);
expect(find('.gh-notification')).to.exist;
await click('[data-test-button="close-notification"]');

View file

@ -5,7 +5,6 @@ import {ServerUnreachableError} from 'ghost-admin/services/ajax';
import {describe, it} from 'mocha';
import {A as emberA} from '@ember/array';
import {expect} from 'chai';
import {get} from '@ember/object';
import {run} from '@ember/runloop';
import {setupTest} from 'ember-mocha';
@ -31,11 +30,11 @@ describe('Unit: Service: notifications', function () {
notifications.showNotification('Notification');
});
expect(notifications.get('alerts.length')).to.equal(1);
expect(notifications.get('alerts.firstObject.message')).to.equal('Alert');
expect(notifications.alerts.length).to.equal(1);
expect(notifications.alerts.firstObject.message).to.equal('Alert');
expect(notifications.get('notifications.length')).to.equal(1);
expect(notifications.get('notifications.firstObject.message')).to.equal('Notification');
expect(notifications.notifications.length).to.equal(1);
expect(notifications.notifications.firstObject.message).to.equal('Notification');
});
it('#handleNotification deals with DS.Notification notifications', function () {
@ -44,10 +43,10 @@ describe('Unit: Service: notifications', function () {
notifications.handleNotification(notification);
notification = notifications.get('alerts')[0];
notification = notifications.alerts[0];
// alerts received from the server should be marked html safe
expect(notification.get('message')).to.have.property('toHTML');
expect(notification.message).to.have.property('toHTML');
});
it('#handleNotification defaults to notification if no status supplied', function () {
@ -55,7 +54,7 @@ describe('Unit: Service: notifications', function () {
notifications.handleNotification({message: 'Test'}, false);
expect(notifications.get('content'))
expect(notifications.content)
.to.deep.include({message: 'Test', status: 'notification'});
});
@ -66,7 +65,7 @@ describe('Unit: Service: notifications', function () {
notifications.showAlert('Test Alert', {type: 'error'});
});
expect(notifications.get('alerts'))
expect(notifications.alerts)
.to.deep.include({message: 'Test Alert', status: 'alert', type: 'error', key: undefined, actions: undefined, description: undefined, icon: undefined});
});
@ -77,7 +76,7 @@ describe('Unit: Service: notifications', function () {
notifications.showNotification('Test Alert', {type: 'error', delayed: true});
});
expect(notifications.get('delayedNotifications'))
expect(notifications.delayedNotifications)
.to.deep.include({message: 'Test Alert', status: 'notification', type: 'error', key: undefined, actions: undefined, description: undefined, icon: undefined});
});
@ -92,14 +91,14 @@ describe('Unit: Service: notifications', function () {
notifications.showAlert('Duplicate', {key: 'duplicate.key.fail'});
});
expect(notifications.get('alerts.length')).to.equal(2);
expect(notifications.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');
expect(notifications.alerts.length).to.equal(2);
expect(notifications.alerts.lastObject.message).to.equal('Duplicate with new message');
});
it('#showAlert clears duplicates using message text', function () {
@ -109,8 +108,8 @@ describe('Unit: Service: notifications', function () {
notifications.showAlert('Duplicate', {key: 'duplicate'});
notifications.showAlert('Duplicate');
expect(notifications.get('alerts.length')).to.equal(2);
expect(notifications.get('alerts.lastObject.key')).to.not.exist;
expect(notifications.alerts.length).to.equal(2);
expect(notifications.alerts.lastObject.key).to.not.exist;
});
it('#showNotification adds POJO notifications', function () {
@ -120,7 +119,7 @@ describe('Unit: Service: notifications', function () {
notifications.showNotification('Test Notification', {type: 'success'});
});
expect(notifications.get('notifications'))
expect(notifications.notifications)
.to.deep.include({message: 'Test Notification', status: 'notification', type: 'success', key: undefined, actions: undefined, description: undefined, icon: undefined});
});
@ -131,7 +130,7 @@ describe('Unit: Service: notifications', function () {
notifications.showNotification('Test Notification', {delayed: true});
});
expect(notifications.get('delayedNotifications'))
expect(notifications.delayedNotifications)
.to.deep.include({message: 'Test Notification', status: 'notification', type: undefined, key: undefined, actions: undefined, description: undefined, icon: undefined});
});
@ -143,11 +142,11 @@ describe('Unit: Service: notifications', function () {
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');
let [alert] = notifications.alerts;
expect(alert.message).to.equal('Single error');
expect(alert.status).to.equal('alert');
expect(alert.type).to.equal('error');
expect(alert.key).to.equal('api-error');
});
it('#showAPIError handles multiple json response errors', function () {
@ -161,8 +160,8 @@ describe('Unit: Service: notifications', function () {
notifications.showAPIError(error);
});
expect(notifications.get('alerts.length')).to.equal(2);
let [alert1, alert2] = notifications.get('alerts');
expect(notifications.alerts.length).to.equal(2);
let [alert1, alert2] = notifications.alerts;
expect(alert1).to.deep.equal({message: 'First error message', status: 'alert', type: 'error', key: 'api-error.first-error', actions: undefined, description: undefined, icon: undefined});
expect(alert2).to.deep.equal({message: 'Second error message', status: 'alert', type: 'error', key: 'api-error.second-error', actions: undefined, description: undefined, icon: undefined});
});
@ -174,7 +173,7 @@ describe('Unit: Service: notifications', function () {
run(() => {
notifications.showAPIError(resp);
});
expect(notifications.get('content').toArray()).to.deep.equal([
expect(notifications.content).to.deep.equal([
{message: 'There was a problem on the server, please try again.', status: 'alert', type: 'error', key: 'api-error', actions: undefined, description: undefined, icon: undefined}
]);
@ -183,7 +182,7 @@ describe('Unit: Service: notifications', function () {
run(() => {
notifications.showAPIError(resp, {defaultErrorText: 'Overridden default'});
});
expect(notifications.get('content').toArray()).to.deep.equal([
expect(notifications.content).to.deep.equal([
{message: 'Overridden default', status: 'alert', type: 'error', key: 'api-error', actions: undefined, description: undefined, icon: undefined}
]);
});
@ -195,7 +194,7 @@ describe('Unit: Service: notifications', function () {
notifications.showAPIError('Test', {key: 'test.alert'});
});
expect(notifications.get('alerts.firstObject.key')).to.equal('api-error.test.alert');
expect(notifications.alerts.firstObject.key).to.equal('api-error.test.alert');
});
it('#showAPIError sets correct key when not passed a key', function () {
@ -205,7 +204,7 @@ describe('Unit: Service: notifications', function () {
notifications.showAPIError('Test');
});
expect(notifications.get('alerts.firstObject.key')).to.equal('api-error');
expect(notifications.alerts.firstObject.key).to.equal('api-error');
});
it('#showAPIError parses default ember-ajax errors correctly', function () {
@ -216,11 +215,11 @@ describe('Unit: Service: notifications', function () {
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');
let notification = notifications.alerts.firstObject;
expect(notification.message).to.equal('Request was rejected because it was invalid');
expect(notification.status).to.equal('alert');
expect(notification.type).to.equal('error');
expect(notification.key).to.equal('api-error');
});
it('#showAPIError parses custom ember-ajax errors correctly', function () {
@ -231,11 +230,11 @@ describe('Unit: Service: notifications', function () {
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');
let notification = notifications.alerts.firstObject;
expect(notification.message).to.equal('Server was unreachable');
expect(notification.status).to.equal('alert');
expect(notification.type).to.equal('error');
expect(notification.key).to.equal('api-error');
});
it('#showAPIError adds error context to message if available', function () {
@ -249,11 +248,11 @@ describe('Unit: Service: notifications', function () {
notifications.showAPIError(error);
});
let alert = notifications.get('alerts.firstObject');
expect(get(alert, 'message')).to.equal('Authorization Error. Please sign in.');
expect(get(alert, 'status')).to.equal('alert');
expect(get(alert, 'type')).to.equal('error');
expect(get(alert, 'key')).to.equal('api-error');
let [alert] = notifications.alerts;
expect(alert.message).to.equal('Authorization Error. Please sign in.');
expect(alert.status).to.equal('alert');
expect(alert.type).to.equal('error');
expect(alert.key).to.equal('api-error');
});
it('#displayDelayed moves delayed notifications into content', function () {
@ -266,7 +265,7 @@ describe('Unit: Service: notifications', function () {
notifications.displayDelayed();
});
expect(notifications.get('notifications')).to.deep.equal([
expect(notifications.notifications).to.deep.equal([
{message: 'Third', status: 'notification', type: undefined, key: undefined, actions: undefined, description: undefined, icon: undefined},
{message: 'First', status: 'notification', type: undefined, key: undefined, actions: undefined, description: undefined, icon: undefined},
{message: 'Second', status: 'notification', type: undefined, key: undefined, actions: undefined, description: undefined, icon: undefined}
@ -281,14 +280,14 @@ describe('Unit: Service: notifications', function () {
notifications.handleNotification(notification);
});
expect(notifications.get('notifications'))
expect(notifications.notifications)
.to.include(notification);
run(() => {
notifications.closeNotification(notification);
});
expect(notifications.get('notifications'))
expect(notifications.notifications)
.to.not.include(notification);
});
@ -311,7 +310,7 @@ describe('Unit: Service: notifications', function () {
notifications.handleNotification(notification);
});
expect(notifications.get('alerts')).to.include(notification);
expect(notifications.alerts).to.include(notification);
run(() => {
notifications.closeNotification(notification);
@ -320,7 +319,7 @@ describe('Unit: Service: notifications', function () {
expect(notification.deleteRecord.calledOnce).to.be.true;
expect(notification.save.calledOnce).to.be.true;
expect(notifications.get('alerts')).to.not.include(notification);
expect(notifications.alerts).to.not.include(notification);
});
it('#closeNotifications only removes notifications', function () {
@ -332,15 +331,15 @@ describe('Unit: Service: notifications', function () {
notifications.showNotification('Second notification');
});
expect(notifications.get('alerts.length'), 'alerts count').to.equal(1);
expect(notifications.get('notifications.length'), 'notifications count').to.equal(2);
expect(notifications.alerts.length, 'alerts count').to.equal(1);
expect(notifications.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);
expect(notifications.alerts.length, 'alerts count').to.equal(1);
expect(notifications.notifications.length, 'notifications count').to.equal(0);
});
it('#closeNotifications only closes notifications with specified key', function () {
@ -358,9 +357,9 @@ describe('Unit: Service: notifications', function () {
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);
expect(notifications.notifications.length, 'notifications count').to.equal(1);
expect(notifications.notifications.firstObject.message, 'notification message').to.equal('Second notification');
expect(notifications.alerts.length, 'alerts count').to.equal(1);
});
it('#clearAll removes everything without deletion', function () {
@ -383,7 +382,7 @@ describe('Unit: Service: notifications', function () {
notifications.clearAll();
expect(notifications.get('content')).to.be.empty;
expect(notifications.content).to.be.empty;
expect(notificationModel.deleteRecord.called).to.be.false;
expect(notificationModel.save.called).to.be.false;
});
@ -399,8 +398,8 @@ describe('Unit: Service: notifications', function () {
notifications.closeAlerts();
});
expect(notifications.get('alerts.length')).to.equal(0);
expect(notifications.get('notifications.length')).to.equal(1);
expect(notifications.alerts.length).to.equal(0);
expect(notifications.notifications.length).to.equal(1);
});
it('#closeAlerts closes only alerts with specified key', function () {
@ -415,8 +414,8 @@ describe('Unit: Service: notifications', function () {
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);
expect(notifications.alerts.length).to.equal(1);
expect(notifications.alerts.firstObject.message).to.equal('Second alert');
expect(notifications.notifications.length).to.equal(1);
});
});