Skip to content

Commit

Permalink
Add a few targeted tests
Browse files Browse the repository at this point in the history
This ensures `{{this.model}}` and the implicit `{{model}}` contunue
to be tested, to prevent any future regressions. It also tests the
behavior described in the RFC where `this.model` and `@model` could
diverge.
  • Loading branch information
chancancode committed Sep 3, 2019
1 parent 4e368ec commit eeac160
Show file tree
Hide file tree
Showing 4 changed files with 292 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import { ENV } from '@ember/-internals/environment';
import Controller from '@ember/controller';
import { Route } from '@ember/-internals/routing';
import { Component } from '@ember/-internals/glimmer';
import { set, tracked } from '@ember/-internals/metal';
import { runTask } from '../../../../../../internal-test-helpers/lib/run';

moduleFor(
'Application test: rendering',
Expand Down Expand Up @@ -38,7 +40,7 @@ moduleFor(
});
}

['@feature(!EMBER_ROUTING_MODEL_ARG) it can access the model provided by the route']() {
['@feature(EMBER_ROUTING_MODEL_ARG) it can access the model provided by the route via @model']() {
this.add(
'route:application',
Route.extend({
Expand All @@ -52,7 +54,7 @@ moduleFor(
'application',
strip`
<ul>
{{#each this.model as |item|}}
{{#each @model as |item|}}
<li>{{item}}</li>
{{/each}}
</ul>
Expand Down Expand Up @@ -96,7 +98,7 @@ moduleFor(
});
}

['@feature(EMBER_ROUTING_MODEL_ARG) it can access the model provided by the route']() {
['@test it can access the model provided by the route via this.model']() {
this.add(
'route:application',
Route.extend({
Expand All @@ -110,7 +112,39 @@ moduleFor(
'application',
strip`
<ul>
{{#each @model as |item|}}
{{#each this.model as |item|}}
<li>{{item}}</li>
{{/each}}
</ul>
`
);

return this.visit('/').then(() => {
this.assertInnerHTML(strip`
<ul>
<li>red</li>
<li>yellow</li>
<li>blue</li>
</ul>
`);
});
}

['@test it can access the model provided by the route via implicit this fallback']() {
this.add(
'route:application',
Route.extend({
model() {
return ['red', 'yellow', 'blue'];
},
})
);

this.addTemplate(
'application',
strip`
<ul>
{{#each model as |item|}}
<li>{{item}}</li>
{{/each}}
</ul>
Expand All @@ -128,6 +162,251 @@ moduleFor(
});
}

async ['@feature(EMBER_ROUTING_MODEL_ARG) interior mutations on the model with set'](assert) {
this.router.map(function() {
this.route('color', { path: '/:color' });
});

this.add(
'route:color',
Route.extend({
model({ color }) {
return { color };
},
})
);

this.addTemplate(
'color',
strip`
[@model: {{@model.color}}]
[this.model: {{this.model.color}}]
[model: {{model.color}}]
`
);

await this.visit('/red');

assert.equal(this.currentURL, '/red');

this.assertInnerHTML(strip`
[@model: red]
[this.model: red]
[model: red]
`);

await this.visit('/yellow');

assert.equal(this.currentURL, '/yellow');

this.assertInnerHTML(strip`
[@model: yellow]
[this.model: yellow]
[model: yellow]
`);

runTask(() => {
let { model } = this.controllerFor('color');
set(model, 'color', 'blue');
});

assert.equal(this.currentURL, '/yellow');

this.assertInnerHTML(strip`
[@model: blue]
[this.model: blue]
[model: blue]
`);
}

async ['@feature(EMBER_ROUTING_MODEL_ARG, EMBER_METAL_TRACKED_PROPERTIES) interior mutations on the model with tracked properties'](
assert
) {
class Model {
@tracked color;

constructor(color) {
this.color = color;
}
}

this.router.map(function() {
this.route('color', { path: '/:color' });
});

this.add(
'route:color',
Route.extend({
model({ color }) {
return new Model(color);
},
})
);

this.addTemplate(
'color',
strip`
[@model: {{@model.color}}]
[this.model: {{this.model.color}}]
[model: {{model.color}}]
`
);

await this.visit('/red');

assert.equal(this.currentURL, '/red');

this.assertInnerHTML(strip`
[@model: red]
[this.model: red]
[model: red]
`);

await this.visit('/yellow');

assert.equal(this.currentURL, '/yellow');

this.assertInnerHTML(strip`
[@model: yellow]
[this.model: yellow]
[model: yellow]
`);

runTask(() => {
this.controllerFor('color').model.color = 'blue';
});

assert.equal(this.currentURL, '/yellow');

this.assertInnerHTML(strip`
[@model: blue]
[this.model: blue]
[model: blue]
`);
}

async ['@feature(EMBER_ROUTING_MODEL_ARG) exterior mutations on the model with set'](assert) {
this.router.map(function() {
this.route('color', { path: '/:color' });
});

this.add(
'route:color',
Route.extend({
model({ color }) {
return color;
},
})
);

this.addTemplate(
'color',
strip`
[@model: {{@model}}]
[this.model: {{this.model}}]
[model: {{model}}]
`
);

await this.visit('/red');

assert.equal(this.currentURL, '/red');

this.assertInnerHTML(strip`
[@model: red]
[this.model: red]
[model: red]
`);

await this.visit('/yellow');

assert.equal(this.currentURL, '/yellow');

this.assertInnerHTML(strip`
[@model: yellow]
[this.model: yellow]
[model: yellow]
`);

runTask(() => {
let controller = this.controllerFor('color');
set(controller, 'model', 'blue');
});

assert.equal(this.currentURL, '/yellow');

this.assertInnerHTML(strip`
[@model: yellow]
[this.model: blue]
[model: blue]
`);
}

async ['@feature(EMBER_ROUTING_MODEL_ARG, EMBER_METAL_TRACKED_PROPERTIES) exterior mutations on the model with tracked properties'](
assert
) {
this.router.map(function() {
this.route('color', { path: '/:color' });
});

this.add(
'route:color',
Route.extend({
model({ color }) {
return color;
},
})
);

this.add(
'controller:color',
class ColorController extends Controller {
@tracked model;
}
);

this.addTemplate(
'color',
strip`
[@model: {{@model}}]
[this.model: {{this.model}}]
[model: {{model}}]
`
);

await this.visit('/red');

assert.equal(this.currentURL, '/red');

this.assertInnerHTML(strip`
[@model: red]
[this.model: red]
[model: red]
`);

await this.visit('/yellow');

assert.equal(this.currentURL, '/yellow');

this.assertInnerHTML(strip`
[@model: yellow]
[this.model: yellow]
[model: yellow]
`);

runTask(() => {
this.controllerFor('color').model = 'blue';
});

assert.equal(this.currentURL, '/yellow');

this.assertInnerHTML(strip`
[@model: yellow]
[this.model: blue]
[model: blue]
`);
}

['@feature(!EMBER_ROUTING_MODEL_ARG) it can render a nested route']() {
this.router.map(function() {
this.route('lists', function() {
Expand Down
4 changes: 0 additions & 4 deletions packages/ember/tests/routing/decoupled_basic_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,6 @@ moduleFor(
return currentPath;
}

get currentURL() {
return this.appRouter.get('currentURL');
}

handleURLRejectsWith(context, assert, path, expectedReason) {
return context
.visit(path)
Expand Down
2 changes: 1 addition & 1 deletion packages/internal-test-helpers/lib/module-for.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ export function setupTestClass(hooks, TestClass, ...mixins) {
return this.instance[name](assert);
});
} else {
let match = /^@feature\(([A-Z_a-z-!]+)\) /.exec(name);
let match = /^@feature\(([A-Z_a-z-! ,]+)\) /.exec(name);

if (match) {
let features = match[1].replace(/ /g, '').split(',');
Expand Down
9 changes: 8 additions & 1 deletion packages/internal-test-helpers/lib/test-cases/application.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,16 @@ export default class ApplicationTestCase extends TestResolverApplicationTestCase
return this.applicationInstance.lookup('router:main');
}

get currentURL() {
return this.appRouter.get('currentURL');
}

async transitionTo() {
await this.appRouter.transitionTo(...arguments);

await runLoopSettled();
}

controllerFor(name) {
return this.applicationInstance.lookup(`controller:${name}`);
}
}

0 comments on commit eeac160

Please sign in to comment.