Skip to content

Commit

Permalink
Test the adding of custom fields via LogStasher
Browse files Browse the repository at this point in the history
The way LogStasher hooks into Rails makes it difficult to test that
configured custom fields actually get added.

It was tricky to find an approach to worked, wasn't too awkward and
wasn't too tightly coupled to LogStasher.

_Notes on some of the esoteric details of these new tests_

`append_info_to_payload`:

This is a Rails instrumentation hook (intended for use by third
parties). It's run during request handling and LogStasher uses it to
"append" its default fields and any custom fields defined by our app.
The visible effect in the context of this method and its caller is that
those LogStasher fields are set on the `payload` hash that was supplied
to the method.

So, invoking this method is enough to simulate a controller action
running for LogStasher's purposes.

And, if the payload hash contains our custom field key (and value, when
there is one), we've defined it successfully.

`logstasher_add_custom_fields_to_payload`:

If a Rails app has defined custom LogStasher fields (with
`LogStasher.add_custom_fields`), LogStasher registers a listener with
Rails that fires whenever a controller is loaded and that listener adds
this method to the loaded controller.

Therefore, if a newly-loaded controller has this method, one or more
LogStasher custom fields have been defined successfully.
  • Loading branch information
aldavidson authored and mike29736 committed Nov 27, 2023
1 parent 3cdb633 commit 9faf031
Showing 1 changed file with 65 additions and 0 deletions.
65 changes: 65 additions & 0 deletions spec/lib/govuk_json_logging_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@
require "govuk_app_config/govuk_json_logging"
require "rack/test"

class TestController < ActionController::Base
include LogStasher::ActionController::Instrumentation
def index; end
end

RSpec.describe GovukJsonLogging do
let(:govuk_headers_class) do
Class.new do
Expand Down Expand Up @@ -78,6 +83,66 @@ def self.headers
expect(fake_stdout.read).to match(/test default log entry/)
end

context "given a block" do
it "evals the block" do
done = false
expect {
GovukJsonLogging.configure do
done = true
end
}.to change { done }.to(true)
end

context "and the block configures custom fields" do
describe "any subsequently-created ActionController" do
let(:headers) { { "REMOTE_ADDR" => "10.10.10.10" } }
let(:mock_request) { ActionDispatch::TestRequest.new(Rack::MockRequest.env_for("http://example.com:8080/", headers)) }
let(:mock_response) { ActionDispatch::TestResponse.new }

before do
GovukJsonLogging.configure do
add_custom_fields do |fields|
fields[:govuk_custom_field] = request.headers["GOVUK-Custom-Header"]
end
end

@controller = TestController.new
allow(@controller).to receive(:request).and_return(mock_request)
allow(@controller).to receive(:response).and_return(mock_response)
end

it "has a logstasher_add_custom_fields_to_payload method" do
expect(@controller.methods).to include(:logstasher_add_custom_fields_to_payload)
end

describe "calling the logstasher_add_custom_fields_to_payload" do
let(:payload) { {} }

it "executes the block" do
expect(@controller).to receive(:logstasher_add_custom_fields_to_payload)
@controller.send(:append_info_to_payload, payload)
end

it "adds the custom fields to the payload" do
@controller.send(:append_info_to_payload, payload)
expect(payload.keys).to include(:govuk_custom_field)
end

context "when the custom field has a value" do
before do
mock_request.headers["GOVUK-Custom-header"] = "My header value"
end

it "sets the custom field value in the payload" do
@controller.send(:append_info_to_payload, payload)
expect(payload[:govuk_custom_field]).to eq("My header value")
end
end
end
end
end
end

describe "when making requests to the application" do
include Rack::Test::Methods

Expand Down

0 comments on commit 9faf031

Please sign in to comment.