Skip to content

Commit 54f02fe

Browse files
authored
[ENG-4010] Address deprecated router event (#1661)
- Ticket: [ENG-4010] ## Purpose - Address deprecation of router events found here: https://deprecations.emberjs.com/v3.x/#toc_deprecate-router-events ## Summary of Changes - Remove usage of `willTransition` and `didTransition` in the app router - Remove usage of private router API from app router - Move logic that was handled in aforementioned `willTransition`, `didTransition` and other private router API calls into a new app-instance initializer `router` (The name is sort of awful, so any alternative name suggestions would be much appreciated 😬 ) - Fetch server-side rendered page if a given waffle flag is not enabled - Scroll to top on page change, except in cases of query-param only route changes
1 parent a4dd069 commit 54f02fe

File tree

26 files changed

+147
-89
lines changed

26 files changed

+147
-89
lines changed
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import ApplicationInstance from '@ember/application/instance';
2+
import Transition from '@ember/routing/-private/transition';
3+
import RouterService from '@ember/routing/router-service';
4+
import Ember from 'ember';
5+
import Features from 'ember-feature-flags/services/features';
6+
7+
import { Blocker } from 'ember-osf-web/services/ready';
8+
import transitionTargetURL from 'ember-osf-web/utils/transition-target-url';
9+
10+
import config from 'ember-get-config';
11+
12+
const {
13+
featureFlagNames: {
14+
routes: routeFlags,
15+
},
16+
} = config;
17+
18+
export function initialize(appInstance: ApplicationInstance): void {
19+
const routerService = appInstance.lookup('service:router') as RouterService;
20+
let readyBlocker = null as Blocker | null;
21+
22+
routerService.on('routeWillChange', (transition: Transition) => {
23+
const ready = appInstance.lookup('service:ready');
24+
const features = appInstance.lookup('service:features') as Features;
25+
if (!readyBlocker || readyBlocker.isDone()) {
26+
readyBlocker = ready.getBlocker();
27+
}
28+
29+
const isInitialTransition = transition.sequence === 0;
30+
if (!isInitialTransition) {
31+
const flag = routeFlags[transition.targetName];
32+
if (flag && !features.isEnabled(flag)) {
33+
if (!Ember.testing) {
34+
try {
35+
window.location.assign(transitionTargetURL(transition));
36+
} catch (e) {
37+
window.location.reload();
38+
}
39+
}
40+
transition.abort();
41+
}
42+
}
43+
44+
routerService._super(transition);
45+
});
46+
47+
routerService.on('routeDidChange', (transition: Transition) => {
48+
const currentUser = appInstance.lookup('service:current-user');
49+
const statusMessages = appInstance.lookup('service:status-messages');
50+
currentUser.checkShowTosConsentBanner();
51+
statusMessages.updateMessages();
52+
if (!transition.queryParamsOnly) {
53+
const { rootElement: rootElementSelector } = appInstance as any;
54+
const rootElement = document.querySelector(rootElementSelector);
55+
rootElement.scrollIntoView();
56+
}
57+
58+
if (readyBlocker && !readyBlocker.isDone()) {
59+
readyBlocker.done();
60+
}
61+
});
62+
}
63+
64+
export default {
65+
initialize,
66+
};

app/router.ts

Lines changed: 0 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -1,96 +1,17 @@
1-
import { getOwner } from '@ember/application';
2-
import Transition from '@ember/routing/-private/transition';
31
import EmberRouter from '@ember/routing/router';
4-
import { inject as service } from '@ember/service';
5-
import Ember from 'ember';
62
import config from 'ember-get-config';
73

8-
import { Blocker } from 'ember-osf-web/services/ready';
9-
import transitionTargetURL from 'ember-osf-web/utils/transition-target-url';
10-
114
const {
125
engines: {
136
collections,
147
registries,
158
},
16-
featureFlagNames: {
17-
routes: routeFlags,
18-
},
199
} = config;
2010

21-
/* eslint-disable ember/no-get */
2211
const Router = EmberRouter.extend({
23-
currentUser: service('current-user'),
24-
features: service('features'),
25-
statusMessages: service('status-messages'),
26-
ready: service('ready'),
27-
28-
// eslint-disable-next-line ember/avoid-leaking-state-in-ember-objects
29-
readyBlocker: null as Blocker | null,
3012
location: config.locationType,
3113
rootURL: config.rootURL,
32-
shouldScrollTop: true,
33-
34-
willTransition(oldInfo: any, newInfo: any, transition: { targetName: string }) {
35-
if (!this.readyBlocker || this.readyBlocker.isDone()) {
36-
this.readyBlocker = this.get('ready').getBlocker();
37-
}
38-
39-
this._super(oldInfo, newInfo, transition);
40-
},
41-
42-
didTransition(...args: any[]) {
43-
this._super(...args);
44-
45-
this.get('currentUser').checkShowTosConsentBanner();
46-
this.get('statusMessages').updateMessages();
47-
48-
if (this.shouldScrollTop) {
49-
const { application: { rootElement: rootElementSelector } } = getOwner(this);
50-
const rootElement = document.querySelector(rootElementSelector);
51-
rootElement.scrollIntoView();
52-
}
53-
54-
if (this.readyBlocker && !this.readyBlocker.isDone()) {
55-
this.readyBlocker.done();
56-
}
57-
},
58-
59-
_doTransition(...args: any[]) {
60-
const transition = this._super(...args);
61-
return this._beforeTransition(transition);
62-
},
63-
64-
_doURLTransition(...args: any[]) {
65-
const transition = this._super(...args);
66-
return this._beforeTransition(transition);
67-
},
68-
69-
_beforeTransition(transition: Transition) {
70-
// Don't snap the page to the top if it's just a query param change
71-
// IE registries, preprints, collections, etc
72-
// There doesn't appear to be a good way to access the transition
73-
// inside of didTransition, so the state is just plucked here for future reference.
74-
this.shouldScrollTop = !transition.queryParamsOnly;
75-
76-
const isInitialTransition = transition.sequence === 0;
77-
if (!isInitialTransition) {
78-
const flag = routeFlags[transition.targetName];
79-
if (flag && !this.get('features').isEnabled(flag)) {
80-
if (!Ember.testing) {
81-
try {
82-
window.location.assign(transitionTargetURL(transition));
83-
} catch (e) {
84-
window.location.reload();
85-
}
86-
}
87-
transition.abort();
88-
}
89-
}
90-
return transition;
91-
},
9214
});
93-
/* eslint-enable ember/no-get */
9415

9516
/* eslint-disable array-callback-return */
9617

config/deprecation-workflow.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ self.deprecationWorkflow.config = {
44
{ handler: 'silence', matchId: 'ember-inflector.globals' },
55
{ handler: 'silence', matchId: 'ember-metal.get-with-default' },
66
{ handler: 'silence', matchId: 'computed-property.volatile' },
7-
{ handler: 'silence', matchId: 'deprecate-router-events' },
87
{ handler: 'silence', matchId: 'implicit-injections' },
98
{ handler: 'silence', matchId: 'manager-capabilities.modifiers-3-13' },
109
{ handler: 'silence', matchId: 'this-property-fallback' },

handbook-docs/troubleshooting/template.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ parameter. You just need to
5252

5353
Then, either in `beforeEach` or in the particular problematic test:
5454

55+
`this.owner.unregister('service:router');`
5556
`this.owner.register('service:router', OsfLinkRouterStub);`
5657

5758
## Buttons in modals aren't tracking analytics events

tests/acceptance/resolve-guid-test.ts

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
import Transition from '@ember/routing/-private/transition';
22
import Service from '@ember/service';
33
import { currentRouteName, currentURL, settled } from '@ember/test-helpers';
4-
import { getContext } from '@ember/test-helpers/setup-context';
54
import { setupMirage } from 'ember-cli-mirage/test-support';
65
import config from 'ember-get-config';
76
import { setupApplicationTest } from 'ember-qunit';
87
import { TestContext } from 'ember-test-helpers';
98
import { module, test } from 'qunit';
10-
import sinon, { SinonStub } from 'sinon';
9+
import sinon from 'sinon';
1110

1211
import { Permission } from 'ember-osf-web/models/osf-model';
1312
import { currentURL as currentLocationURL, visit } from 'ember-osf-web/tests/helpers';
@@ -23,16 +22,15 @@ const KeenStub = Service.extend({
2322
},
2423
});
2524

25+
const routeWillChangeStub = sinon.stub();
26+
2627
function routingAssertions(assert: Assert, segment: string, url: string, route: string) {
2728
assert.equal(currentURL(), `/${segment}${url}`, `The "real" URL contains the hidden "${segment}" segment`);
2829
assert.equal(currentLocationURL(), url, 'The Location URL is the same');
2930
assert.equal(currentRouteName(), route, 'The correct route was reached');
3031

31-
// eslint-disable-next-line ember/no-private-routing-service
32-
const router = (getContext() as TestContext).owner.lookup('router:main');
33-
const flagStub: SinonStub = router._beforeTransition;
3432
assert.ok(
35-
flagStub.args.any(
33+
routeWillChangeStub.args.any(
3634
([t]: [Transition]) => t.targetName === route,
3735
),
3836
`The router checked for a feature flag for "${route}"`,
@@ -44,9 +42,8 @@ module('Acceptance | resolve-guid', hooks => {
4442
setupMirage(hooks);
4543

4644
hooks.beforeEach(function(this: TestContext) {
47-
// eslint-disable-next-line ember/no-private-routing-service
48-
const router = this.owner.lookup('router:main');
49-
sinon.stub(router, '_beforeTransition').returnsArg(0);
45+
const router = this.owner.lookup('service:router');
46+
router.on('routeWillChange', routeWillChangeStub);
5047
});
5148

5249
test('File | Index', async assert => {

tests/engines/registries/integration/components/page-link/component-test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ module('Registries | Integration | Component | page-link', hooks => {
3131
setupEngineRenderingTest(hooks, 'registries');
3232

3333
hooks.beforeEach(function(this: TestContext) {
34+
this.owner.unregister('service:router');
3435
this.owner.register('service:router', RouterStub);
3536
this.owner.register('service:osf-router', RouterStub);
3637
this.owner.register('service:current-user', CurrentUserStub);

tests/engines/registries/integration/components/side-nav/component-test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ module('Registries | Integration | Component | side-nav', hooks => {
3131
setupEngineRenderingTest(hooks, 'registries');
3232

3333
hooks.beforeEach(function(this: TestContext) {
34+
this.owner.unregister('service:router');
3435
this.owner.register('service:router', RouterStub);
3536
this.owner.register('service:osf-router', RouterStub);
3637
this.owner.register('service:current-user', CurrentUserStub);

tests/integration/components/ancestry-display/component-test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ module('Integration | Component | ancestry-display', hooks => {
2222

2323
hooks.beforeEach(function(this: TestContext) {
2424
this.store = this.owner.lookup('service:store');
25+
this.owner.unregister('service:router');
2526
this.owner.register('service:router', OsfLinkRouterStub.extend({
2627
urlFor(__: any, modelId: string) {
2728
return `/${modelId}`;

tests/integration/components/contributors/component-test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ module('Integration | Component | contributors', hooks => {
2525
hooks.beforeEach(function(this: ThisTestContext) {
2626
this.store = this.owner.lookup('service:store');
2727
this.currentUser = this.owner.lookup('service:current-user');
28+
this.owner.unregister('service:router');
2829
this.owner.register('service:router', OsfLinkRouterStub);
2930
server.loadFixtures('schema-blocks');
3031
server.loadFixtures('registration-schemas');

tests/integration/components/draft-registration-card/component-test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ module('Integration | Component | draft-registration-card', hooks => {
1414
hooks.beforeEach(function(this: TestContext) {
1515
this.store = this.owner.lookup('service:store');
1616
this.intl = this.owner.lookup('service:intl');
17+
this.owner.unregister('service:router');
1718
this.owner.register('service:router', OsfLinkRouterStub);
1819
server.loadFixtures('schema-blocks');
1920
server.loadFixtures('registration-schemas');

0 commit comments

Comments
 (0)