rubytestingjekylljekyll-extensions

How to Test/Debug Jekyll Plugins?


For a blog, I put together an inline tag that pulls header information from a specified webpage. It works, but I need to add caching, so that I'm not making redundant network calls.

I'd like a tighter debugging cycle than restarting the server and waiting for a rebuild, but running the plugin as Ruby code reports uninitialized constant Liquid (NameError). That makes sense, since it isn't required, and wouldn't run, since the plugin is just a class definition.

So, I tried creating some scaffolding to run the code, or what I thought would be scaffolding, anyway.

require 'liquid'
require_relative '../_plugins/header.rb'

ht = HeaderInlineTag.new
ht.initialize 'header', 'some path'
puts ht.render()

This produces...

_test/header.rb:4:in `<main>': private method `new' called for HeaderInlineTag:Class (NoMethodError)

Considering the possibility that initialize() might be run to create objects, I combined the first two lines of code, but that didn't work, either. Same error, different function name. The plugin doesn't mark anything as private, and declaring the methods public doesn't change anything.

What more is needed to test the plugin without carrying around the entire blog?


Solution

  • The solution was beyond my Ruby knowledge, but mostly straightforward, once I connected the pieces of information floating around.

    First, this existing answer is about a specific issue dealing with Rails, but incidentally shows how to deal with private new methods: Call them through send, as in HeaderInlineTag.send :new.

    Then, this indirect call to .new() now (of course) calls .initialize(), meaning that it needs the three parameters that are required by any plugin. Two parameters are for the testing itself, so they're easy. The third is a parse context. Documentation on writing Jekyll plugins is never clear on what the parse context actually is, since it gets sent automatically as part of the build process. However, some research and testing turns up Liquid::ParseContext as the culprit.

    Finally, .render() also takes the ParseContext value.

    Therefore, the the test scaffold should look something like this.

    require 'liquid'
    require_relative '../_plugins/header.rb'
    
    context = Liquid::ParseContext.new
    ht = HeaderInlineTag.send :new, 'header', 'some path...', context
    puts ht.render context
    

    I can call this from my blog's root folder with ruby _test/header.rb, and it prints the plugin's output. I can now update this script to pull the parameters from the command line or a CSV file, depending on the tests required.