Skip to content
/ jibe Public

Elixir library for testing that a map/list data structure matches a particular pattern.

License

Notifications You must be signed in to change notification settings

jdl/jibe

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

32 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Jibe

An elixir library for comparing an arbitrarily nested map/list against a pattern.

This is intended as a helper in unit tests, but there's nothing forcing that to be the case. It's just a simple set of elixir functions that could be called from anywhere. Having said that, I use it in a lot of tests and pretty much only in tests.

API Docs

API docs are here

Example

pattern = [:red, :green]

# Partial matches are fine.
Jibe.match?(pattern, [:blue, :red, :purple, :green])
true

# Missing elements are no good though.
# In this case :red was expected and not found.
Jibe.match?(pattern, [:green])
false

# Order matters by deault.
Jibe.match?(pattern, [:green, :red])
false

# Or you don't care about order.
Jibe.match?({:unsorted, pattern}, [:green, :red])
true

The pattern can be an arbitraily nested structure of maps and lists. See the docs for examples using maps, dates, wildcards, and more.

What does this look like in a typical unit test?

I originally made this to help test API results in Phoenix apps. If you don't use Phoenix just imagine that we have a thing that is spewing out JSON, and we'd like to check some or all of our fields. JSON deserialization is external to Jibe. Use Poison or Jason or whatever you want.

# Again, I'm assuming "Phoenix" here, but Jibe doesn't care.

defmodule MyAppWeb.UsersControllerTest do
  use MyApp.ConnCase
  import MyApp.Factory # using `ex_machina` in this case. 
  
  setup do
    fred = insert(:user, first_name: "Fred", last_name: "Flintstone")
    barney = insert(:user, first_name: "Barney", last_name: "Rubble")
    wilma = insert(:user, first_name: "Wilma", last_name: "Flintstone")
    
    conn =
      build_conn()
      # |> whatever else you need to do to set up your conn (login, etc.)
    
    {:ok, conn: conn, users: [fred, barney, wilma]}
  end

  test "index of all users", %{conn: conn, users: [fred, barney, wilma]} do
    data =
      conn
      |> get(users_path(conn, :index))
      |> json_response(200) # JSON is deserialized into Elixir maps/lists here

    # Usually I'll check the shape of one of the results, and then just look for IDs
    # or something smaller than "the entire record" for the rest. This works because 
    # Jibe assumes that your pattern is a subset of the actual data.
    
    # If I know and expect to enforce a particular sort order.
    pattern =
      [
        %{
          "id" => fred.id,
          "first_name" => "Fred",
          "last_name" => "Flintstone"
        },
        %{ "id" => barney.id },
        %{ "id" => wilma.id }
      ]
    assert Jibe.match?(pattern, data)
    
    # If instead I don't care about the sort order.
    # This is slower to execute, but in a small unit test it barely matters.
    pattern =
      {:unsorted, [
        %{
          "id" => fred.id,
          "first_name" => "Fred",
          "last_name" => "Flintstone"
        },
        %{ "id" => barney.id},
        %{ "id" => wilma.id}
      ]}
    assert Jibe.match?(pattern, data)
    
    # Or maybe I only care that "Barney" showed up somewhere in the results, not caring at all about
    # the rest of the list.
    pattern = [ %{"id" => barney.id} ]
    assert Jibe.match?(pattern, data)

  end

Installation

The package can be installed by adding jibe to your list of dependencies in mix.exs:

def deps do
  [
    {:jibe, "~> 0.2.1"}
  ]
end

About

Elixir library for testing that a map/list data structure matches a particular pattern.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages