Skip to content

Fix current path detection for locale URL parameter#8792

Merged
aduth merged 3 commits intomainfrom
aduth-tab-navigation-locale-param
Jul 18, 2023
Merged

Fix current path detection for locale URL parameter#8792
aduth merged 3 commits intomainfrom
aduth-tab-navigation-locale-param

Conversation

@aduth
Copy link
Contributor

@aduth aduth commented Jul 17, 2023

🛠 Summary of changes

Improves "current path" detection for TabNavigationComponent, fixing an issue where locale specified through a URL parameter would not be reflected.

Example: https://secure.login.gov/?locale=es

Related Slack discussion: https://gsa-tts.slack.com/archives/C0NGESUN5/p1689604911179219

📜 Testing Plan

  1. Go to all of the following URLs and observe that "Sign in" is shown as the currently-selected link:

👀 Screenshots

Before After
image image

changelog: Bug Fixes, Localization, Fix tab navigation not showing selected tab in specific parameter combinations
request.path == URI.parse(path).path
rescue URI::InvalidURIError
recognized_path = Rails.application.routes.recognize_path(path)
[recognized_path, request].pluck(:controller, :action).uniq.one?
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This hazards toward being overly "clever" in a way which harms readability. Open to revising.

This is basically equivalent to the expanded form...

Suggested change
[recognized_path, request].pluck(:controller, :action).uniq.one?
request[:controller] == recognized_path[:controller] &&
request[:action] == recognized_path[:action]

Copy link
Contributor Author

@aduth aduth Jul 17, 2023

Choose a reason for hiding this comment

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

Could also extract a method for some self-documenting code, but at that point we've probably lost any benefit of "simplifying"

Suggested change
[recognized_path, request].pluck(:controller, :action).uniq.one?
same_hash_values?([recognized_path, request], [:controller, :action])
end
def same_hash_values?(hashes, properties)
hashes.pluck(*properties).uniq.one?

Copy link
Contributor

Choose a reason for hiding this comment

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

How about:

Suggested change
[recognized_path, request].pluck(:controller, :action).uniq.one?
request.slice(:controller, :action) == recognized_path.slice(:controller, :action)

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 think I've probably talked myself into just going with the simple version 😄

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@zachmargolis Oops, missed your comment 'til now. Yeah, that might be a reasonable compromise of conciseness and readability!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@zachmargolis Unfortunately doesn't work as-is, since request isn't actually a hash, it's a ActionDispatch::Request (ActionDispatch::TestRequest in spec).

Copy link
Contributor

Choose a reason for hiding this comment

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

ah dang. Thanks for trying, I do agree with the simpler approach that you landed on

Copy link
Contributor

@zachmargolis zachmargolis left a comment

Choose a reason for hiding this comment

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

LGTM

allow(vc_test_request).to receive(:path).and_return('/first')
let(:request_path) { '/first' }

class ExampleController < ApplicationController; end
Copy link
Contributor

Choose a reason for hiding this comment

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

the way RSpec uses blocks, class definitions like this end up at the global scope, so they can collide across specs, especially with a generic name like ExampleController

A few options:

  1. Much more specific controller name TabNavExampleController
  2. anonymous controller (let(:example_controller_class) { Class.new(ApplicationController)
    • this probably wouldn't play well with the router :[
  3. Delete/Undef the controller class in after the block cleanup? Object.remove_const(:ExampleController)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good call-out. I know RSpec creates its own namespace for each spec, so maybe we can tie into that? Dunno if there's a programmatic way, but maybe it's fine to do manually. Based on some quick local testing:

Suggested change
class ExampleController < ApplicationController; end
class RSpec::ExampleGroups::TabNavigationComponent::ExampleController < ApplicationController; end

Having some trouble with actually getting the routing to respect this, though (capitalization, etc).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Actually, since we don't care about running any code associated with the controller action, and since ViewComponent already assumes the presence of an ApplicationController, maybe it's fine to not define a new controller at all, and use that instead.

See 219bd88

Copy link
Contributor

Choose a reason for hiding this comment

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

even better option!

@aduth aduth merged commit 408f308 into main Jul 18, 2023
@aduth aduth deleted the aduth-tab-navigation-locale-param branch July 18, 2023 12:40
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.

2 participants