-
Notifications
You must be signed in to change notification settings - Fork 21
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
Update layout_for_admin component to take custom asset filenames #3993
Conversation
6949cf1
to
0b29cbc
Compare
0b29cbc
to
35070cd
Compare
35070cd
to
77e9db0
Compare
77e9db0
to
ba61613
Compare
ba61613
to
08f5ded
Compare
08f5ded
to
4244ec3
Compare
4244ec3
to
232d27b
Compare
232d27b
to
66e2a21
Compare
66e2a21
to
fa4037c
Compare
c4ae73e
to
3f29ecb
Compare
3f29ecb
to
caed1b4
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great stuff David 👍
caed1b4
to
2f39828
Compare
2f39828
to
d71638d
Compare
d71638d
to
92649fb
Compare
92649fb
to
c413dca
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great, all the changes look good to me. Only thing I remembered to suggest is that we should add some information in the commit message about how we ended up committing the sin of using (allow|expect)_any_instance_of
and how we ended up stubbing ActiveView::Base - as there is quite opaque.
It'd be good to get a nod from @andysellick or one of the frontend devs on our team before merging though
Yea great shout. Sorry i was using CI to run my tests as i was having issues locally and forgot to update the commit message. I'll sort that now 👍 |
c413dca
to
8c76f06
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Change looks good, just a few comments/questions 👍
environment: production | ||
product_name: Publishing | ||
browser_title: 'A page title' | ||
js_filename: "application" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These examples pass the default value, would it be clearer to show this functionality in action?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The problem with that is that i'd have to add a blank admin
stylesheet, because it will actually try to compile the file. So it if update it to use "admin" it'll look for "admin.js" and blow up if it can't find it.
I figured this was the lesser of 2 evils, but let me know if you'd prefer another approach 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh I see that makes sense. Tricky! In that case maybe add a description to these examples to clarify? Something like:
description: An alternative JS filename can be used in place of the default `application.js` if required (note that this cannot easily be demonstrated here).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
great shout. Thanks Andy will sort that now
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, description
needs to be added at the top level, underneath the example name, e.g.
with_custom_js_filename:
description: etc.
data:
environment: production
It should appear in the component guide if you want to check it.
@@ -16,4 +16,25 @@ def component_name | |||
|
|||
assert_select 'meta[name="robots"][content="noindex,nofollow,noimageindex"]', visible: false | |||
end | |||
|
|||
it "can receive a custom js filename" do | |||
allow_any_instance_of(ActionView::Base).to receive(:javascript_include_tag) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again just interested to know how this works - why does the JS test have allow_any_instance_of
and expect_any_instance_of
, but the CSS test only has expect_any_instance_of
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similar to above, the reason we're unable to make an assertion on the page is that it will blow up while trying to render the component if it's unable to find the file based on filename passed into the component.
Due to that we have to stub out the method that handles the compilation of the assets. It feels like in this situation the thing we really care about is that the correct file is being included.
How allow and expect is that they stub out the method for the class passed in and return "" (by default).
So essentially what happens here is that the layout makes the call to compile admin.js
and we intercept that call and return an empty string. Blocking it from actually trying to compile and blowing up.
The reason that we need allow_any_instance_of
in the JS test is due to there being a second method call here
So two calls are made:
<%= javascript_include_tag "govuk_publishing_components/vendor/modernizr" %>
then
<%= javascript_include_tag "application" %>
Without the allow this line
expect_any_instance_of(ActionView::Base).to receive(:javascript_include_tag).with("admin").once
blows up because the javascript_include_tag
method has been stubbed, but only once with expectation that the argument will be "admin".
The output of the test is something similar to
expected javascript_include_tag with the argument of "admin", but it was actually "govuk_publishing_components/vendor/modernizr"
The allow
allows the method to be called with any argument any amount of times which ensures we don't see the error above. While the expect is checking that the call is made with "admin" once which is the desired out come
Hopefully that makes sense.
Maybe it's clearer if i update the allow to be more explicit and do
allow_any_instance_of(ActionView::Base).to receive(:javascript_include_tag).with("govuk_publishing_components/vendor/modernizr")
expect_any_instance_of(ActionView::Base).to receive(:javascript_include_tag).with("admin").once
So it's clear that the allow is due to the method being called twice, once with a file we're not worried about with our change to the implementation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are other approaches we could use like dynamically creating an empty admin.js
file before action before running the test, testing what's in the file, then deleting it after running the test, but that comes with it's own setbacks. Still complex, far slower etc.
But happy to chat it through if you'd like!
I'll go back and update the commit message with some of the above.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Really interesting stuff, thanks for taking the time to explain 👍
8c76f06
to
705bb9b
Compare
705bb9b
to
2ac5402
Compare
2ac5402
to
98f1098
Compare
@andysellick i've made the requested changes. Hopefully the above explanation makes sense. Let me know if you not and/or you want any other changes 👍 |
We're adding an admin interface to our application and want to use retain application.js & application.scss for the public interface. This will allow us to pass admin.js and admin.scss in as args so we can retain only loading the required components for each so the page load time is fast. There has been some added complexity in testing this as the #javascript_include_tag and #stylesheet_link_tag methods being passed a filename that isn't present in the assets directory will raise an error due to the file not being found when it's during attempted compilation. We have a few options here: 1. stub out the methods and return an empty string so there is no attempt to compile the file. In this situation we would just want to check that the methods receive the correct filename. 2. create the files dynamically prior to running the test, check the output on the rendered page and then delete the files after the test has run. 3. skip the test entirely. We've opted for option 1 as probably less complex and faster than option 2 and preferable to not testing at all. Unfortunately we've had to use "allow_any_instance_of" and "expect_any_instance_of" to stub the calls to check that the JS and CSS filenames are being passed into the #javascript_include_tag and #stylesheet_link_tag methods. These are implemeneted in the ActionView::Helpers::AssetTagHelper helper which is included in ActionView::Base which is particularly gnarly to attempt to stub a single instance of. While this isn't ideal, it's probably preferable to having to stub out a series of objects for what is essentially a very simple test which checks the correct filename is passed in.
98f1098
to
5ba7778
Compare
I've tested it's working as expected on the component guide so i'll merge if there's no objections |
- Update layout_for_admin component to take custom asset filenames PR #3993
What
Allow custom JS and CSS filenames to be passed to the layout_for_admin component.
Why
We're adding an admin interface to our application and want to use retain application.js & application.scss for the public interface.
This will allow us to pass admin.js and admin.scss in as args so we can retain only loading the required components for each so the page load time is fast.
Visual Changes
N/A
Testing
It was a bit awkward to test this as passing it a filename that doesn't exist causes exceptions. Using any_instance_of is a bit of a smell, but it's probs okay(ish) here to avoid additional complexity.
Trello card
https://trello.com/c/r6uafy2D/1354-basic-admin-area