End of tutorial
This commit is contained in:
parent
42aeae609d
commit
6c5dd4f352
38 changed files with 489 additions and 1 deletions
5
app/adapters/application.js
Normal file
5
app/adapters/application.js
Normal file
|
@ -0,0 +1,5 @@
|
|||
import DS from 'ember-data';
|
||||
|
||||
export default DS.JSONAPIAdapter.extend({
|
||||
namespace: 'api'
|
||||
});
|
4
app/components/item-listing.js
Normal file
4
app/components/item-listing.js
Normal file
|
@ -0,0 +1,4 @@
|
|||
import Ember from 'ember';
|
||||
|
||||
export default Ember.Component.extend({
|
||||
});
|
20
app/components/list-filter.js
Normal file
20
app/components/list-filter.js
Normal file
|
@ -0,0 +1,20 @@
|
|||
import Ember from 'ember';
|
||||
|
||||
export default Ember.Component.extend({
|
||||
classNames: ['list-filter'],
|
||||
value: '',
|
||||
|
||||
init() {
|
||||
this._super(...arguments);
|
||||
this.get('filter')('').then((results) => this.set('results', results));
|
||||
},
|
||||
|
||||
actions: {
|
||||
handleFilterEntry() {
|
||||
let filterInputValue = this.get('value');
|
||||
let filterAction = this.get('filter');
|
||||
filterAction(filterInputValue).then((filterResults) => this.set('results', filterResults));
|
||||
}
|
||||
}
|
||||
|
||||
});
|
13
app/controllers/items.js
Normal file
13
app/controllers/items.js
Normal file
|
@ -0,0 +1,13 @@
|
|||
import Ember from 'ember';
|
||||
|
||||
export default Ember.Controller.extend({
|
||||
actions: {
|
||||
filterByName(param) {
|
||||
if (param !== '') {
|
||||
return this.get('store').query('item', { name: param });
|
||||
} else {
|
||||
return this.get('store').findAll('item');
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
3
app/controllers/items/index.js
Normal file
3
app/controllers/items/index.js
Normal file
|
@ -0,0 +1,3 @@
|
|||
import ItemsController from '../items';
|
||||
|
||||
export default ItemsController;
|
11
app/models/item.js
Normal file
11
app/models/item.js
Normal file
|
@ -0,0 +1,11 @@
|
|||
import DS from 'ember-data';
|
||||
|
||||
export default DS.Model.extend({
|
||||
title: DS.attr(),
|
||||
owner: DS.attr(),
|
||||
location: DS.attr(),
|
||||
type: DS.attr(),
|
||||
image: DS.attr(),
|
||||
bedrooms: DS.attr(),
|
||||
description: DS.attr()
|
||||
});
|
|
@ -7,6 +7,10 @@ const Router = Ember.Router.extend({
|
|||
});
|
||||
|
||||
Router.map(function() {
|
||||
this.route('about');
|
||||
this.route('items', function() {
|
||||
this.route('show', {path: '/:item_id'});
|
||||
});
|
||||
});
|
||||
|
||||
export default Router;
|
||||
|
|
4
app/routes/about.js
Normal file
4
app/routes/about.js
Normal file
|
@ -0,0 +1,4 @@
|
|||
import Ember from 'ember';
|
||||
|
||||
export default Ember.Route.extend({
|
||||
});
|
8
app/routes/index.js
Normal file
8
app/routes/index.js
Normal file
|
@ -0,0 +1,8 @@
|
|||
import Ember from 'ember';
|
||||
|
||||
export default Ember.Route.extend({
|
||||
beforeModel() {
|
||||
this._super(...arguments);
|
||||
this.replaceWith('items');
|
||||
}
|
||||
});
|
4
app/routes/items.js
Normal file
4
app/routes/items.js
Normal file
|
@ -0,0 +1,4 @@
|
|||
import Ember from 'ember';
|
||||
|
||||
export default Ember.Route.extend({
|
||||
});
|
7
app/routes/items/index.js
Normal file
7
app/routes/items/index.js
Normal file
|
@ -0,0 +1,7 @@
|
|||
import Ember from 'ember';
|
||||
|
||||
export default Ember.Route.extend({
|
||||
model() {
|
||||
return this.get('store').findAll('item');
|
||||
}
|
||||
});
|
7
app/routes/items/show.js
Normal file
7
app/routes/items/show.js
Normal file
|
@ -0,0 +1,7 @@
|
|||
import Ember from 'ember';
|
||||
|
||||
export default Ember.Route.extend({
|
||||
model(params) {
|
||||
return this.get('store').findRecord('item', params.item_id);
|
||||
}
|
||||
});
|
9
app/templates/about.hbs
Normal file
9
app/templates/about.hbs
Normal file
|
@ -0,0 +1,9 @@
|
|||
<div class="jumbo">
|
||||
<div class="right tomster"></div>
|
||||
<h2>About Super Rentals</h2>
|
||||
<p>
|
||||
The Super Rentals website is a delightful project created to explore Ember.
|
||||
By building a property rental site, we can simultaneously imagine traveling
|
||||
AND building Ember applications.
|
||||
</p>
|
||||
</div>
|
17
app/templates/application.hbs
Normal file
17
app/templates/application.hbs
Normal file
|
@ -0,0 +1,17 @@
|
|||
<div class="container">
|
||||
<div class="menu">
|
||||
{{#link-to 'index'}}
|
||||
<h1 class="left">
|
||||
<em>StockPile</em>
|
||||
</h1>
|
||||
{{/link-to}}
|
||||
<div class="left links">
|
||||
{{#link-to 'about'}}
|
||||
About
|
||||
{{/link-to}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="body">
|
||||
{{outlet}}
|
||||
</div>
|
||||
</div>
|
15
app/templates/components/item-listing.hbs
Normal file
15
app/templates/components/item-listing.hbs
Normal file
|
@ -0,0 +1,15 @@
|
|||
<article class="listing">
|
||||
<h3 class="title name">{{#link-to "items.show" item}}{{item.title}}{{/link-to}}</h3>
|
||||
<div class="detail owner">
|
||||
<span>Owner:</span> {{item.owner}}
|
||||
</div>
|
||||
<div class="detail type">
|
||||
<span>Type:</span> {{item.type}}
|
||||
</div>
|
||||
<div class="detail location">
|
||||
<span>Location:</span> {{item.location}}
|
||||
</div>
|
||||
<div class="detail bedrooms">
|
||||
<span>Number of bedrooms:</span> {{item.bedrooms}}
|
||||
</div>
|
||||
</article>
|
2
app/templates/components/list-filter.hbs
Normal file
2
app/templates/components/list-filter.hbs
Normal file
|
@ -0,0 +1,2 @@
|
|||
{{input value=value key-up=(action 'handleFilterEntry') class="light" placeholder="Filter By Name"}}
|
||||
{{yield results}}
|
1
app/templates/index.hbs
Normal file
1
app/templates/index.hbs
Normal file
|
@ -0,0 +1 @@
|
|||
{{outlet}}
|
1
app/templates/items.hbs
Normal file
1
app/templates/items.hbs
Normal file
|
@ -0,0 +1 @@
|
|||
{{outlet}}
|
10
app/templates/items/index.hbs
Normal file
10
app/templates/items/index.hbs
Normal file
|
@ -0,0 +1,10 @@
|
|||
{{#list-filter
|
||||
filter=(action 'filterByName') as |items| }}
|
||||
|
||||
<ul class="results">
|
||||
{{#each items as |itemUnit|}}
|
||||
<li>{{item-listing item=itemUnit}}</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
{{/list-filter}}
|
||||
{{outlet}}
|
22
app/templates/items/show.hbs
Normal file
22
app/templates/items/show.hbs
Normal file
|
@ -0,0 +1,22 @@
|
|||
<div class="jumbo show-listing">
|
||||
<h2 class="title">{{model.title}}</h2>
|
||||
<div class="right detail-section">
|
||||
<div class="detail owner">
|
||||
<strong>Owner:</strong> {{model.owner}}
|
||||
</div>
|
||||
<div class="detail">
|
||||
<strong>Type:</strong> {{model.type}}
|
||||
</div>
|
||||
<div class="detail">
|
||||
<strong>Location:</strong> {{model.city}}
|
||||
</div>
|
||||
<div class="detail">
|
||||
<strong>Number of bedrooms:</strong> {{model.bedrooms}}
|
||||
</div>
|
||||
<p class="description">{{model.description}}</p>
|
||||
</div>
|
||||
<img src="{{model.image}}" class="rental-pic">
|
||||
</div>
|
||||
|
||||
|
||||
{{outlet}}
|
|
@ -2,6 +2,7 @@
|
|||
"name": "ember-quickstart",
|
||||
"dependencies": {
|
||||
"ember": "~2.9.0",
|
||||
"ember-cli-shims": "0.1.3"
|
||||
"ember-cli-shims": "0.1.3",
|
||||
"bootstrap": "~3.3.5"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,9 @@ var EmberApp = require('ember-cli/lib/broccoli/ember-app');
|
|||
module.exports = function(defaults) {
|
||||
var app = new EmberApp(defaults, {
|
||||
// Add options here
|
||||
'ember-bootstrap': {
|
||||
'importBootstrapTheme': true
|
||||
}
|
||||
});
|
||||
|
||||
// Use `app.import` to add additional libraries to the generated
|
||||
|
|
56
mirage/config.js
Normal file
56
mirage/config.js
Normal file
|
@ -0,0 +1,56 @@
|
|||
export default function() {
|
||||
this.namespace = '/api';
|
||||
|
||||
let items = [{
|
||||
type: 'items',
|
||||
id: 'grand-old-mansion',
|
||||
attributes: {
|
||||
title: 'Grand Old Mansion',
|
||||
owner: 'Veruca Salt',
|
||||
city: 'San Francisco',
|
||||
type: 'Estate',
|
||||
bedrooms: 15,
|
||||
image: 'https://upload.wikimedia.org/wikipedia/commons/c/cb/Crane_estate_(5).jpg',
|
||||
description: "This grand old mansion sits on over 100 acres of rolling hills and dense redwood forests."
|
||||
}
|
||||
}, {
|
||||
type: 'items',
|
||||
id: 'urban-living',
|
||||
attributes: {
|
||||
title: 'Urban Living',
|
||||
owner: 'Mike Teavee',
|
||||
city: 'Seattle',
|
||||
type: 'Condo',
|
||||
bedrooms: 1,
|
||||
image: 'https://upload.wikimedia.org/wikipedia/commons/0/0e/Alfonso_13_Highrise_Tegucigalpa.jpg',
|
||||
description: "A commuters dream. This rental is within walking distance of 2 bus stops and the Metro."
|
||||
}
|
||||
}, {
|
||||
type: 'items',
|
||||
id: 'downtown-charm',
|
||||
attributes: {
|
||||
title: 'Downtown Charm',
|
||||
owner: 'Violet Beauregarde',
|
||||
city: 'Portland',
|
||||
type: 'Apartment',
|
||||
bedrooms: 3,
|
||||
image: 'https://upload.wikimedia.org/wikipedia/commons/f/f7/Wheeldon_Apartment_Building_-_Portland_Oregon.jpg',
|
||||
description: "Convenience is at your doorstep with this charming downtown rental. Great restaurants and active night life are within a few feet."
|
||||
}
|
||||
}];
|
||||
|
||||
this.get('/items', function(db, request) {
|
||||
if(request.queryParams.name !== undefined) {
|
||||
let filteredItems = items.filter(function(i) {
|
||||
return i.attributes.title.toLowerCase().indexOf(request.queryParams.name.toLowerCase()) !== -1;
|
||||
});
|
||||
return { data: filteredItems };
|
||||
} else {
|
||||
return { data: items };
|
||||
}
|
||||
});
|
||||
|
||||
this.get('/items/:id', function (db, request) {
|
||||
return { data: items.find((item) => request.params.id === item.id) };
|
||||
});
|
||||
}
|
11
mirage/scenarios/default.js
Normal file
11
mirage/scenarios/default.js
Normal file
|
@ -0,0 +1,11 @@
|
|||
export default function(/* server */) {
|
||||
|
||||
/*
|
||||
Seed your development database using your factories.
|
||||
This data will not be loaded in your tests.
|
||||
|
||||
Make sure to define a factory for each model you want to create.
|
||||
*/
|
||||
|
||||
// server.createList('post', 10);
|
||||
}
|
4
mirage/serializers/application.js
Normal file
4
mirage/serializers/application.js
Normal file
|
@ -0,0 +1,4 @@
|
|||
import { JSONAPISerializer } from 'ember-cli-mirage';
|
||||
|
||||
export default JSONAPISerializer.extend({
|
||||
});
|
|
@ -21,6 +21,7 @@
|
|||
"devDependencies": {
|
||||
"broccoli-asset-rev": "^2.4.5",
|
||||
"ember-ajax": "^2.4.1",
|
||||
"ember-bootstrap": "0.11.2",
|
||||
"ember-cli": "2.9.1",
|
||||
"ember-cli-app-version": "^2.0.0",
|
||||
"ember-cli-babel": "^5.1.7",
|
||||
|
@ -29,6 +30,7 @@
|
|||
"ember-cli-htmlbars-inline-precompile": "^0.3.3",
|
||||
"ember-cli-inject-live-reload": "^1.4.1",
|
||||
"ember-cli-jshint": "^1.0.4",
|
||||
"ember-cli-mirage": "0.2.4",
|
||||
"ember-cli-qunit": "^3.0.1",
|
||||
"ember-cli-release": "^0.2.9",
|
||||
"ember-cli-sri": "^2.1.0",
|
||||
|
|
47
tests/acceptance/list-items-test.js
Normal file
47
tests/acceptance/list-items-test.js
Normal file
|
@ -0,0 +1,47 @@
|
|||
import { test } from 'qunit';
|
||||
import moduleForAcceptance from 'ember-quickstart/tests/helpers/module-for-acceptance';
|
||||
|
||||
moduleForAcceptance('Acceptance | list items');
|
||||
|
||||
test('visiting /items', function(assert) {
|
||||
visit('/items');
|
||||
andThen(function() {
|
||||
assert.equal(currentURL(), '/items');
|
||||
});
|
||||
});
|
||||
|
||||
test('should link to information about the company.', function (assert) {
|
||||
visit('/items');
|
||||
click('a:contains("About")');
|
||||
andThen(function () {
|
||||
assert.equal(currentURL(), '/about', 'should navigate to about');
|
||||
});
|
||||
});
|
||||
|
||||
test('should list available rentals.', function (assert) {
|
||||
visit('/items');
|
||||
|
||||
andThen(function() {
|
||||
assert.equal(find('.listing').length, 3, 'should see 3 listings');
|
||||
});
|
||||
});
|
||||
|
||||
test('should filter the list of rentals by city.', function (assert) {
|
||||
visit('/items');
|
||||
fillIn('.list-filter input', 'urban');
|
||||
keyEvent('.list-filter input', 'keyup', 69);
|
||||
andThen(function () {
|
||||
assert.equal(find('.listing').length, 1, 'should show 1 listing');
|
||||
assert.equal(find('.listing .name:contains("Urban Living")').length, 1, 'should contain 1 listing with name Urban Living');
|
||||
});
|
||||
});
|
||||
|
||||
test('should show details for a specific rental', function (assert) {
|
||||
visit('/items');
|
||||
click('a:contains("Grand Old Mansion")');
|
||||
andThen(function() {
|
||||
assert.equal(currentURL(), '/items/grand-old-mansion', 'should navigate to show route');
|
||||
assert.equal(find('.show-listing h2').text(), "Grand Old Mansion", 'should list rental title');
|
||||
assert.equal(find('.description').length, 1, 'should list a description of the property');
|
||||
});
|
||||
});
|
21
tests/integration/components/item-listing-test.js
Normal file
21
tests/integration/components/item-listing-test.js
Normal file
|
@ -0,0 +1,21 @@
|
|||
import { moduleForComponent, test } from 'ember-qunit';
|
||||
import hbs from 'htmlbars-inline-precompile';
|
||||
|
||||
moduleForComponent('item-listing', 'Integration | Component | item listing', {
|
||||
integration: true
|
||||
});
|
||||
|
||||
test('it renders', function(assert) {
|
||||
this.render(hbs`{{item-listing}}`);
|
||||
|
||||
assert.equal(this.$().text().trim(), '');
|
||||
|
||||
// Template block usage:
|
||||
this.render(hbs`
|
||||
{{#item-listing}}
|
||||
template block text
|
||||
{{/item-listing}}
|
||||
`);
|
||||
|
||||
assert.equal(this.$().text().trim(), 'template block text');
|
||||
});
|
73
tests/integration/components/list-filter-test.js
Normal file
73
tests/integration/components/list-filter-test.js
Normal file
|
@ -0,0 +1,73 @@
|
|||
import { moduleForComponent, test } from 'ember-qunit';
|
||||
import hbs from 'htmlbars-inline-precompile';
|
||||
import wait from 'ember-test-helpers/wait';
|
||||
import RSVP from 'rsvp';
|
||||
|
||||
moduleForComponent('list-filter', 'Integration | Component | list filter', {
|
||||
integration: true
|
||||
});
|
||||
|
||||
const ITEMS = [{title: 'Grand Old Mansion'}, {title: 'Urban Living'}, {title: 'Downtown Charm'}];
|
||||
const FILTERED_ITEMS = [{title: 'Grand Old Mansion'}];
|
||||
|
||||
test('should initially load all listings', function (assert) {
|
||||
// we want our actions to return promises, since they are potentially fetching data asynchronously
|
||||
this.on('filterByName', (val) => {
|
||||
if (val === '') {
|
||||
return RSVP.resolve(ITEMS);
|
||||
} else {
|
||||
return RSVP.resolve(FILTERED_ITEMS);
|
||||
}
|
||||
});
|
||||
|
||||
// with an integration test, you can set up and use your component in the same way your application
|
||||
// will use it.
|
||||
this.render(hbs`
|
||||
{{#list-filter filter=(action 'filterByName') as |results|}}
|
||||
<ul>
|
||||
{{#each results as |item|}}
|
||||
<li class="name">
|
||||
{{item.title}}
|
||||
</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
{{/list-filter}}
|
||||
`);
|
||||
|
||||
// the wait function will return a promise that will wait for all promises
|
||||
// and xhr requests to resolve before running the contents of the then block.
|
||||
return wait().then(() => {
|
||||
assert.equal(this.$('.name').length, 3);
|
||||
assert.equal(this.$('.name').first().text().trim(), 'Grand Old Mansion');
|
||||
});
|
||||
});
|
||||
|
||||
test('should update with matching listings', function (assert) {
|
||||
this.on('filterByName', (val) => {
|
||||
if (val === '') {
|
||||
return RSVP.resolve(ITEMS);
|
||||
} else {
|
||||
return RSVP.resolve(FILTERED_ITEMS);
|
||||
}
|
||||
});
|
||||
|
||||
this.render(hbs`
|
||||
{{#list-filter filter=(action 'filterByName') as |results|}}
|
||||
<ul>
|
||||
{{#each results as |item|}}
|
||||
<li class="name">
|
||||
{{item.title}}
|
||||
</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
{{/list-filter}}
|
||||
`);
|
||||
|
||||
// The keyup event here should invoke an action that will cause the list to be filtered
|
||||
this.$('.list-filter input').val('Grand').keyup();
|
||||
|
||||
return wait().then(() => {
|
||||
assert.equal(this.$('.name').length, 1);
|
||||
assert.equal(this.$('.name').text().trim(), 'Grand Old Mansion');
|
||||
});
|
||||
});
|
12
tests/unit/adapters/application-test.js
Normal file
12
tests/unit/adapters/application-test.js
Normal file
|
@ -0,0 +1,12 @@
|
|||
import { moduleFor, test } from 'ember-qunit';
|
||||
|
||||
moduleFor('adapter:application', 'Unit | Adapter | application', {
|
||||
// Specify the other units that are required for this test.
|
||||
// needs: ['serializer:foo']
|
||||
});
|
||||
|
||||
// Replace this with your real tests.
|
||||
test('it exists', function(assert) {
|
||||
let adapter = this.subject();
|
||||
assert.ok(adapter);
|
||||
});
|
12
tests/unit/controllers/items-test.js
Normal file
12
tests/unit/controllers/items-test.js
Normal file
|
@ -0,0 +1,12 @@
|
|||
import { moduleFor, test } from 'ember-qunit';
|
||||
|
||||
moduleFor('controller:items', 'Unit | Controller | items', {
|
||||
// Specify the other units that are required for this test.
|
||||
// needs: ['controller:foo']
|
||||
});
|
||||
|
||||
// Replace this with your real tests.
|
||||
test('it exists', function(assert) {
|
||||
let controller = this.subject();
|
||||
assert.ok(controller);
|
||||
});
|
12
tests/unit/controllers/items/index-test.js
Normal file
12
tests/unit/controllers/items/index-test.js
Normal file
|
@ -0,0 +1,12 @@
|
|||
import { moduleFor, test } from 'ember-qunit';
|
||||
|
||||
moduleFor('controller:items/index', 'Unit | Controller | items/index', {
|
||||
// Specify the other units that are required for this test.
|
||||
// needs: ['controller:foo']
|
||||
});
|
||||
|
||||
// Replace this with your real tests.
|
||||
test('it exists', function(assert) {
|
||||
let controller = this.subject();
|
||||
assert.ok(controller);
|
||||
});
|
12
tests/unit/models/item-test.js
Normal file
12
tests/unit/models/item-test.js
Normal file
|
@ -0,0 +1,12 @@
|
|||
import { moduleForModel, test } from 'ember-qunit';
|
||||
|
||||
moduleForModel('item', 'Unit | Model | item', {
|
||||
// Specify the other units that are required for this test.
|
||||
needs: []
|
||||
});
|
||||
|
||||
test('it exists', function(assert) {
|
||||
let model = this.subject();
|
||||
// let store = this.store();
|
||||
assert.ok(!!model);
|
||||
});
|
11
tests/unit/routes/about-test.js
Normal file
11
tests/unit/routes/about-test.js
Normal file
|
@ -0,0 +1,11 @@
|
|||
import { moduleFor, test } from 'ember-qunit';
|
||||
|
||||
moduleFor('route:about', 'Unit | Route | about', {
|
||||
// Specify the other units that are required for this test.
|
||||
// needs: ['controller:foo']
|
||||
});
|
||||
|
||||
test('it exists', function(assert) {
|
||||
let route = this.subject();
|
||||
assert.ok(route);
|
||||
});
|
11
tests/unit/routes/index-test.js
Normal file
11
tests/unit/routes/index-test.js
Normal file
|
@ -0,0 +1,11 @@
|
|||
import { moduleFor, test } from 'ember-qunit';
|
||||
|
||||
moduleFor('route:index', 'Unit | Route | index', {
|
||||
// Specify the other units that are required for this test.
|
||||
// needs: ['controller:foo']
|
||||
});
|
||||
|
||||
test('it exists', function(assert) {
|
||||
let route = this.subject();
|
||||
assert.ok(route);
|
||||
});
|
11
tests/unit/routes/items-test.js
Normal file
11
tests/unit/routes/items-test.js
Normal file
|
@ -0,0 +1,11 @@
|
|||
import { moduleFor, test } from 'ember-qunit';
|
||||
|
||||
moduleFor('route:items', 'Unit | Route | items', {
|
||||
// Specify the other units that are required for this test.
|
||||
// needs: ['controller:foo']
|
||||
});
|
||||
|
||||
test('it exists', function(assert) {
|
||||
let route = this.subject();
|
||||
assert.ok(route);
|
||||
});
|
11
tests/unit/routes/items/index-test.js
Normal file
11
tests/unit/routes/items/index-test.js
Normal file
|
@ -0,0 +1,11 @@
|
|||
import { moduleFor, test } from 'ember-qunit';
|
||||
|
||||
moduleFor('route:items/index', 'Unit | Route | items/index', {
|
||||
// Specify the other units that are required for this test.
|
||||
// needs: ['controller:foo']
|
||||
});
|
||||
|
||||
test('it exists', function(assert) {
|
||||
let route = this.subject();
|
||||
assert.ok(route);
|
||||
});
|
11
tests/unit/routes/items/show-test.js
Normal file
11
tests/unit/routes/items/show-test.js
Normal file
|
@ -0,0 +1,11 @@
|
|||
import { moduleFor, test } from 'ember-qunit';
|
||||
|
||||
moduleFor('route:items/show', 'Unit | Route | items/show', {
|
||||
// Specify the other units that are required for this test.
|
||||
// needs: ['controller:foo']
|
||||
});
|
||||
|
||||
test('it exists', function(assert) {
|
||||
let route = this.subject();
|
||||
assert.ok(route);
|
||||
});
|
Reference in a new issue