Automated Web App Testing With phpStorm

Selenium IDE was a great way to handle automated web app testing like the Store Locator Plus plugins for WordPress.    Selenium IDE is a simple script recorder and playback too that runs on Firefox.    Or, I should say, it used to run on Firefox.  That broke in 2017 when Firefox 52 came out.

After a lot of research I finally found a viable alternative to Selenium IDE that will work with modern browsers.  It is also free, locally installed, and open source. All winning attributes.  Paying for services is not much of an issue so the free part is not a requirement just a “that’s nice” feature.

Web app testing services

I tried several paid alternatives including Browserstack — a paid monthly service that runs virtual desktops and mobile device simulations hosting various browsers. Having to connect to a remote server via proxies or tunnels is a pain.    It also means no testing when offline or when the network is unreliable.    Having multiple browsers is great but 90% of the testing that needs to happen is base functionality which is the same across browsers.    Modern browser are also very good at testing mobile with browser like Safari going beyond simple screen sizing in their mimic of IOS, for example.

Other alternatives included several locally installed proprietary test frameworks.   Nearly every one of them ranges from mediocre to downright horrid.    This is clearly an industry stuck in the 1990s mindset of application development — from the start where you have to fill out a form with all your contact info to be “allowed” to demo the product (and be later harassed by sales people) to the 1980s desktop-centric interfaces.    Many did not work on MacOS.   Those that worked were heavy, bloated, and had a steep learning curve.    Does nobody integrate with my phpStorm, my web app IDE?

It just so happens that the best local testing suite today happens to be free.

The winner?   Selenium Webdriver with a few libraries like WebDriverIO + Mocha + Chai to make things easy.
Read More

WordPress wp_update_plugins Deep Dive

When using a private update service for premium WordPress plugins, some version tests get left behind leaving users with a half-updated plugin stack.   When operating a freemium model, like Store Locator Plus, where the free base plugin may be updated and impact how the premium add ons work having all update notifications arrive at once is critical.     There are times when version 3 of the main plugin will ONLY work with version 2 of a premium add on.    Within Store Locator Plus there are “pre-flight” checks built into both the base plugin and the premium add ons to ensure the entire WordPress site stays running if there is a conflict.
Read More

Using Custom Vagrant Sites For WordPress Development

As with many things in life, I recently learned that I’ve been doing things the hard way when it comes to WordPress development and Vagrant.

I got on the Varying-Vagrant-Vagrants bandwagon years ago.   It made it easy to write my Store Locator Plus code and test it on several different WordPress installations.    Along the way I learned how to provision my test boxes and share code between them.   When VVV 2 came out earlier this year I decided to upgrade.  It did make things easy, but in the early days of limited documentation I followed a few sparse examples and “figure out my own way”.   Of course that turned out to be the hard way of doing things.    I’m going to share with you the shortcuts I learned today to hopefully save you some time.


Read More

WordPress Hooks and Filters Order Of Precedence

When building plugins and themes I often need to reference the WordPress order of precedence of hooks.   This helps ensure various components are loaded only when needed and at the right time.   The base list I reference is the old Codex Plugin API/Action Reference page.   Its sister resource, the Codex Plugin API/Filter Reference is also useful.

The only problem I have with those resources is when I need to determine what will fire on the front-end, backend (admin only) , AJAX, and Cron.    This is my cheat sheet to help sort out the first two (front-end v. admin processing).

WordPress Action Hooks

Stage 1 : Loading

Front EndAdmin Pages
muplugins_loadedmuplugins_loaded
registered_taxonomyregistered_taxonomy
registered_post_typeregistered_post_type
plugins_loadedplugins_loaded
sanitize_comment_cookiessanitize_comment_cookies
setup_themesetup_theme
load_textdomainload_textdomain
after_setup_themeafter_setup_theme
auth_cookie_malformed 
auth_cookie_validauth_cookie_valid
set_current_userset_current_user
initinit
widgets_init *widgets_init *
register_sidebarregister_sidebar
wp_register_sidebar_widgetwp_register_sidebar_widget
wp_default_scripts wp_default_scripts
wp_default_styles wp_default_styles
admin_bar_init admin_bar_init
add_admin_bar_menus add_admin_bar_menus
wp_loaded wp_loaded

Notes

widgets_init is fired by hooking the init action.  It fires at priority 1.

Stage 2 : Processing

After wp_loaded is called, this is where the front end and admin processes diverge.

Front EndAdmin Pages
parse_request
  rest_api_init *conditionally
 auth_redirect
send_headers _admin_menu
parse_query  admin_menu
pre_get_posts  admin_init
posts_selection current_screen
 load-(page)
 send_headers
 pre_get_posts
 posts_selection
