Merge pull request #44 from thermokarst/species-refactor

Species refactor
This commit is contained in:
Matthew Dillon 2015-11-04 20:26:09 -07:00
commit 6881d57786
47 changed files with 528 additions and 256 deletions

View file

@ -1,5 +1,6 @@
{
"predef": [
"server",
"document",
"window",
"-Promise",

View file

@ -1,7 +1,5 @@
---
language: node_js
node_js:
- "0.12"
sudo: false
@ -10,7 +8,12 @@ cache:
- node_modules
before_install:
- export PATH=/usr/local/phantomjs-2.0.0/bin:$PATH
- mkdir -p ~/.nvm/versions
- source ~/.nvm/nvm.sh && nvm install 0.12.2
- mkdir travis-phantomjs
- wget https://s3.amazonaws.com/travis-phantomjs/phantomjs-2.0.0-ubuntu-12.04.tar.bz2 -O $PWD/travis-phantomjs/phantomjs-2.0.0-ubuntu-12.04.tar.bz2
- tar -xvf $PWD/travis-phantomjs/phantomjs-2.0.0-ubuntu-12.04.tar.bz2 -C $PWD/travis-phantomjs
- export PATH=$PWD/travis-phantomjs:$PATH
- "npm config set spin false"
- "npm install -g npm@^2"

View file

@ -23,7 +23,7 @@ export default BaseAuthenticator.extend({
return RSVP.resolve(data);
},
invalidate: function(data) {
invalidate: function(/* data */) {
return RSVP.resolve();
},
});

View file

@ -1,5 +1,5 @@
import Ember from 'ember';
import { formatDate } from '../utils/date-helpers';
import formatDate from '../utils/date-helpers';
export default Ember.Helper.helper(function(params) {
let value = params[0],

19
app/mirage/config.js Normal file
View file

@ -0,0 +1,19 @@
export default function() {
// Don't use mirage for development (for now)
this.urlPrefix = 'http://127.0.0.1:8901';
this.namespace = '/api';
this.passthrough();
}
export function testConfig() {
this.urlPrefix = 'https://bactdb-test.herokuapp.com';
this.namespace = '/api/hymenobacter';
this.timing = 0;
this.get('/users/:id');
this.get('/species');
this.post('/species');
this.get('/species/:id');
this.put('/species/:id');
}

View file

@ -0,0 +1,12 @@
import Mirage, { faker } from 'ember-cli-mirage';
export default Mirage.Factory.extend({
speciesName() { return faker.lorem.words().join(' '); },
typeSpecies: faker.random.boolean(),
etymology: faker.lorem.sentences(),
genusName: 'hymenobacter',
strains: [],
totalStrains: 0,
sortOrder: faker.random.number(),
canEdit: faker.random.boolean(),
});

View file

@ -0,0 +1,8 @@
import Mirage, { faker } from 'ember-cli-mirage';
export default Mirage.Factory.extend({
name() { return faker.name.firstName() + ' ' + faker.name.lastName(); },
email: faker.internet.email,
role: 'R',
canEdit: false,
});

View file

@ -0,0 +1,7 @@
export default function(/* server */) {
// Seed your development database using your factories. This
// data will not be loaded in your tests.
// server.createList('contact', 10);
}

View file

@ -0,0 +1,15 @@
import Ember from 'ember';
const { Mixin } = Ember;
export default Mixin.create({
transitionRoute: null,
actions: {
delete: function() {
this.get('model').destroyRecord().then(() => {
this.transitionToRoute(this.get('transitionRoute'));
});
},
},
});

View file

@ -0,0 +1,36 @@
import Ember from 'ember';
const { Mixin , inject: { service } } = Ember;
export default Mixin.create({
currentUser: service('session-account'),
fallbackRouteBefore: null,
fallbackRouteAfter: null,
beforeModel: function(transition) {
this._super(transition);
this.get('currentUser.account').then((user) => {
if (user.get('isReader')) {
this.transitionTo(this.get('fallbackRouteBefore'));
}
});
},
afterModel: function(model) {
if (!model.get('isNew') && !model.get('canEdit')) {
this.transitionTo(this.get('fallbackRouteAfter'), model.get('id'));
}
},
actions: {
willTransition: function(/*transition*/) {
const controller = this.get('controller');
const model = controller.get('model');
if (model.get('isNew')) {
model.destroyRecord();
}
},
},
});

36
app/mixins/save-model.js Normal file
View file

@ -0,0 +1,36 @@
import Ember from 'ember';
import ajaxError from '../utils/ajax-error';
const { Mixin } = Ember;
export default Mixin.create({
fallbackRoute: null,
actions: {
save: function(properties) {
const model = this.get('model');
const fallbackRoute = this.get('fallbackRoute');
model.setProperties(properties);
if (model.get('hasDirtyAttributes')) {
model.save().then((model) => {
this.transitionToRoute(fallbackRoute, model);
}, () => {
ajaxError(model.get('errors'), this.get('flashMessages'));
});
} else {
this.transitionToRoute(fallbackRoute, model);
}
},
cancel: function() {
const model = this.get('model');
model.get('errors').clear();
model.rollbackAttributes();
this.transitionToRoute(this.get('fallbackRoute'), model);
},
},
});

View file

@ -3,7 +3,8 @@ import Ember from 'ember';
export default Ember.Component.extend({
quill: null,
value: null, // passed in
value: null,
update: null,
didInsertElement: function() {
let quill = new Quill(`#${this.get('elementId')} .editor`, {
@ -22,11 +23,10 @@ export default Ember.Component.extend({
quill.on('text-change', (delta, source) => {
if (source === 'user') {
this.set('value', Ember.$(quill.getHTML()).html());
this.attrs['update'](Ember.$(quill.getHTML()).html());
}
});
this.set('quill', quill);
},
});

View file

@ -1,30 +1,9 @@
import Ember from 'ember';
import ajaxError from '../../../../utils/ajax-error';
import SaveModel from '../../../../mixins/save-model';
export default Ember.Controller.extend({
actions: {
save: function() {
let species = this.get('model');
const { Controller } = Ember;
if (species.get('hasDirtyAttributes')) {
species.save().then((species) => {
this.transitionToRoute('protected.species.show', species);
}, () => {
ajaxError(species.get('errors'), this.get('flashMessages'));
});
} else {
this.transitionToRoute('protected.species.show', species);
}
},
cancel: function() {
let species = this.get('model');
species.get('errors').clear();
species.rollbackAttributes();
this.transitionToRoute('protected.species.show', species);
},
},
export default Controller.extend(SaveModel, {
// Required for SaveModel mixin
fallbackRoute: 'protected.species.show',
});

View file

@ -1,28 +1,15 @@
import Ember from 'ember';
import ElevatedAccess from '../../../../mixins/elevated-access';
export default Ember.Route.extend({
currentUser: Ember.inject.service('session-account'),
const { Route } = Ember;
beforeModel: function(transition) {
this._super(transition);
this.get('currentUser.account').then((user) => {
if (user.get('isReader')) {
this.transitionTo('protected.species.index');
}
});
},
export default Route.extend(ElevatedAccess, {
// Required for ElevatedAccess mixin
fallbackRouteBefore: 'protected.species.index',
fallbackRouteAfter: 'protected.species.show',
afterModel: function(species) {
if (!species.get('canEdit')) {
this.transitionTo('species.show', species.get('id'));
}
},
setupController: function(controller, model) {
controller.set('model', model);
this.get('currentUser.account').then((user) => {
controller.set('metaData', user.get('metaData'));
});
model: function(params) {
return this.store.findRecord('species', params.species_id);
},
});

View file

@ -1,7 +1,6 @@
{{
protected/species/species-form
species=model
metaData=metaData
save="save"
cancel="cancel"
on-save=(action "save")
on-cancel=(action "cancel")
}}

View file

@ -1,6 +0,0 @@
import Ember from 'ember';
export default Ember.Controller.extend({
sortParams: ['speciesName', 'strainCount'],
sortedSpecies: Ember.computed.sort('model', 'sortParams'),
});

View file

@ -1,17 +1,10 @@
import Ember from 'ember';
export default Ember.Route.extend({
currentUser: Ember.inject.service('session-account'),
const { Route } = Ember;
export default Route.extend({
model: function() {
return this.store.findAll('species');
},
setupController: function(controller, model) {
controller.set('model', model);
this.get('currentUser.account').then((user) => {
controller.set('metaData', user.get('metaData'));
});
},
});

View file

@ -0,0 +1,20 @@
import Ember from 'ember';
const { Component, inject: { service }} = Ember;
export default Component.extend({
currentUser: service('session-account'),
metaData: null,
species: null,
setupMetaDataOnInit: Ember.on('init', function() {
this.get('currentUser.account').then((user) => {
this.set('metaData', user.get('metaData'));
});
}),
sortParams: ['speciesName', 'strainCount'],
sortedSpecies: Ember.computed.sort('species', 'sortParams'),
});

View file

@ -0,0 +1,33 @@
<h3 id="total-species">Total species: {{species.length}}</h3>
{{add-button label="Add Species" link="protected.species.new" canAdd=metaData.canAdd}}
<table class="flakes-table">
<thead>
<tr>
<th>Name</th>
<th>Strains</th>
</tr>
</thead>
<tbody>
{{#each sortedSpecies as |species|}}
<tr>
<td>
<em>
{{#link-to 'protected.species.show' species}}
{{species.speciesName}}
{{/link-to}}
</em>
</td>
<td>
{{#each species.strains as |strain index|}}
{{if index ","}}
{{#link-to 'protected.strains.show' strain.id}}
{{{strain.strainNameMU}}}
{{/link-to}}
{{/each}}
</td>
</tr>
{{/each}}
</tbody>
</table>

View file

@ -1,34 +1,6 @@
<h2>{{genus-name}} Species</h2>
<h3>Total species: {{model.length}}</h3>
{{add-button label="Add Species" link="protected.species.new" canAdd=metaData.canAdd}}
<table class="flakes-table">
<thead>
<tr>
<th>Name</th>
<th>Strains</th>
</tr>
</thead>
<tbody>
{{#each sortedSpecies as |species|}}
<tr>
<td>
<em>
{{#link-to 'protected.species.show' species}}
{{species.speciesName}}
{{/link-to}}
</em>
</td>
<td>
{{#each species.strains as |strain index|}}
{{if index ","}}
{{#link-to 'protected.strains.show' strain.id}}
{{{strain.strainNameMU}}}
{{/link-to}}
{{/each}}
</td>
</tr>
{{/each}}
</tbody>
</table>
{{
protected/species/index/species-table
species=model
}}

View file

@ -1,29 +1,9 @@
import Ember from 'ember';
import ajaxError from '../../../../utils/ajax-error';
import SaveModel from '../../../../mixins/save-model';
export default Ember.Controller.extend({
actions: {
save: function() {
let species = this.get('model');
const { Controller } = Ember;
if (species.get('hasDirtyAttributes')) {
species.save().then((species) => {
this.transitionToRoute('protected.species.show', species.get('id'));
}, () => {
ajaxError(species.get('errors'), this.get('flashMessages'));
});
} else {
species.destroyRecord().then(() => {
this.transitionToRoute('protected.species.index');
});
}
},
cancel: function() {
this.get('model').destroyRecord().then(() => {
this.transitionToRoute('protected.species.index');
});
},
},
export default Controller.extend(SaveModel, {
// Required for SaveModel mixin
fallbackRoute: 'protected.species.show',
});

View file

@ -1,30 +1,14 @@
import Ember from 'ember';
import ElevatedAccess from '../../../../mixins/elevated-access';
export default Ember.Route.extend({
currentUser: Ember.inject.service('session-account'),
const { Route } = Ember;
beforeModel: function(transition) {
this._super(transition);
this.get('currentUser.account').then((user) => {
if (user.get('isReader')) {
this.transitionTo('protected.species.index');
}
});
},
export default Route.extend(ElevatedAccess, {
// Required for ElevatedAccess mixin
fallbackRouteBefore: 'protected.species.index',
fallbackRouteAfter: 'protected.species.show',
model: function() {
return this.store.createRecord('species');
},
actions: {
willTransition: function(/*transition*/) {
const controller = this.get('controller');
const species = controller.get('model');
if (species.get('isNew')) {
species.destroyRecord();
}
},
},
});

View file

@ -1,6 +1,6 @@
{{
protected/species/species-form
species=model
save="save"
cancel="cancel"
on-save=(action "save")
on-cancel=(action "cancel")
}}

View file

@ -1,12 +1,9 @@
import Ember from 'ember';
import DeleteModel from '../../../../mixins/delete-model';
export default Ember.Controller.extend({
actions: {
delete: function() {
this.get('model').destroyRecord().then(() => {
this.transitionToRoute('protected.species.index');
});
},
},
const { Controller } = Ember;
export default Controller.extend(DeleteModel, {
// Required for DeleteModel mixin
transitionRoute: 'protected.species.index',
});

View file

@ -1,8 +1,10 @@
import Ember from 'ember';
export default Ember.Route.extend({
const { Route } = Ember;
export default Route.extend({
model: function(params) {
return this.store.findRecord('species', params.species_id, { reload: true });
return this.store.findRecord('species', params.species_id);
},
});

View file

@ -0,0 +1,14 @@
import Ember from 'ember';
const { Component } = Ember;
export default Component.extend({
species: null,
"on-delete": null,
actions: {
deleteSpecies: function() {
return this.attrs['on-delete']();
},
},
});

View file

@ -0,0 +1,62 @@
<div class="grid-1">
<div class="span-1">
<fieldset class="flakes-information-box">
<legend>
Species <em>{{species.speciesName}}</em>
</legend>
{{! ROW 1 }}
<div class="grid-2 gutter-20">
<dl class="span-1">
<dt>Strains</dt>
<dd>
<ul>
{{#each species.strains as |strain index|}}
<li>
{{#link-to 'protected.strains.show' strain.id}}
{{{strain.strainNameMU}}}
{{/link-to}}
</li>
{{/each}}
</ul>
</dd>
</dl>
<dl class="span-1">
<dt>Type Species?</dt>
<dd>
{{if species.typeSpecies 'Yes' 'No'}}
</dd>
</dl>
</div>
{{! ROW 2 }}
<div class="grid-1 gutter-20">
<dl class="span-1">
<dt>Etymology</dt>
<dd>
{{{species.etymology}}}
</dd>
</dl>
</div>
{{! ROW 3 }}
<div class="grid-2 gutter-20">
<dl class="span-1">
<dt>Record Created</dt>
<dd>{{null-time species.createdAt 'LL'}}</dd>
</dl>
<dl class="span-1">
<dt>Record Updated</dt>
<dd>{{null-time species.updatedAt 'LL'}}</dd>
</dl>
</div>
</fieldset>
</div>
</div>
{{#if species.canEdit}}
<br>
{{#link-to 'protected.species.edit' species class="button-gray smaller"}}
Edit
{{/link-to}}
{{delete-button delete=(action 'deleteSpecies')}}
{{/if}}

View file

@ -1,62 +1,5 @@
<div class="grid-1">
<div class="span-1">
<fieldset class="flakes-information-box">
<legend>
Species <em>{{model.speciesName}}</em>
</legend>
{{! ROW 1 }}
<div class="grid-2 gutter-20">
<dl class="span-1">
<dt>Strains</dt>
<dd>
<ul>
{{#each model.strains as |strain index|}}
<li>
{{#link-to 'protected.strains.show' strain.id}}
{{{strain.strainNameMU}}}
{{/link-to}}
</li>
{{/each}}
</ul>
</dd>
</dl>
<dl class="span-1">
<dt>Type Species?</dt>
<dd>
{{if model.typeSpecies 'Yes' 'No'}}
</dd>
</dl>
</div>
{{! ROW 2 }}
<div class="grid-1 gutter-20">
<dl class="span-1">
<dt>Etymology</dt>
<dd>
{{{model.etymology}}}
</dd>
</dl>
</div>
{{! ROW 3 }}
<div class="grid-2 gutter-20">
<dl class="span-1">
<dt>Record Created</dt>
<dd>{{null-time model.createdAt 'LL'}}</dd>
</dl>
<dl class="span-1">
<dt>Record Updated</dt>
<dd>{{null-time model.updatedAt 'LL'}}</dd>
</dl>
</div>
</fieldset>
</div>
</div>
{{#if model.canEdit}}
<br>
{{#link-to 'protected.species.edit' model class="button-gray smaller"}}
Edit
{{/link-to}}
{{delete-button delete=(action 'delete')}}
{{/if}}
{{
protected/species/show/species-card
species=model
on-delete=(action 'delete')
}}

View file

@ -1,13 +1,71 @@
import Ember from 'ember';
export default Ember.Component.extend({
const { Component, inject: { service } } = Ember;
export default Component.extend({
currentUser: service('session-account'),
// Read-only attributes
species: null,
isNew: null,
isDirty: false,
// Actions
"on-save": null,
"on-cancel": null,
"on-update": null,
// Property mapping
propertiesList: ['speciesName', 'typeSpecies', 'strains', 'etymology'],
speciesName: null,
typeSpecies: null,
strains: null,
etymology: null,
resetOnInit: Ember.on('init', function() {
this.get('propertiesList').forEach((field) => {
const valueInSpecies = this.get('species').get(field);
this.set(field, valueInSpecies);
});
// Read-only attributes
this.set('isNew', this.get('species.isNew'));
}),
setupMetaDataOnInit: Ember.on('init', function() {
this.get('currentUser.account').then((user) => {
this.set('metaData', user.get('metaData'));
});
}),
updateField: function(property, value) {
this.set(property, value);
// Manually compare against passed in value
if (this.get('species').get(property) !== value) {
this.set('isDirty', true);
} else {
this.set('isDirty', false);
}
},
actions: {
save: function() {
this.sendAction('save');
return this.attrs['on-save'](this.getProperties(this.get('propertiesList')));
},
cancel: function() {
this.sendAction('cancel');
return this.attrs['on-cancel']();
},
speciesNameDidChange: function(value) {
this.updateField('speciesName', value);
},
typeSpeciesDidChange: function() {
this.updateField('typeSpecies', !this.get('typeSpecies'));
},
etymologyDidChange: function(value) {
this.updateField('etymology', value);
},
},
}
});

View file

@ -1,21 +1,22 @@
<form class="grid-form" {{action 'save' on='submit'}}>
<fieldset>
<legend><em>{{species.speciesName}}</em></legend>
<legend><em>{{speciesName}}</em></legend>
<div data-row-span="2">
<div data-field-span="1">
<label>Species Name</label>
{{input value=species.speciesName}}
{{one-way-input type="text" class="species-name" value=speciesName update=(action "speciesNameDidChange")}}
</div>
<div data-field-span="1">
<label>Type Species?</label>
{{input type="checkbox" checked=species.typeSpecies}} {{if species.typeSpecies 'Yes' 'No'}}
<input type="checkbox" checked={{typeSpecies}} value="{{typeSpecies}}" onchange={{action "typeSpeciesDidChange"}}>
{{if typeSpecies 'Yes' 'No'}}
</div>
</div>
{{#unless species.isNew}}
{{#unless isNew}}
<div data-row-span="1">
<div data-field-span="1">
<label>Strains</label>
{{#each species.strains as |strain index|}}
{{#each strains as |strain index|}}
{{if index ","}}
{{#link-to 'protected.strains.show' strain.id}}
{{{strain.strainNameMU}}}
@ -29,7 +30,7 @@
<div data-row-span="1">
<div data-field-span="1">
<label>Etymology</label>
{{text-editor value=species.etymology}}
{{text-editor value=etymology update=(action "etymologyDidChange")}}
</div>
</div>
</fieldset>
@ -37,8 +38,8 @@
<a class="button-red smaller" {{action 'cancel'}}>
Cancel
</a>
{{#if species.hasDirtyAttributes}}
<button type="submit" class="button-green smaller">
{{# if isDirty}}
<button type="submit" class="button-green smaller save-species">
Save
</button>
{{/if}}

View file

@ -9,5 +9,13 @@ export default Ember.Component.extend({
cancel: function() {
this.sendAction('cancel');
},
}
isolatedFromDidChange: function(value) {
this.set('strain.isolatedFrom', value);
},
notesDidChange: function(value) {
this.set('strain.notes', value);
},
},
});

View file

@ -25,7 +25,7 @@
<div data-row-span="2">
<div data-field-span="2">
<label>Isolated From</label>
{{text-editor value=strain.isolatedFrom}}
{{text-editor value=strain.isolatedFrom update=(action "isolatedFromDidChange")}}
</div>
</div>
<div data-row-span="3">
@ -45,7 +45,7 @@
<div data-row-span="2">
<div data-field-span="2">
<label>Notes</label>
{{text-editor value=strain.notes}}
{{text-editor value=strain.notes update=(action "notesDidChange")}}
</div>
</div>
</fieldset>

View file

@ -12,7 +12,7 @@ export default Ember.Route.extend(UnauthenticatedRouteMixin, {
this.get('session').authenticate('authenticator:jwt-resolved', token).then(() => {
this.get('currentUser.account').then((account) => {
this.transitionTo('protected.users.changepassword', account.get('id'));
})
});
});
},

View file

@ -1,7 +1,3 @@
function formatDate(date, format) {
export default function formatDate(date, format) {
return window.moment(date).format(format);
}
export {
formatDate
};

View file

@ -4,6 +4,6 @@ export default function parseBase64(token) {
tokenData = atob(token.split('.')[1]);
return JSON.parse(tokenData);
} catch (e) {
return tokenData;
return token;
}
}

View file

@ -18,6 +18,9 @@
"antiscroll": "git://github.com/azirbel/antiscroll.git#90391fb371c7be769bc32e7287c5271981428356",
"jquery-mousewheel": "~3.1.4",
"jquery-ui": "~1.11.4",
"quill": "~0.19.14"
"quill": "~0.19.14",
"pretender": "~0.10.1",
"lodash": "~3.7.0",
"Faker": "~3.0.0"
}
}

View file

@ -36,6 +36,7 @@ module.exports = function(environment) {
apiURL = 'https://bactdb-test.herokuapp.com';
ENV.APP.LOG_ACTIVE_GENERATION = false;
ENV.APP.LOG_VIEW_LOOKUPS = false;
ENV.locationType = 'none';
}
if (environment === 'production') {

View file

@ -30,14 +30,16 @@
"ember-cli-htmlbars-inline-precompile": "^0.2.0",
"ember-cli-ic-ajax": "0.2.1",
"ember-cli-inject-live-reload": "^1.3.1",
"ember-cli-mirage": "0.1.11",
"ember-cli-qunit": "^1.0.0",
"ember-simple-auth": "1.0.0",
"ember-cli-release": "0.2.3",
"ember-cli-sri": "^1.0.3",
"ember-cli-uglify": "^1.2.0",
"ember-data": "1.13.13",
"ember-disable-proxy-controllers": "^1.0.0",
"ember-export-application-global": "^1.0.3",
"ember-select-2": "1.3.0"
"ember-one-way-input": "0.1.3",
"ember-select-2": "1.3.0",
"ember-simple-auth": "1.0.0"
}
}

View file

@ -1,5 +1,6 @@
{
"predef": [
"server",
"document",
"window",
"location",

View file

@ -0,0 +1,70 @@
import Ember from 'ember';
import { module, test } from 'qunit';
import startApp from '../helpers/start-app';
import { authenticateSession } from '../helpers/ember-simple-auth';
module('Acceptance | species', {
beforeEach: function() {
this.application = startApp();
authenticateSession(this.application, {
access_token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJiYWN0ZGIiLCJzdWIiOiIxIiwiZXhwIjoxNDQ2NTAyMjI2LCJpYXQiOjE0NDY0OTg2MjZ9.vIjKHAsp2TkCV505EbtCo2xQT-2oQkB-Nv5y0b6E7Mg"
});
server.create('users', { role: 'A', canEdit: true });
},
afterEach: function() {
Ember.run(this.application, 'destroy');
}
});
test('visiting /species', function(assert) {
const species = server.createList('species', 20);
visit('/species');
andThen(function() {
assert.equal(currentURL(), '/species');
assert.equal(find(".flakes-table > tbody > tr").length, species.length);
assert.equal(find("#total-species").text(), "Total species: 20");
});
});
test('visiting /species/:id', function(assert) {
const species = server.create('species');
visit(`/species/${species.id}`);
andThen(function() {
assert.equal(currentURL(), `/species/${species.id}`);
assert.equal(find(".flakes-information-box > legend > em").text().trim(), species.speciesName);
});
});
test('editing /species/:id/edit', function(assert) {
const species = server.create('species', { 'canEdit': true });
visit(`/species/${species.id}/edit`);
andThen(function() {
assert.equal(currentURL(), `/species/${species.id}/edit`);
fillIn('.species-name', 'Revised Species Name');
click('.save-species');
andThen(function() {
assert.equal(currentURL(), `/species/${species.id}`);
assert.equal(find(".flakes-information-box > legend > em").text().trim(), 'Revised Species Name');
});
});
});
test('creating /species/new', function(assert) {
visit(`/species/new`);
andThen(function() {
assert.equal(currentURL(), `/species/new`);
fillIn('.species-name', 'New Species Name');
click('.save-species');
andThen(function() {
assert.equal(find(".flakes-information-box > legend > em").text().trim(), 'New Species Name');
});
});
});

View file

@ -1,5 +1,5 @@
import resolver from './helpers/resolver';
import flashMessageHelper from './helpers/flash-message';
// import flashMessageHelper from './helpers/flash-message';
import {
setResolver

View file

@ -0,0 +1,12 @@
import Ember from 'ember';
import DeleteModelMixin from '../../../mixins/delete-model';
import { module, test } from 'qunit';
module('Unit | Mixin | delete model');
// Replace this with your real tests.
test('it works', function(assert) {
var DeleteModelObject = Ember.Object.extend(DeleteModelMixin);
var subject = DeleteModelObject.create();
assert.ok(subject);
});

View file

@ -0,0 +1,12 @@
import Ember from 'ember';
import ElevatedAccessMixin from '../../../mixins/elevated-access';
import { module, test } from 'qunit';
module('Unit | Mixin | elevated access');
// Replace this with your real tests.
test('it works', function(assert) {
var ElevatedAccessObject = Ember.Object.extend(ElevatedAccessMixin);
var subject = ElevatedAccessObject.create();
assert.ok(subject);
});

View file

@ -0,0 +1,12 @@
import Ember from 'ember';
import SaveModelMixin from '../../../mixins/save-model';
import { module, test } from 'qunit';
module('Unit | Mixin | save model');
// Replace this with your real tests.
test('it works', function(assert) {
var SaveModelObject = Ember.Object.extend(SaveModelMixin);
var subject = SaveModelObject.create();
assert.ok(subject);
});

View file

@ -5,7 +5,7 @@ import {
moduleForModel('measurement', {
// Specify the other units that are required for this test.
needs: ['model:strain']
needs: ['model:strain', 'model:characteristic']
});
test('it exists', function(assert) {

View file

@ -5,7 +5,7 @@ import {
moduleForModel('strain', {
// Specify the other units that are required for this test.
needs: ['model:measurement']
needs: ['model:measurement', 'model:characteristic', 'model:species']
});
test('it exists', function(assert) {

View file

@ -1,10 +1,10 @@
import parseBase64 from '../../../utils/parse-base64';
import { module, test } from 'qunit';
module('Unit | Utility | parse base64');
module('parseBase64');
// Replace this with your real tests.
test('it works', function(assert) {
var result = parseBase64();
var result = parseBase64('123');
assert.ok(result);
});