LivebookTest.DependencyPatcher (livebook_test v0.1.0)

Copy Markdown View Source

Rewrites Mix.install dependency declarations for local testing.

This is the core feature of LivebookTest and the third stage in the pipeline:

Discovery  Exporter  **DependencyPatcher**  Runner  Report

Why dependency patching matters

Livebook notebooks are standalone documents. They declare their dependencies using Mix.install/2 with Hex version specifiers:

Mix.install([
  {:my_lib, "~> 0.5"}
])

When testing notebooks as part of a project's CI pipeline, you want those notebooks to use the current checkout of my_lib, not the published Hex version. This module rewrites the dependency declarations to use local paths instead.

Modes

  • Remote (:remote) — leave the script untouched
  • Local (:local) — rewrite Hex deps to local path deps

How patching works

The patcher operates on the exported Elixir script (not the .livemd), using regex-based replacement to rewrite Mix.install calls:

# Before (remote)
Mix.install([{:my_lib, "~> 0.5"}])

# After (local)
Mix.install([{:my_lib, path: "."}])

Summary

Types

Local dependency mapping

Patch mode matching LivebookTest.Config.dependency_mode()

Functions

Patches an Elixir script according to the given dependency mode.

Types

local_deps()

@type local_deps() :: LivebookTest.Config.local_deps()

Local dependency mapping

patch_mode()

@type patch_mode() :: :remote | :local

Patch mode matching LivebookTest.Config.dependency_mode()

Functions

patch(script, atom, local_deps)

@spec patch(String.t(), patch_mode(), local_deps()) :: String.t()

Patches an Elixir script according to the given dependency mode.

In :remote mode, the script is returned unchanged. In :local mode, dependency declarations within Mix.install are rewritten to use local paths.

Examples

iex> script = "Mix.install([{:ex_arrow, "~> 0.5"}])"
iex> LivebookTest.DependencyPatcher.patch(script, :remote, [])
"Mix.install([{:ex_arrow, "~> 0.5"}])"

iex> script = "Mix.install([{:ex_arrow, "~> 0.5"}])"
iex> patched = LivebookTest.DependencyPatcher.patch(script, :local, ex_arrow: ".")
iex> String.contains?(patched, "path:")
true