From 671f63007ab62ef4c83a0f886be2315b07dcdf93 Mon Sep 17 00:00:00 2001 From: Alex LaFroscia Date: Mon, 22 Feb 2021 15:48:12 -0500 Subject: [PATCH] fix(ember): keep route hook context when performance-wrapping --- packages/ember/addon/index.ts | 8 +-- .../unit/instrument-route-performance-test.ts | 62 +++++++++++++++++++ 2 files changed, 66 insertions(+), 4 deletions(-) create mode 100644 packages/ember/tests/unit/instrument-route-performance-test.ts diff --git a/packages/ember/addon/index.ts b/packages/ember/addon/index.ts index 8fc44f7d306d..eb9e4a9bed26 100644 --- a/packages/ember/addon/index.ts +++ b/packages/ember/addon/index.ts @@ -71,22 +71,22 @@ export const instrumentRoutePerformance = (BaseRoute: any) => { return { [BaseRoute.name]: class extends BaseRoute { beforeModel(...args: any[]) { - return instrumentFunction('ember.route.beforeModel', (this).fullRouteName, super.beforeModel, args); + return instrumentFunction('ember.route.beforeModel', (this).fullRouteName, super.beforeModel.bind(this), args); } async model(...args: any[]) { - return instrumentFunction('ember.route.model', (this).fullRouteName, super.model, args); + return instrumentFunction('ember.route.model', (this).fullRouteName, super.model.bind(this), args); } async afterModel(...args: any[]) { - return instrumentFunction('ember.route.afterModel', (this).fullRouteName, super.afterModel, args); + return instrumentFunction('ember.route.afterModel', (this).fullRouteName, super.afterModel.bind(this), args); } async setupController(...args: any[]) { return instrumentFunction( 'ember.route.setupController', (this).fullRouteName, - super.setupController, + super.setupController.bind(this), args, ); } diff --git a/packages/ember/tests/unit/instrument-route-performance-test.ts b/packages/ember/tests/unit/instrument-route-performance-test.ts new file mode 100644 index 000000000000..fbe858e42c36 --- /dev/null +++ b/packages/ember/tests/unit/instrument-route-performance-test.ts @@ -0,0 +1,62 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; +import Route from '@ember/routing/route'; +import { instrumentRoutePerformance } from '@sentry/ember'; +import sinon from 'sinon' +import { setupSentryTest } from '../helpers/setup-sentry'; + +module('Unit | Utility | instrument-route-performance', function(hooks) { + setupTest(hooks); + setupSentryTest(hooks); + + test('wrapped Route hooks maintain the current context', function(assert) { + const beforeModel = sinon.spy(); + const model = sinon.spy(); + const afterModel = sinon.spy(); + const setupController = sinon.spy(); + + class DummyRoute extends Route { + beforeModel(...args: any[]) { + return beforeModel.call(this, ...args); + } + + model(...args: any[]) { + return model.call(this, ...args); + } + + afterModel(...args: any[]) { + return afterModel.call(this, ...args); + } + + setupController(...args: any[]) { + return setupController.call(this, ...args); + } + } + + const InstrumentedDummyRoute = instrumentRoutePerformance(DummyRoute); + + this.owner.register('route:dummy', InstrumentedDummyRoute); + + const route = this.owner.lookup('route:dummy'); + + route.beforeModel('foo'); + + assert.ok(beforeModel.calledOn(route), "The context for `beforeModel` is the route"); + assert.ok(beforeModel.calledWith('foo'), 'The arguments for `beforeModel` are passed through'); + + route.model('bar'); + + assert.ok(model.calledOn(route), "The context for `model` is the route"); + assert.ok(model.calledWith('bar'), 'The arguments for `model` are passed through'); + + route.afterModel('bax'); + + assert.ok(afterModel.calledOn(route), "The context for `afterModel` is the route"); + assert.ok(afterModel.calledWith('bax'), 'The arguments for `afterModel` are passed through'); + + route.setupController('baz'); + + assert.ok(setupController.calledOn(route), "The context for `setupController` is the route"); + assert.ok(setupController.calledWith('baz'), 'The arguments for `setupController` are passed through'); + }); +});