use super::render_go_mod;
#[test]
fn render_go_mod_without_extras() {
let out = render_go_mod("github.com/example/mylib", None, "v1.0.0", None, None);
assert!(
out.contains("github.com/example/mylib v1.0.0"),
"should contain main module require"
);
assert!(
out.contains("github.com/stretchr/testify v1.11.1"),
"should contain testify require"
);
assert!(
!out.contains("github.com/tree-sitter"),
"should not contain tree-sitter without extras"
);
}
#[test]
fn render_go_mod_includes_testify_indirect_deps() {
let out = render_go_mod("github.com/example/mylib", None, "v1.0.0", None, None);
for indirect in [
"github.com/davecgh/go-spew v1.1.1 // indirect",
"github.com/pmezard/go-difflib v1.0.0 // indirect",
"gopkg.in/yaml.v3 v3.0.1 // indirect",
] {
assert!(
out.contains(indirect),
"go.mod must contain testify indirect dep `{indirect}`, got:\n{out}"
);
}
}
#[test]
fn render_go_mod_registry_mode_uses_sibling_module_path() {
let out = render_go_mod("github.com/example/mylib", None, "v1.0.0", None, None);
assert!(
out.contains("module github.com/example/mylib-e2e"),
"registry-mode main module must be a sibling path, got: {out}"
);
assert!(
!out.contains("module github.com/example/mylib/e2e"),
"registry-mode main module must not shadow the module under test, got: {out}"
);
}
#[test]
fn render_go_mod_local_mode_uses_nested_module_path() {
let out = render_go_mod(
"github.com/example/mylib",
Some("../../packages/go"),
"v0.0.0",
None,
None,
);
assert!(
out.contains("module github.com/example/mylib/e2e"),
"local-mode main module should stay nested, got: {out}"
);
}
#[test]
fn render_go_mod_with_extras_includes_requires() {
use crate::core::config::manifest_extras::{ExtraDepSpec, ManifestExtras};
let mut extras = ManifestExtras::default();
extras.dev_dependencies.insert(
"github.com/tree-sitter/go-tree-sitter".to_string(),
ExtraDepSpec::Simple("v0.24.0".to_string()),
);
let out = render_go_mod("github.com/example/mylib", None, "v1.0.0", Some(&extras), None);
assert!(
out.contains("github.com/tree-sitter/go-tree-sitter v0.24.0"),
"should include tree-sitter extra, got: {out}"
);
assert!(
out.contains("github.com/example/mylib v1.0.0"),
"should still contain main module"
);
}
#[test]
fn render_go_mod_extras_with_replace_directive() {
use crate::core::config::manifest_extras::{ExtraDepSpec, ManifestExtras};
let mut extras = ManifestExtras::default();
extras.dependencies.insert(
"github.com/upstream/lib".to_string(),
ExtraDepSpec::Simple("v0.5.0".to_string()),
);
let out = render_go_mod(
"github.com/example/mylib",
Some("../../packages/go"),
"v0.0.0",
Some(&extras),
None,
);
assert!(
out.contains("github.com/upstream/lib v0.5.0"),
"should include upstream lib"
);
assert!(
out.contains("replace github.com/example/mylib => ../../packages/go"),
"should include replace directive"
);
}
#[test]
fn render_go_mod_empty_extras_matches_no_extras() {
use crate::core::config::manifest_extras::ManifestExtras;
let extras = ManifestExtras::default();
let without_empty = render_go_mod("github.com/example/mylib", None, "v1.0.0", None, None);
let with_empty = render_go_mod("github.com/example/mylib", None, "v1.0.0", Some(&extras), None);
assert_eq!(without_empty, with_empty, "empty extras should be equivalent to None");
}
#[test]
fn render_go_mod_extras_are_sorted_deterministically() {
use crate::core::config::manifest_extras::{ExtraDepSpec, ManifestExtras};
let mut extras = ManifestExtras::default();
extras.dev_dependencies.insert(
"github.com/z-last/lib".to_string(),
ExtraDepSpec::Simple("v1.0.0".to_string()),
);
extras.dev_dependencies.insert(
"github.com/a-first/lib".to_string(),
ExtraDepSpec::Simple("v2.0.0".to_string()),
);
extras.dependencies.insert(
"github.com/m-middle/lib".to_string(),
ExtraDepSpec::Simple("v3.0.0".to_string()),
);
let out = render_go_mod("github.com/example/mylib", None, "v1.0.0", Some(&extras), None);
let first_idx = out.find("github.com/a-first/lib").expect("should find a-first");
let middle_idx = out.find("github.com/m-middle/lib").expect("should find m-middle");
let last_idx = out.find("github.com/z-last/lib").expect("should find z-last");
assert!(
first_idx < middle_idx && middle_idx < last_idx,
"extras should be sorted alphabetically: {out}"
);
}
#[test]
fn render_go_mod_extras_handles_detailed_form_with_version() {
use crate::core::config::manifest_extras::{ExtraDepSpec, ManifestExtras};
let mut extras = ManifestExtras::default();
let mut table = toml::Table::new();
table.insert("version".to_string(), toml::Value::String("v0.25.0".to_string()));
table.insert("features".to_string(), toml::Value::String("debug".to_string()));
extras.dev_dependencies.insert(
"github.com/example/with-features".to_string(),
ExtraDepSpec::Detailed(table),
);
let out = render_go_mod("github.com/example/mylib", None, "v1.0.0", Some(&extras), None);
assert!(
out.contains("github.com/example/with-features v0.25.0"),
"should extract version from detailed form, got: {out}"
);
}
#[test]
fn render_go_mod_extras_skips_entries_without_version() {
use crate::core::config::manifest_extras::{ExtraDepSpec, ManifestExtras};
let mut extras = ManifestExtras::default();
let mut table = toml::Table::new();
table.insert(
"git".to_string(),
toml::Value::String("https://example.com".to_string()),
);
extras.dev_dependencies.insert(
"github.com/example/no-version".to_string(),
ExtraDepSpec::Detailed(table),
);
let out = render_go_mod("github.com/example/mylib", None, "v1.0.0", Some(&extras), None);
assert!(
!out.contains("github.com/example/no-version"),
"should skip extras without version field, got: {out}"
);
}
#[test]
fn render_go_mod_extras_idempotent() {
use crate::core::config::manifest_extras::{ExtraDepSpec, ManifestExtras};
let mut extras = ManifestExtras::default();
extras.dev_dependencies.insert(
"github.com/tree-sitter/go-tree-sitter".to_string(),
ExtraDepSpec::Simple("v0.24.0".to_string()),
);
let first = render_go_mod("github.com/example/mylib", None, "v1.0.0", Some(&extras), None);
let second = render_go_mod("github.com/example/mylib", None, "v1.0.0", Some(&extras), None);
assert_eq!(first, second, "re-rendering with same extras should be stable");
}
#[test]
fn render_go_mod_direct_require_block_is_alphabetical() {
let out = render_go_mod(
"github.com/xberg-io/tree-sitter-language-pack/packages/go",
None,
"v1.16.2",
None,
None,
);
let testify_idx = out
.find("github.com/stretchr/testify")
.expect("should contain testify require");
let module_idx = out
.find("github.com/xberg-io/tree-sitter-language-pack/packages/go v1.16.2")
.expect("should contain module require");
assert!(
testify_idx < module_idx,
"testify must sort before the xberg module in the direct require block, got:\n{out}"
);
}
#[test]
fn render_go_mod_merges_dependency_go_mod_indirect_requires() {
let dir = tempfile::tempdir().expect("create temp dir");
std::fs::write(
dir.path().join("go.mod"),
"module github.com/xberg-io/tree-sitter-language-pack/packages/go\n\n\
go 1.26\n\n\
require github.com/tree-sitter/go-tree-sitter v0.25.0\n\n\
require github.com/mattn/go-pointer v0.0.1 // indirect\n",
)
.expect("write fixture go.mod");
let out = render_go_mod(
"github.com/xberg-io/tree-sitter-language-pack/packages/go",
Some("../../packages/go"),
"v1.16.2",
None,
Some(dir.path()),
);
let testify_idx = out
.find("github.com/stretchr/testify")
.expect("should contain testify require");
let module_idx = out
.find("github.com/xberg-io/tree-sitter-language-pack/packages/go v1.16.2")
.expect("should contain module require");
assert!(
testify_idx < module_idx,
"testify must sort before the xberg module, got:\n{out}"
);
let expected_indirect_order = [
"github.com/davecgh/go-spew v1.1.1 // indirect",
"github.com/mattn/go-pointer v0.0.1 // indirect",
"github.com/pmezard/go-difflib v1.0.0 // indirect",
"github.com/tree-sitter/go-tree-sitter v0.25.0 // indirect",
"gopkg.in/yaml.v3 v3.0.1 // indirect",
];
let mut last_idx = None;
for indirect in expected_indirect_order {
let idx = out
.find(indirect)
.unwrap_or_else(|| panic!("go.mod must contain indirect dep `{indirect}`, got:\n{out}"));
if let Some(last) = last_idx {
assert!(last < idx, "indirect block out of alphabetical order, got:\n{out}");
}
last_idx = Some(idx);
}
}
#[test]
fn render_go_mod_excludes_extra_that_duplicates_dependency_direct_require() {
use crate::core::config::manifest_extras::{ExtraDepSpec, ManifestExtras};
let dir = tempfile::tempdir().expect("create temp dir");
std::fs::write(
dir.path().join("go.mod"),
"module github.com/xberg-io/tree-sitter-language-pack/packages/go\n\n\
go 1.26\n\n\
require github.com/tree-sitter/go-tree-sitter v0.25.0\n\n\
require github.com/mattn/go-pointer v0.0.1 // indirect\n",
)
.expect("write fixture go.mod");
let mut extras = ManifestExtras::default();
extras.dev_dependencies.insert(
"github.com/tree-sitter/go-tree-sitter".to_string(),
ExtraDepSpec::Simple("v0.25.0".to_string()),
);
let out = render_go_mod(
"github.com/xberg-io/tree-sitter-language-pack/packages/go",
Some("../../packages/go"),
"v0.0.0",
Some(&extras),
Some(dir.path()),
);
let occurrences = out.matches("github.com/tree-sitter/go-tree-sitter").count();
assert_eq!(
occurrences, 1,
"go-tree-sitter must appear exactly once (direct, not also indirect), got:\n{out}"
);
assert!(
!out.contains("github.com/tree-sitter/go-tree-sitter v0.25.0 // indirect"),
"go-tree-sitter is already a direct require and must not also be `// indirect`, got:\n{out}"
);
assert!(
out.contains("github.com/mattn/go-pointer v0.0.1 // indirect"),
"go-pointer (only indirect) should still be included, got:\n{out}"
);
}
#[test]
fn render_go_mod_dependency_with_no_extra_requires_matches_testify_only() {
let dir = tempfile::tempdir().expect("create temp dir");
std::fs::write(
dir.path().join("go.mod"),
"module github.com/xberg-io/example/packages/go\n\ngo 1.26\n",
)
.expect("write fixture go.mod");
let with_dependency_dir = render_go_mod(
"github.com/xberg-io/example/packages/go",
Some("../../packages/go"),
"v1.0.0",
None,
Some(dir.path()),
);
let without_dependency_dir = render_go_mod(
"github.com/xberg-io/example/packages/go",
Some("../../packages/go"),
"v1.0.0",
None,
None,
);
assert_eq!(
with_dependency_dir, without_dependency_dir,
"a dependency go.mod with no requires must not change the testify-only indirect output"
);
for indirect in [
"github.com/davecgh/go-spew v1.1.1 // indirect",
"github.com/pmezard/go-difflib v1.0.0 // indirect",
"gopkg.in/yaml.v3 v3.0.1 // indirect",
] {
assert!(
with_dependency_dir.contains(indirect),
"should still contain testify indirect `{indirect}`, got:\n{with_dependency_dir}"
);
}
}