use crate::common;
use common::{GitCliHarness, git, init_repo};
use nils_test_support::StubBinDir;
use nils_test_support::cmd::{CmdOutput, run_with};
use std::path::Path;
fn run_with_open_script(
harness: &GitCliHarness,
cwd: &Path,
args: &[&str],
open_script: &str,
) -> CmdOutput {
let stubs = StubBinDir::new();
stubs.write_exe("open", open_script);
let options = harness.cmd_options(cwd).with_path_prepend(stubs.path());
run_with(&harness.git_cli_bin(), args, &options)
}
fn run_with_open_stub(harness: &GitCliHarness, cwd: &Path, args: &[&str]) -> CmdOutput {
run_with_open_script(
harness,
cwd,
args,
r#"#!/bin/bash
set -euo pipefail
exit 0
"#,
)
}
#[test]
fn open_repo_opens_normalized_remote_homepage() {
let harness = GitCliHarness::new();
let dir = init_repo();
git(
dir.path(),
&["remote", "add", "origin", "git@github.com:acme/repo.git"],
);
let output = run_with_open_stub(&harness, dir.path(), &["open", "repo"]);
assert_eq!(output.code, 0);
assert_eq!(output.stderr_text(), "");
assert_eq!(
output.stdout_text(),
"🌐 Opened: https://github.com/acme/repo\n"
);
}
#[test]
fn open_commit_opens_commit_page_for_ref() {
let harness = GitCliHarness::new();
let dir = init_repo();
git(
dir.path(),
&["remote", "add", "origin", "git@github.com:acme/repo.git"],
);
let sha = git(dir.path(), &["rev-parse", "HEAD"])
.trim_end_matches(['\n', '\r'])
.to_string();
let output = run_with_open_stub(&harness, dir.path(), &["open", "commit", "HEAD"]);
assert_eq!(output.code, 0);
assert_eq!(output.stderr_text(), "");
assert_eq!(
output.stdout_text(),
format!("🔗 Opened: https://github.com/acme/repo/commit/{sha}\n")
);
}
#[test]
fn open_file_encodes_path_spaces() {
let harness = GitCliHarness::new();
let dir = init_repo();
git(
dir.path(),
&["remote", "add", "origin", "git@github.com:acme/repo.git"],
);
let output = run_with_open_stub(
&harness,
dir.path(),
&["open", "file", "docs/my file.md", "main"],
);
assert_eq!(output.code, 0);
assert_eq!(output.stderr_text(), "");
assert_eq!(
output.stdout_text(),
"📄 Opened: https://github.com/acme/repo/blob/main/docs/my%20file.md\n"
);
}
#[test]
fn open_actions_rejects_non_github_provider() {
let harness = GitCliHarness::new();
let dir = init_repo();
git(
dir.path(),
&["remote", "add", "origin", "git@gitlab.com:acme/repo.git"],
);
let output = harness.run(dir.path(), &["open", "actions"]);
assert_eq!(output.code, 1);
assert_eq!(output.stdout_text(), "");
assert_eq!(
output.stderr_text(),
"❗ actions is only supported for GitHub remotes.\n"
);
}
#[test]
fn open_repo_headless_environment_prints_clear_manual_open_warning() {
let harness = GitCliHarness::new();
let dir = init_repo();
git(
dir.path(),
&["remote", "add", "origin", "git@github.com:acme/repo.git"],
);
let output = run_with_open_script(
&harness,
dir.path(),
&["open", "repo"],
r#"#!/bin/bash
set -euo pipefail
echo "/usr/bin/open: 882: www-browser: not found" >&2
echo "xdg-open: no method available for opening '$1'" >&2
exit 3
"#,
);
assert_eq!(output.code, 0);
assert_eq!(
output.stdout_text(),
"🔗 URL: https://github.com/acme/repo\n"
);
assert_eq!(
output.stderr_text(),
"⚠️ Could not launch a browser in this environment; open the URL manually.\n"
);
}
#[test]
fn open_repo_non_headless_open_error_still_fails() {
let harness = GitCliHarness::new();
let dir = init_repo();
git(
dir.path(),
&["remote", "add", "origin", "git@github.com:acme/repo.git"],
);
let output = run_with_open_script(
&harness,
dir.path(),
&["open", "repo"],
r#"#!/bin/bash
set -euo pipefail
echo "open: permission denied" >&2
exit 126
"#,
);
assert_eq!(output.code, 126);
assert_eq!(output.stdout_text(), "");
assert_eq!(output.stderr_text(), "open: permission denied\n");
}