Skip to content

Conversation

@vishalkakadiya
Copy link

Add Enqueued_Scripts_Size_Check class

Closes #17

@vishalkakadiya vishalkakadiya marked this pull request as draft February 10, 2023 17:01
Copy link
Member

@felixarntz felixarntz left a comment

Choose a reason for hiding this comment

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

@vishalkakadiya There are a couple things that need iteration here; mostly small things, but a few are critical to be addressed prior to merge (e.g. the modification to the test bootstrap script, and a cleanup routine for globals).

Please see my below feedback.

@felixarntz
Copy link
Member

@jjgrainger @vishalkakadiya Regarding the problem that the test plugin code never runs in the unit tests, the issue is that the test plugin is never actually loaded. And we shouldn't force it to load generally via the test bootstrap file as that would pollute other tests (see my comment in the review above).

Since plugins are only loaded once, very early in the WordPress load cycle, we have to find ways to write test plugins so that they can be loaded on demand in the test suite without polluting global scope.
Here's one idea that could work:

  • We could write every test plugin as a plugin that adds nothing to the global scope that can't be unset (e.g. it's okay to add hooks, or modify a global variable, but it's not okay to introduce functions or classes).
  • Basically this means that every test plugin we write should only ever use closures, never named functions. And all it should do to the global scope is add actions or filters, using closures for the callbacks. This way, everything that the plugin does can be reset without disrupting other subsequent tests.
  • This way, in any test that needs to simulate this plugin being active, we can require the plugin main file (not require_once). As long as it doesn't define any functions or classes, we can load it multiple times, in multiple tests. And any hooks that loading the plugin adds will be reset afterwards (as all WordPress hooks are reset automatically after each test).
  • Of course this wouldn't work as a general requirement for plugins, but since we're only speaking about the test plugins for this repository to use in unit tests, I think that's a reasonable requirement.

Also see my related review feedback above, we should use separate test single-file plugins per individual check that we test, otherwise, if we have a single plugin with all errors, things will get messy and they may conflict with each other. We should be able to change the test plugin with errors that we have so far to make it two separate plugins and have both of those plugins satisfy the above requirements in order not to irrevocably pollute global scope.

@jjgrainger jjgrainger self-assigned this Feb 23, 2023
@jjgrainger jjgrainger marked this pull request as ready for review February 23, 2023 21:12
@jjgrainger
Copy link
Contributor

Thanks @felixarntz the feedback here and the discussions with @joemcgill on Slack have been helpful here!

I've gone over the changes requested and made the updates to the test plugins based on your feedback. This has been helpful in cleaning things up and avoiding issues around loading the plugins for testing.

The changes I've made has got test working but there are a couple of things I want to highlight.

  • When trying to 'activate' the test plugin for this check the Force_Single_Plugin_Preparation would throw an exception because the plugin isn't recognised. This error comes from the validate_plugin() call because the test plugin does not exist in the array returned by get_plugins(). The way I've worked around this is by using the Plugin Checker plugin as the check context as the test plugin file exists within this plugin.
  • After making all the changes I still faced the same issue where the script being enqueued by the test plugin would never end up in the wp_scripts()->done array. To resolve this I have also included the wp_head() and wp_footer() calls along with wp_enqueue_scripts() in the Enqueued_Scripts_Size_Check class. I haven't looked deeper into this to determine if this is the correct approach or there is a different way to resolve this.

Let me know if you have any questions or feedback on this.

Thanks

@jjgrainger jjgrainger changed the title WIP: Add Enqueued_Scripts_Size_Check class Add Enqueued_Scripts_Size_Check class Feb 23, 2023
Comment on lines 172 to 174
wp_enqueue_scripts();
wp_head();
wp_footer();
Copy link
Member

Choose a reason for hiding this comment

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

My main question about this approach is that it can introduce other side effects when all of this is called. I'm also unsure how this accounts for situations where someone is conditionally loading scripts based on some state associated with the URL, like the template type, etc.

Instead of calling wp_head() and wp_footer() directly, you could call WP_Scripts::do_head_items() and WP_Scripts::do_footer_items(), respectively without introducing other side effects if there are other actions hooked to header/footer actions.

Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks @joemcgill I agree it would be cleaner using the WP_Scripts methods you've mentioned. I've updated the PR to use these.

Copy link
Member

Choose a reason for hiding this comment

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

Thanks @jjgrainger. Can you clarify my other question about how the $url is intended to be used in relationship to what scripts are being enqueued?

Copy link
Contributor

Choose a reason for hiding this comment

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

@joemcgill we simulate the URL being requested by modifying the main WP_Query. We have a URL_Aware trait which handles this and provides methods to use within checks. The run method in this check uses those to loop over each of the URLs and run the check logic against each publicly viewable post type and home page. Let me know if you have any other questions.

@jjgrainger jjgrainger removed their assignment Feb 27, 2023
@jjgrainger jjgrainger requested a review from joemcgill February 27, 2023 15:47
Copy link
Member

@joemcgill joemcgill left a comment

Choose a reason for hiding this comment

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

I'm not seeing anything that stands out as a blocker here. I think it will be good to get this merged and do some field analysis on a few known plugins to make sure this performing the way we expect, particularly since mocking state changes to globals can be tricky to account for.

Copy link
Member

@felixarntz felixarntz left a comment

Choose a reason for hiding this comment

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

@vishalkakadiya @jjgrainger This looks great now, thank you for the iterations!

I have a few last bits of feedback here, but it's almost good to merge.

@jjgrainger jjgrainger requested a review from felixarntz March 14, 2023 16:11
@jjgrainger
Copy link
Contributor

Thanks @felixarntz I've updated the PR based on the feedback. This is ready for review

Copy link
Member

@felixarntz felixarntz left a comment

Choose a reason for hiding this comment

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

@jjgrainger Thank you for the updates, LGTM!

@felixarntz felixarntz merged commit 5c6be31 into trunk Mar 14, 2023
@felixarntz felixarntz deleted the feature/add-enqueued_scripts_size_check-class branch March 14, 2023 18:32
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.

Create Enqueued_Scripts_Size_Check

5 participants