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 → ReportWhy 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
Functions
Patches an Elixir script according to the given dependency mode.
Types
@type local_deps() :: LivebookTest.Config.local_deps()
Local dependency mapping
@type patch_mode() :: :remote | :local
Patch mode matching LivebookTest.Config.dependency_mode()
Functions
@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