Skip to content

Commit

Permalink
feat: add onTransitionTo & onReplaceWith events (#573)
Browse files Browse the repository at this point in the history
  • Loading branch information
tstormk authored Apr 8, 2021
1 parent b73cc27 commit 7971a02
Show file tree
Hide file tree
Showing 8 changed files with 603 additions and 13 deletions.
14 changes: 8 additions & 6 deletions addon-test-support/test-link.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,10 @@ export default class TestLink extends Link {
transitionTo(event?: Event): Transition {
this._preventTransitionOut(event);

if (this.onTransitionTo) {
this.onTransitionTo();
}
// Fire both the `onTransitionTo` event used for testing, as well as the
// optional `onTransitionTo` event used by the code being tested
this._params.onTransitionTo?.();
this.onTransitionTo?.();

return this._createDummyTransition();
}
Expand All @@ -37,9 +38,10 @@ export default class TestLink extends Link {
replaceWith(event?: Event): Transition {
this._preventTransitionOut(event);

if (this.onReplaceWith) {
this.onReplaceWith();
}
// Fire both the `onReplaceWith` event used for testing, as well as the
// optional `onReplaceWith` event used by the code being tested
this._params.onReplaceWith?.();
this.onReplaceWith?.();

return this._createDummyTransition();
}
Expand Down
4 changes: 3 additions & 1 deletion addon/components/link/template.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,7 @@
query=@query
fromURL=@fromURL
preventDefault=@preventDefault
onTransitionTo=@onTransitionTo
onReplaceWith=@onReplaceWith
)
~}}
~}}
21 changes: 20 additions & 1 deletion addon/helpers/link.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,23 @@ export interface LinkHelperNamedParams
* This is mutually exclusive with any other `LinkParams`.
*/
fromURL?: string;

/**
* An optional callback that will be fired when the Link is transitioned to.
*
* The callback is only fired if the Link is explicitly invoked, not if the
* app transitions to the Link through other means.
*/
onTransitionTo?: () => void;

/**
* An optional callback that will be fired when the current route is replaced
* with the Link.
*
* The callback is only fired if the Link is explicitly invoked, not if the
* app transitions to the Link through other means.
*/
onReplaceWith?: () => void;
}

export default class LinkHelper extends Helper {
Expand Down Expand Up @@ -119,7 +136,9 @@ export default class LinkHelper extends Helper {
positionalQueryParameters ? -1 : undefined
) as RouteModel[])
: undefined,
query: named.query ?? positionalQueryParameters
query: named.query ?? positionalQueryParameters,
onTransitionTo: named.onTransitionTo,
onReplaceWith: named.onReplaceWith
};
}

Expand Down
21 changes: 21 additions & 0 deletions addon/link.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,23 @@ export interface LinkParams {
* Optional query params object.
*/
query?: QueryParams;

/**
* An optional callback that will be fired when the Link is transitioned to.
*
* The callback is only fired if the Link is explicitly invoked, not if the
* app transitions to the Link through other means.
*/
onTransitionTo?: () => void;

/**
* An optional callback that will be fired when the current route is replaced
* with the Link.
*
* The callback is only fired if the Link is explicitly invoked, not if the
* app transitions to the Link through other means.
*/
onReplaceWith?: () => void;
}

function freezeParams(params: LinkParams) {
Expand Down Expand Up @@ -234,6 +251,8 @@ export default class Link {
this._linkManager.isRouterInitialized
);

this._params.onTransitionTo?.();

return this._linkManager.router.transitionTo(...this._routeArgs);
}

Expand All @@ -248,6 +267,8 @@ export default class Link {
this._linkManager.isRouterInitialized
);

this._params.onReplaceWith?.();

return this._linkManager.router.replaceWith(...this._routeArgs);
}
}
Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
"@types/ember__test-helpers": "^1.7.3",
"@types/qunit": "^2.11.1",
"@types/rsvp": "^4.0.3",
"@types/sinon": "^9.0.10",
"broccoli-asset-rev": "^3.0.0",
"ember-array-helper": "^5.1.0",
"ember-cli": "~3.24.0",
Expand All @@ -68,6 +69,7 @@
"ember-on-modifier": "^1.0.1",
"ember-qunit": "^4.6.0",
"ember-resolver": "^8.0.2",
"ember-sinon-qunit": "^5.0.0",
"ember-source": "~3.25.0",
"ember-source-channel-url": "^3.0.0",
"ember-template-lint": "^2.18.1",
Expand Down
66 changes: 66 additions & 0 deletions tests/acceptance/link-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ import { visit, currentURL, click } from '@ember/test-helpers';
import { setupApplicationTest } from 'ember-qunit';
import { module, test } from 'qunit';

import Controller from '@ember/controller';
import Route from '@ember/routing/route';

import { hbs } from 'ember-cli-htmlbars';
import { TestContext } from 'ember-test-helpers';

import pDefer from 'p-defer';
import sinon from 'sinon';

import { settledExceptTimers } from 'dummy/tests/helpers/settled-except-timers';

Expand Down Expand Up @@ -391,4 +393,68 @@ module('Acceptance | link', function (hooks) {

assert.dom().hasText('/with-model/123');
});

test('it fires onTransitionTo correctly', async function (this: TestContext, assert) {
const spy = sinon.spy();

this.owner.register(
'controller:application',
class ApplicationController extends Controller {
spy = spy;
}
);
this.owner.register(
'template:application',
hbs`
<Link @route="foo" @query={{hash qp=123}} @onTransitionTo={{this.spy}} as |l|>
<a
data-test-123
href={{l.href}}
{{on "click" l.transitionTo}}
>
Link
</a>
</Link>
`
);

await visit('/');
assert.strictEqual(currentURL(), '/');

await click('[data-test-123');

assert.ok(spy.calledOnce);
});

test('it fires onReplaceWith correctly', async function (this: TestContext, assert) {
const spy = sinon.spy();

this.owner.register(
'controller:application',
class ApplicationController extends Controller {
spy = spy;
}
);
this.owner.register(
'template:application',
hbs`
<Link @route="foo" @query={{hash qp=123}} @onReplaceWith={{this.spy}} as |l|>
<a
data-test-123
href={{l.href}}
{{on "click" l.replaceWith}}
>
Link
</a>
</Link>
`
);

await visit('/');
assert.strictEqual(currentURL(), '/');

await click('[data-test-123');

assert.ok(spy.calledOnce);
});
});
3 changes: 3 additions & 0 deletions tests/test-helper.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import { setApplication } from '@ember/test-helpers';
import { start } from 'ember-qunit';

import setupSinon from 'ember-sinon-qunit';

import Application from 'dummy/app';
import config from 'dummy/config/environment';

import 'qunit-dom';

setApplication(Application.create(config.APP));

setupSinon();
start();
Loading

0 comments on commit 7971a02

Please sign in to comment.