wp  wp
template_redirect 
get_header 
wp_enqueue_scripts admin_enqueue_scripts
wp_head 
  admin_print_styles-(hookname)
  admin_print_styles
  admin_print_scripts-(hookname)
  admin_print_scripts
wp_print_scripts  wp_print_scripts
  admin_head-(hookname)
  admin_head
  adminmenu
 in_admin_header
get_search_form admin_notices
 all_admin_notices
loop_start restrict_manage_posts
the_post the_post
get_template_part_content  pre_user_query
loop_end  
get_sidebar  
dynamic_sidebar  
get_search_form  
pre_get_comments  
wp_meta  
get_footer   in_admin_footer
get_sidebar  
wp_footer  admin_footer
wp_print_footer_scripts  
admin_bar_menu  admin_bar_menu
wp_before_admin_bar_render wp_before_admin_bar_render
wp_after_admin_bar_render wp_after_admin_bar_render
  admin_print_footer_scripts
  admin_footer-(hookname)
shutdown shutdown
 wp_dashboard_setup

 

 

Starting Up A Plugin

I use PHP autoloading to eliminate require and include statements throughout the code.   It requires a consistent directory structure and file naming convention.  If you follow PHP best practices this should not be an issue.  I also recommend naming your PHP files after the class they contain and keeping every class in its own file.

Here is an example from my latest side project that sets up the autoloader and loads up the bulk of the plugin code when the WordPress plugins_loaded hook is fired.   It also exits the plugin early if a WordPress heartbeat comes in since this plugin, like 99% of those out there, has no need to listen to the heartbeat and load up all the overhead.

 

Loading Code As Needed

Rather than load up a pile of code into memory when a plugin loads, I prefer to break down my code into classes that are only loaded as needed.   No need to load up all that admin settings page overhead if we are only rendering a shortcode for a user on the front-end.

I use plugins_loaded to fire up my main plugin class and let the construction of that class manage the logic of when to load up the other modules.

 

Front End Only Processing

The main plugin loads a class that runs several methods during construction, adding hooks to admin_menu to load up the admin class when on the back end, testing for Cron or AJAX calls, and checking is_admin() and loaded the front end if NOT running an admin page.

Admin Only Processing

The admin_menu Hook

I often use the admin_menu hook to load up classes that are only needed on admin pages.   My typical structure is to have a controlling MyClass_Admin object which loads via admin_menu and within that add intelligence to the loading by relegating any code that does not have to run during the admin_menu hook into further subclasses such as MyClass_Admin_Init which is loaded up via a method attached to the ‘admin_init’ hook.

I use this method if I do not need to load up features earlier in the call stack (Stage 1 Loading) such as tweaking the admin_bar.

 

The is_admin() Test

This built-in WordPress function can also be used to check if admin pages are being loaded.   I tend to leave this as a sanity check to ensure we are on an admin page within my objects.  This avoids the overhead of calling and is_admin() test on every single page load, though I’ve not yet tested if this is more or less efficient than tying into the admin_menu hook.

I use this method if I need things to happen earlier in the call stack than admin_menu allows such as modifying the admin menu bar.

AJAX Only Processing

I often load this when the main plugin is loaded, which gets invoked via the plugins_loaded hook.    I typically use a method in the class that is loaded to manage the plugin that does a simple AJAX test:

Cron Only Processing

Similar to AJAX, Cron can fire at any time.  It too is managed via plugins_loaded with the main plugin class and has a check for DOING_CRON:

 

 

REST API Process

The REST endpoints need to be configured early in the process. Using the rest_api_init hook is a good place to attach things — but recently I ran into an issue when doing cross-domain REST processing where the endpoints are not connected soon enough.

The REST API invokes rest_api_loaded() via the WP parse_request action hook.

The rest_api_loaded() function lives in rest-api.php. It looks for a query variable named ‘rest_route’ via $GLOBALS[ ‘wp’ ]->query_vars[‘rest_route’]. If set it defines REST_REQUEST as true AND invokes rest_get_server().

Inside the rest_get_server() it will check if the global $wp_rest_server is created, if not it will create it and in the process fire off the rest_api_init hook.

Adding Screen Options To WordPress Admin Pages

Many of the built-in WordPress admin pages have a Screen Options drop-down tab on the top right of the page.   This is used to set how many items are shown in the default WordPress tables, such as the list of pages or posts.   Some of the WordPress admin interfaces also allow you to set which columns to show or hide on the page.

As a plugin or theme author it provides a consistent interface for your users if you utilize this built-in feature as a way to control the admin user experience for your users.   I’ve been busy adding this to the Store Locator Plus Manage Locations interface for version 4.8 and found the documentation to be lacking at best.   Here are my notes on how I hacked this into existence.

The Steps

There are a few basic steps to the process;  Tell WordPress you have screen options you want to track, Save those options when they are changed, Implement those options while rendering the page.

