As part of my effort to learn Ember.js, I built a relatively simple app that used the TFL API to fetch bus arrival times at nearby stops. It can also do tube, DLR and overground, and eventually I may include other means of transport. It’s called London Waits.
All this was built in Ember 1.13, and only now I decided to upgrade it to Ember 2. It wasn’t trivial, but in the process I gathered some notes that may help others.
Ember 2.0: initial upgrades
I started by upgrading Ember proper to 2.0.x. This can be done with Bower:
1$ bower install ember#2.0.x --save
There was immediately a problem. When I run the app, it complained that it required a more recent version of jQuery:
1Error: Assertion Failed: Ember Views require jQuery between 1.7 and 2.1
I did as told:
1$ bower install jquery#2.1.x --save
This got my tests passing again, so I proceeded to upgrade Ember Data. Now, before version 2.3, Ember Data had both an npm module and a Bower component, and both were required. I’m not entirely sure, but I think the npm module provided CLI tools, whereas the Bower package provided the library proper. In fact, try upgrading the npm package only first:
1$ npm install [email protected] --save-dev
My tests pass after that, but the debug messages in the console reveal that I’m still using an old version of Ember Data:
This is fixed by installing the Bower package. Pay special attention to the fact
that the version comes after a ‘#’, not an ‘@’, and that the dependency is saved
with runtime packages --save
, instead of development packages --save-dev
.
Easy to miss!
1$ bower install ember-data#2.0.x --save
My tests were passing and I was on Ember 2. Yay!
Ember 2.1: problems with error routes
Carrying on with the upgrade, I went for Ember 2.1. It should be just a matter of upgrading the package, right?
1$ bower install ember#2.1.x --save
However, one of my tests stopped working: one that ensured that the app rendered an error route correctly. After some online research, I discovered that this indeed stopped working in the run up to 2.1, and there seems to be no official support. I was rather bummed by this, but fortunately I found a workaround in a thread discussing this issue on GitHub.
I generalised the workaround into a helper and published it as a GitHub Gist, although the example provided has some additional changes that we’ll get to later in this writeup. Right now, for the code just as it was upgraded from 1.13, the example should look like this:
1/// tests/acceptance/errors-test.js 2import Ember from 'ember'; 3import { module, test } from 'qunit'; 4import startApp from 'london-waits/tests/helpers/start-app'; 5import errorStateWorkaround from 'london-waits/tests/helpers/error-state-workaround'; 6 7module("Acceptance | errors", { 8 beforeEach: function() { 9 this.application = startApp(); 10 errorStateWorkaround.setup(err => { 11 // Return `true` if `err` is the error 12 // we expect, and `false` otherwise 13 }); 14 }, 15 16 afterEach: function() { 17 errorStateWorkaround.teardown(); 18 Ember.run(this.application, 'destroy'); 19 }, 20}); 21 22test("Something that lands an error", function(assert) { 23 // Do something that would get the user to 24 // an error route or substate 25 26 andThen(function() { 27 // Assert that the error has ocurred as expected 28 }); 29});
After that, I got my tests passing. Now it’s time to upgrade Ember Data:
1$ npm install [email protected] --save-dev 2$ bower install ember-data#2.1.x --save
And that’s all for 2.1.
Ember 2.2: liquid-fire needs upgrading
A simpler one now. My app was using the liquid-fire addon at version 0.21.2. This was not compatible with Ember 2.2. The error I was getting was:
1TypeError: renderNode.state is undefined
Anyway, I upgraded liquid-fire along with Ember itself. These are the lines to run, and the ones for Ember Data 2.2:
1$ bower install ember#2.2.x --save 2$ npm install liquid-fire --save-dev 3$ npm install [email protected] --save-dev 4$ bower install ember-data#2.2.x --save
Ember 2.3: Ember Data is not in Bower any more
For Ember 2.3, just install Ember 2.3 (d’oh):
1$ bower install ember#2.3.x --save
The release notes for Ember 2.3 advise that we upgrade ember-qunit, which is a Bower package. I wasn’t getting any errors on my tests, but did it nonetheless:
1$ bower install ember-qunit --save
As for the release notes for Ember Data
2.3, these
inform us that the Bower package is not required any more, as Ember Data is now
a full-fledged Ember addon. Also, ember-cli-shims (npm) needs to be upgraded to
0.1.0. Manually remove any references to ember-data from bower.json
:
1diff --git a/bower.json b/bower.json 2index 214ef1e..8f74eb7 100644 3--- a/bower.json 4+++ b/bower.json 5@@ -4,7 +4,6 @@ 6 "ember": "2.3.x", 7 "ember-cli-shims": "ember-cli/ember-cli-shims#0.0.3", 8 "ember-cli-test-loader": "ember-cli-test-loader#0.1.3", 9- "ember-data": "2.2.x", 10 "ember-load-initializers": "ember-cli/ember-load-initializers#0.1.5", 11 "ember-qunit": "^0.4.20", 12 "ember-qunit-notifications": "0.0.7", 13@@ -19,7 +18,6 @@ 14 "Faker": "~2.1.3" 15 }, 16 "resolutions": { 17- "ember-data": "2.2.x", 18 "ember": "2.3.x", 19 "jquery": "2.1.x", 20 "ember-qunit": "^0.4.20"
And upgrade the required packages at the command line:
1$ npm install [email protected] --save-dev 2$ bower install ember-cli-shims#0.1.0 --save
2.4: an easy one
1$ bower install ember#2.4.x --save 2$ npm install [email protected] --save-dev
Piece of cake.
2.5: changes to selectors in tests
So I upgraded Ember as usual:
1$ bower install ember#2.5.x --save
And tests started failing :-(
I’m not sure where exactly this comes from, but the semantics of jQuery
selectors seem to have changed subtly between Ember 2.4 and 2.5, at least in
acceptance tests. This affected all my acceptance tests because the click()
helper started to fail.
My HTML contains something like this:
And my acceptance tests would do this:
1click(':contains("Bar")');
Before 2.5, that would have sufficed to follow the link, but now the helper must
be triggering the click
event differently, so it’s necessary to be more
specific. This works:
1click('a:contains("Bar")');
And since Ember Data is a proper Ember addon, I thought I would upgrade it as such from now on:
1$ ember install [email protected]
2.6: finally!
The last step was easy again:
Epilogue: updating ancillary files
After all the above, I got the app working on Ember(+Data) 2.6. Although this
should be enough, there are still some differences with a proper 2.6 app as
generated with ember new
. These differences are in the files generated with
the application. I decided to update these too to avoid any potential problems
in the future.
What I did was generating a new app, then comparing the generated files with
those in mine. There are a few differences, for example in app/app.js
:
1@@ -1,6 +1,6 @@ 2 import Ember from 'ember'; 3-import Resolver from './resolver'; 4-import loadInitializers from 'ember-load-initializers'; 5+import Resolver from 'ember/resolver'; 6+import loadInitializers from 'ember/load-initializers'; 7 import config from './config/environment'; 8 9 var App; 10@@ -25,7 +25,7 @@ Ember.onerror = function(error) { 11 App = Ember.Application.extend({ 12 modulePrefix: config.modulePrefix, 13 podModulePrefix: config.podModulePrefix, 14- Resolver 15+ Resolver: Resolver 16 }); 17 18 loadInitializers(App, config.modulePrefix);
Also there are new files, such as tests/helpers/module-for-acceptance.js
,
which is used in acceptance tests.
Differences too in package.json
and bower.json
. I updated the packages that
were behind, leaving alone those for which my version was ahead. All in all, I
tried to reduce differences with a 2.6 app as much as possible. This included:
- Updating old packages
- Leaving alone packages that I had added myself
- Updating packages added by myself that had compatibility issues or deprecation notices
- Removing some packages that are not necessary any more
- Adding new packages
- Removing the
resolutions
section frombower.json
This was a slow and annoying process, but it may spare me new problems in the
future. Also, I avoided including the addon ember-welcome-page
because it’s
only useful in new installs, and expected to be removed by the developer after
work starts.
After all these changes, my tests failed again, again because of a subtlety,
this time in the test helper moduleForAcceptance
. In two of my tests, I had a
utility function defined as part of the test module:
Turns out this doesn’t work when using moduleForAcceptance
instead of
module
. I had to define the utility function outside and bind it to the module
at beforeEach
:
1/// tests/acceptance/my-test-test.js 2function myUtilityFunction() { 3 // do useful stuff... 4} 5 6moduleForAcceptance("Acceptance - my test", { 7 // ... 8 beforeEach() { 9 this.myUtilityFunction = myUtilityFunction; 10 }, 11 // ... 12}); 13 14test("Test case", function(assert) { 15 // ... 16 this.myUtilityFunction(); 17 // ... 18});
This got me back on green tests.
After all this, I still have a deprecation notice coming from liquid-fire. There doesn’t seem to be anything I can do about that, so I’ll just leave it there and wait until a new release of the addon fixes it.