#![allow(clippy::unwrap_used)]
use assert_cmd::Command;
use predicates::str::contains;
use std::path::Path;
use tempfile::{tempdir, TempDir};
fn bb_in(dir: &Path) -> Command {
let mut cmd = Command::cargo_bin("bb").unwrap();
cmd.current_dir(dir)
.args(["browse", "--print"])
.env("BB_KEYRING_DISABLE", "1")
.env("NO_COLOR", "1")
.env_remove("BB_REPO")
.env_remove("BB_EMAIL")
.env_remove("BB_TOKEN");
cmd
}
fn git_repo() -> TempDir {
let tmp = tempdir().unwrap();
run_git(tmp.path(), &["init"]);
run_git(tmp.path(), &["config", "user.email", "dev@example.com"]);
run_git(tmp.path(), &["config", "user.name", "Dev Person"]);
tmp
}
fn run_git(dir: &Path, args: &[&str]) {
let status = std::process::Command::new("git")
.current_dir(dir)
.args(args)
.env("GIT_CONFIG_NOSYSTEM", "1")
.env("GIT_TERMINAL_PROMPT", "0")
.status()
.unwrap();
assert!(status.success(), "git {args:?} failed in {dir:?}");
}
#[test]
fn bb_repo_env_var_wins_without_consulting_git() {
let tmp = tempdir().unwrap();
let mut cmd = Command::cargo_bin("bb").unwrap();
cmd.current_dir(tmp.path())
.args(["browse", "--print"])
.env("BB_KEYRING_DISABLE", "1")
.env("NO_COLOR", "1")
.env("BB_REPO", "acme/widgets")
.assert()
.success()
.stdout(contains("https://bitbucket.org/acme/widgets"));
}
#[test]
fn a_whitespace_only_bb_repo_fails_to_parse_as_a_slug() {
let repo = git_repo();
run_git(
repo.path(),
&[
"remote",
"add",
"origin",
"git@bitbucket.org:acme/widgets.git",
],
);
let mut cmd = Command::cargo_bin("bb").unwrap();
cmd.current_dir(repo.path())
.args(["browse", "--print"])
.env("BB_KEYRING_DISABLE", "1")
.env("NO_COLOR", "1")
.env("BB_REPO", " ")
.assert()
.failure()
.stderr(contains("invalid repository"));
}
#[test]
fn outside_a_git_repository_the_error_names_the_repo_flag() {
let tmp = tempdir().unwrap();
bb_in(tmp.path())
.assert()
.failure()
.stderr(contains("no git repository here"))
.stderr(contains("--repo"));
}
#[test]
fn a_repository_with_no_remotes_says_so() {
let repo = git_repo();
bb_in(repo.path())
.assert()
.failure()
.stderr(contains("no git remotes configured"));
}
#[test]
fn a_non_bitbucket_remote_reports_how_many_were_checked() {
let repo = git_repo();
run_git(
repo.path(),
&[
"remote",
"add",
"origin",
"https://github.com/someone/thing.git",
],
);
bb_in(repo.path())
.assert()
.failure()
.stderr(contains("no bitbucket.org remote found (checked 1)"));
}
#[test]
fn an_https_bitbucket_origin_resolves() {
let repo = git_repo();
run_git(
repo.path(),
&[
"remote",
"add",
"origin",
"https://bitbucket.org/acme/widgets.git",
],
);
bb_in(repo.path())
.assert()
.success()
.stdout(contains("https://bitbucket.org/acme/widgets"));
}
#[test]
fn a_bitbucket_remote_other_than_origin_still_resolves() {
let repo = git_repo();
run_git(
repo.path(),
&[
"remote",
"add",
"origin",
"https://github.com/someone/fork.git",
],
);
run_git(
repo.path(),
&[
"remote",
"add",
"upstream",
"git@bitbucket.org:acme/widgets.git",
],
);
bb_in(repo.path())
.assert()
.success()
.stdout(contains("https://bitbucket.org/acme/widgets"));
}
#[test]
fn a_detached_head_is_reported_when_the_source_branch_is_inferred() {
let repo = git_repo();
run_git(
repo.path(),
&[
"remote",
"add",
"origin",
"git@bitbucket.org:acme/widgets.git",
],
);
std::fs::write(repo.path().join("file.txt"), "hello").unwrap();
run_git(repo.path(), &["add", "file.txt"]);
run_git(repo.path(), &["commit", "-m", "initial"]);
run_git(repo.path(), &["checkout", "--detach", "HEAD"]);
Command::cargo_bin("bb")
.unwrap()
.current_dir(repo.path())
.args(["pr", "create", "main"])
.env("BB_KEYRING_DISABLE", "1")
.env("NO_COLOR", "1")
.env("BB_EMAIL", "dev@example.com")
.env("BB_TOKEN", "t0ken-value")
.env("BB_API_BASE", "http://127.0.0.1:1")
.env_remove("BB_REPO")
.assert()
.failure()
.stderr(contains("not a symbolic ref"));
}
#[test]
fn a_remote_with_an_empty_url_is_skipped_rather_than_parsed() {
let repo = git_repo();
run_git(repo.path(), &["config", "remote.origin.url", ""]);
run_git(
repo.path(),
&[
"remote",
"add",
"backup",
"git@bitbucket.org:acme/widgets.git",
],
);
bb_in(repo.path())
.assert()
.success()
.stdout(contains("https://bitbucket.org/acme/widgets"));
}