Seems easy enough, but they are all wired together in what is a little less elegant that some of the other components of WordPress Core.  Hopefully these notes will help you get starts on how to do this properly.

Tell WordPress You Have Options

This is done by adding options using the WordPress add_screen_option() method.   It should be called via the WordPress load-<hook> action hook to ensure the proper WP_Screen environment is active when this function is called.

load-{$page_hook} is called from within the base WordPress admin.php call.    This comes AFTER the admin_init hook. Which means your instructions to add screen options to an admin page can come much later than the “Save The Options” code below.   However, you will need to know the page you are hooked into.    Since most admin pages are accessed by adding an entry to the WordPress admin menu, you should be able to store the page hook when calling add_menu_page() or add_submenu_page() to attach your custom admin page to the WordPress admin interface.   This is also a good place to add your hook to setup the screen options.

In this example code I use a named array in $this->menu_items to build a list of several pages I want to add to the admin interface.   It has several properties including the name of the method that will render my page and the name of the method that will add my screen options.    It will also store the hook.     This SLP_AdminUI class is a simple “traffic cop” that loads other classes that do the work so we can isolate code to the specific page being processed.

 

And the page-specific class that does the per-page magic…

Save The Options

Options are saved via the generic ‘set-screen-option’ filter in WordPress.   The option is called via the set_screen_options() function as part of every single WordPress admin.php call.   At least there is top-of-function short circuits that will drop out of the process for a variety of reasons which means the majority of admin pages that do not have screen options will not process much code before moving on.   For those pages that do have screen options, here are the important notes.

You must add the filter to set the screen options by employing the WordPress set-screen-option filter your code.   Since this is fired off very early in the process, basically at the start of WordPress when the admin page is processed, you need to add the filter early in the WordPress feature stack.   Calling it too late, for example inside your WordPress ‘admin_menu’ action hook functions, will not help you.  I’ve hooked my set-screen-options to the WordPress init action.

set-screen-option filter call stack 2017-06-15_09-20-20.png

The call stack an variable references from WordPress Core 4.8 when the set-screen-option filter if applied.

Note: Finding the right point of where to hook your code into WordPress is a key to leveling up your WordPress Foo.   You can find the general order of action hooks on the old-school WordPress Codex.

WordPress Admin Hooks 2017-06-15_09-54-46.png

The filter passes in 3 parameters and you really should be using object-oriented programming techniques so the full call should look something like the code below.  The SLP_Actions init() method is called by the main plugin code via the WordPress init action hook: add_action( ‘init’ , array( $this->Actions , ‘init’ ) ).  The save_screen_options() method in this action class is only a traffic cop; it will load up the proper code module based on what page is being processed by WordPress and call the save_screen_options() method for that specific page.  In this example it is the Manage Locations page.

This SLP_Admin_Locations class is only loaded when the Locations tab is active in the Store Locator Plus plugin.    This ensures less memory is consumed when other WordPress admin pages are loaded and keeps our screen options isolated to just those we are interested in for this page.

If the filter, save_screen_options() of SLP_Admin_Locations in this example, returns a value other than false then the set_screen_options() of WordPress will call

Implement The Options

Implementing the options will depend on  your specific use case.   In my case I’m using the per_page setting to determine how many locations to show in a locations table.  It is a modified version of WP_List_Table so the typical prepare_items() examples do not apply.   In my class I’ve also decided to implement the WP_Screen per_page standard of fetching the user_meta with get_user_option() and fall back to the WP_Screen _options property fallbacks for default values.

Here is the function I call in various places to limit how many locations are shown in my table.

Manage Locations Per Page Option 2017-06-15_15-27-19.png

The Manage Locations per-page screen option in SLP 4.8

Related Notes

Some interesting things I found along the way that may be worth noting…

The default per_page up/down toggle will fire the page update/save (form submit) every time someone clicks the toggle.  Ouch.   Typing a number an clicking the Apply button is a lot less server overhead.

The set-screen-option is a per-user setting.   It is stored in user_meta.    The $option value is the user meta key , and value is the value.     Using serialized options may be a good idea here but it will complicate code.  I’m a big fan of less data I/O, because that is a costly performance hit, over multiple get_option() or user_meta() requests that hammer the database.

The option name ‘per_page’ is super-special.   This single screen option name will alone trigger the Screen Options drop down to be active.   Sadly this is a standalone option in user_meta which means it will force at least TWO data I/O operations if you use this AND any other options (including a serialized option).  Ugggh, WordPress…

The Screen Options drop down will only render if you add a screen option with the name ‘per_page’, the page has meta boxes attached, or you have defined layout columns for the page. From the WP_Screen::show_screen_options() method:

Browsers that disable JavaScript will not see the Screen Options drop-down.  WordPress will apply the hide-if-no-js class which hides elements that depend on JS to work properly.

%d bloggers like this: