Skip to content

[FIX] Handle hash change in url #337

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Conversation

akashdsouza
Copy link
Contributor

@akashdsouza
Copy link
Contributor Author

akashdsouza commented Sep 1, 2017

I'm also trying to write a couple of acceptance tests. However, I'm not sure as how to defer the assertions

@MartinMalinda
Copy link
Contributor

As long as it will trigger page refresh it's not gonna be testable.

Some ideas:

  • Make hashToQuery return the new url, instead of doing the redirect directly
  • Create a shim for this function
  • Add an initializer, import this function shim there, add an eventListener for hashchange
  • Lookup the router service and in the hashchange callback, do router.transitionTo(newURL) (it should accept URL afaik)

@akashdsouza akashdsouza changed the title WIP:[FIX] Handle hash change in url [FIX] Handle hash change in url Sep 7, 2017
@akashdsouza akashdsouza force-pushed the bugfix_redirect_on_hash_change branch from 9f14289 to 51e5513 Compare September 7, 2017 09:12
@akashdsouza
Copy link
Contributor Author

I have made some changes. @MartinMalinda do these changes look ok?

@@ -0,0 +1,32 @@
(() => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lib/hash-to-query/vendor/hash-to-query/index.js that looks a bit strange file path, is that intentional?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just looked up ember-router-service-polyfill addon for reference. But then again, this is just an in-repo addon. Any suggestions?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am only wondering about placement of the file lib -> hash-to-query -> vendor -> hash-to-query -> index.js.

export function initialize(application) {
let redirectToUrl = hashToQuery();
if (redirectToUrl) {
window.location.href = window.location.origin + redirectToUrl;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would do this first check already in the vendor file, it will happen sooner.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It will also need typeof FastBoot === undefined check there.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would do this first check already in the vendor file, it will happen sooner.

I don't understand. Wouldn't we need to have this check before setting location href?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It will also need typeof FastBoot === undefined check there

If this check can be moved to vendor file, can't window check also be placed along with that

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes I would move it as a whole:

  let redirectToUrl = hashToQuery();
  if (redirectToUrl) {
    window.location.href = window.location.origin + redirectToUrl;
  }

To the vendor file.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this check can be moved to vendor file, can't window check also be placed along with that

If FastBoot is undefined, window will be defined. No need to double check for window.

});

// Replace this with your real tests.
test('it works', function(assert) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be good to have some input/output tests for the hashToQuery function here. (unless the test coverage for it is elsewhere already)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Simple acceptance test would be cool as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added tests for hashToQuery

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to verify that legacy links with hashes work (as the currently do today)

(() => {
/* globals define */
function hashToQuery() {
var hash = window && window.location && window.location.hash;
Copy link
Contributor

@MartinMalinda MartinMalinda Sep 7, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is overly defensive. hashToQuery should be called only when window.location exists.

@akashdsouza akashdsouza force-pushed the bugfix_redirect_on_hash_change branch from 6c97a7c to 8a31915 Compare September 7, 2017 16:52
initialize(this.appInstance);

let redirectToUrl = hashToQuery('method', '/class');
assert.equal(redirectToUrl, '/class?anchor=method&show=inherited,protected,private,deprecated', 'hashToQuery function works');
Copy link
Contributor

@MartinMalinda MartinMalinda Sep 7, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

try these tests with some real data scenarios:

let redirectToUrl = hashToQuery('#method', '/class');
  assert.equal(redirectToUrl, '/class?anchor=method&show=inherited,protected,private,deprecated', 'hashToQuery function works');
  assert.equal(hashToQuery('#method_pushPayload', '/ember-data/2.14/classes/DS.Store'), '/ember-data/2.14/classes/DS.Store/methods/pushPayload?anchor=pushPayload&show=inherited,protected,private,deprecated');
  assert.equal(hashToQuery('#method_pushPayload', '/ember-data/2.14/classes/DS.Store/methods/createRecord'), '/ember-data/2.14/classes/DS.Store/methods/pushPayload?anchor=pushPayload&show=inherited,protected,private,deprecated');
  assert.equal(hashToQuery('#method_push', '/ember-data/2.14/classes/DS.Store/methods/createRecord'), '/ember-data/2.14/classes/DS.Store/methods/push?anchor=push&show=inherited,protected,private,deprecated');

Only the second one passes. The others fail because they contain /methods/. Either the hashToQuery function needs to be updated or a new function needs be made that shares some of the logic.

@MartinMalinda
Copy link
Contributor

I'm looking into this a little bit more the situation on the initial load of the app and the internal hashchange are a bit different.

Maybe reusing the hashToQuery function is not the best way and just having two different function would be better.

I hacked this together really quick and it works:

import hashToQuery from 'hash-to-query';
import Inflector from 'ember-inflector';

const {inflector} = Inflector;

export function initialize(application) {
  if (typeof FastBoot === 'undefined') {
    window.onhashchange = function() {
      const { hash } = window.location;
      if (hash.includes('#') && hash.includes('_')) {
        const [type, anchor] = hash.replace('#', '').split('_');
        const router = application.lookup('service:router');
        const currentRoute = router.get('currentRouteName');
        const baseRoute = currentRoute.split('.').splice(0, 3).join('.');
        const subRoute = `${inflector.pluralize(type)}.${type}`;
        router.transitionTo(`${baseRoute}.${subRoute}`, {
          queryParams: { anchor }
        });        
      }
    }
  }
}

export default {
  name: 'hash-to-query-redirect',
  initialize
};

@MartinMalinda
Copy link
Contributor

We can also update to 2.15 and the polyfill does not need to be installed

@MartinMalinda
Copy link
Contributor

@akashdsouza would it be fine for you if I pull your commit and create a new PR with my changes?

@akashdsouza
Copy link
Contributor Author

@MartinMalinda Sure. Go ahead

@@ -8,33 +8,8 @@ module.exports = {
return true;
},

contentFor (type, config) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this really going to work for direct url access, such as say I have a bookmarked link for something with #method_toString?

@@ -8,33 +8,8 @@ module.exports = {
return true;
},

contentFor (type, config) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if we are taking out the need for contentFor, then this doesn't need to be an in-repo addon. just make it a util function.

}
}
}
if (typeof FastBoot === 'undefined') {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what's this for? Should never enter this if I don't think...

@locks locks temporarily deployed to ember-api-docs-staging-pr-337 September 8, 2017 17:17 Inactive
@locks locks temporarily deployed to ember-api-docs-staging-pr-337 September 8, 2017 17:29 Inactive
@toddjordan
Copy link
Contributor

tried to deploy a heroku preview app for this but got an error running yarn:
image

@toddjordan
Copy link
Contributor

Going to drop support for legacy method/property links, making this fix moot.

@toddjordan toddjordan closed this Mar 28, 2019
Gaurav0 pushed a commit to Gaurav0/ember-api-docs that referenced this pull request Sep 16, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants