Skip to content

Commit

Permalink
test gm commands end to end (#48)
Browse files Browse the repository at this point in the history
related to
- #24 

## description
in order to be able to test the `gm remove` command:
- add `--no-confirm` to `gm remove`

in a new `tests/gm.nu` test module, adds
- a `run-with-env` command to take care of the test environment wrapping
and cleaning
- tests for
  - `gm list`
  - `gm update-cache`
  - `gm status`
  - `gm clone`
  - `gm remove` 
- the true expected errors next to `assert error` in NOTE, for when
we'll be able to check the content of an error in Nushell 😏
  • Loading branch information
amtoine authored Nov 7, 2023
1 parent 0ba1c02 commit 0a7e901
Show file tree
Hide file tree
Showing 2 changed files with 266 additions and 5 deletions.
38 changes: 33 additions & 5 deletions src/nu-git-manager/mod.nu
Original file line number Diff line number Diff line change
Expand Up @@ -245,9 +245,13 @@ export def "gm update-cache" []: nothing -> nothing {
#
# remove a precise repo by giving its full name, a name collision is unlikely
# > gm remove amtoine/nu-git-manager
#
# remove a precise repo without confirmation
# > gm remove amtoine/nu-git-manager --no-confirm
export def "gm remove" [
pattern?: string # a pattern to restrict the choices
--fuzzy # remove after fuzzy-finding the repo(s) to clean
--no-confirm # do not ask for confirmation: useful in scripts but requires a single match
]: nothing -> nothing {
let root = get-repo-store-path
let choices = gm list
Expand All @@ -271,6 +275,29 @@ export def "gm remove" [
},
1 => { $choices | first },
_ => {
if $no_confirm {
if $pattern == null {
error make --unspanned {
msg: (
$"(ansi red_bold)invalid_arguments_and_options(ansi reset):\n"
+ "no search pattern will match all projects and `--no-confirm` won't "
+ "remove multiple directories"
)
}
} else {
throw-error {
msg: "invalid_arguments_and_options"
label: {
text: (
"this pattern is too broad, multiple repos won't be removed by "
+ "`--no-confirm`"
)
span: (metadata $pattern | get span)
}
}
}
}

let prompt = $"please choose a repository to (ansi red)remove(ansi reset)"
let choice = if $fuzzy {
$choices | input list --fuzzy $prompt
Expand All @@ -287,15 +314,16 @@ export def "gm remove" [
},
}

let prompt = $"are you (ansi defu)sure(ansi reset) you want to (ansi red_bold)remove(ansi reset) (ansi yellow)($repo_to_remove)(ansi reset)? "
match (["no", "yes"] | input list $prompt) {
"no" => {
if not $no_confirm {
let prompt = $"are you (ansi defu)sure(ansi reset) you want to (ansi red_bold)remove(ansi reset) (ansi yellow)($repo_to_remove)(ansi reset)? "
if (["no", "yes"] | input list $prompt) == "no" {
log info $"user chose to (ansi green_bold)keep(ansi reset) (ansi yellow)($repo_to_remove)(ansi reset)"
return
},
"yes" => { rm --recursive --force --verbose ($root | path join $repo_to_remove) },
}
}

rm --recursive --force --verbose ($root | path join $repo_to_remove)

let cache_file = get-repo-store-cache-path
check-cache-file $cache_file
remove-from-cache $cache_file ($root | path join $repo_to_remove)
Expand Down
233 changes: 233 additions & 0 deletions tests/gm.nu
Original file line number Diff line number Diff line change
@@ -0,0 +1,233 @@
use std assert

use ../src/nu-git-manager/fs/path.nu ["path sanitize"]
use ../src/nu-git-manager/ *

def run-with-env [code: closure, --prepare-cache] {
# NOTE: for the CI to run, the repos need to live inside `HOME`
let TEST_ENV_BASE = $nu.home-path | path join ".local/share/nu-git-manager/tests" (random uuid)

let TEST_ENV = {
GIT_REPOS_HOME: ($TEST_ENV_BASE | path join "repos"),
GIT_REPOS_CACHE: ($TEST_ENV_BASE | path join "repos.cache"),
}

if $prepare_cache {
with-env $TEST_ENV { gm update-cache }
}

with-env $TEST_ENV $code

rm --recursive --force --verbose $TEST_ENV_BASE
}

export def error-with-empty-store [] {
run-with-env {
# NOTE: the full error:
# ```
# Error: × cache_not_found:
# │ please run `gm update-cache` to create the cache
# ```
assert error { gm list }
}
}

export def cache-update [] {
run-with-env {
gm update-cache
assert equal (gm list) []
}
}

export def clone-invalid-depth [] {
run-with-env --prepare-cache {
# NOTE: full error
# ```
# Error: × invalid_clone_depth
# ╭─[entry #5:1:1]
# 1 │ gm clone https://github.com/amtoine/nu-git-manager --depth 0
# · ┬
# · ╰── clone depth should be strictly positive, found 0
# ╰────
# ```
assert error { gm clone https://github.com/amtoine/nu-git-manager --depth 0 }
}
}

export def clone-depth-1 [] {
run-with-env --prepare-cache {
gm clone https://github.com/amtoine/nu-git-manager --depth 1
assert (
$env.GIT_REPOS_HOME
| path join "github.com/amtoine/nu-git-manager"
| path sanitize
| path exists
)
assert equal (gm list) ["github.com/amtoine/nu-git-manager"]
}
}

export def clone-twice [] {
run-with-env --prepare-cache {
gm clone https://github.com/amtoine/nu-git-manager --depth 1
# NOTE: full error
# ```
# Error: × repository_already_in_store
# ╭─[entry #2:1:1]
# 1 │ gm clone https://github.com/amtoine/nu-git-manager
# · ────────────────────┬────────────────────
# · ╰── this repository has already been cloned by gm
# ╰────
# ```
assert error { gm clone https://github.com/amtoine/nu-git-manager }
}
}

export def clone-full-repo [] {
run-with-env --prepare-cache {
gm clone https://github.com/amtoine/nu-git-manager

let repo = (
$env.GIT_REPOS_HOME | path join "github.com/amtoine/nu-git-manager" | path sanitize
)

let actual = git -C $repo rev-list HEAD | lines | last
let expected = "2ed2d875d80505d78423328c6b2a60522715fcdf"
assert equal $actual $expected
}
}

export def clone-bare [] {
run-with-env --prepare-cache {
gm clone https://github.com/amtoine/nu-git-manager --bare

let repo = $env.GIT_REPOS_HOME | path join "github.com/amtoine/nu-git-manager"

assert ($repo | path join "HEAD" | path sanitize | path exists)
}
}

export def clone-set-remote [] {
run-with-env --prepare-cache {
let url = "https://github.com/amtoine/nu-git-manager"
gm clone $url --remote test-remote-name --fetch https --push ssh

let repo = (
$env.GIT_REPOS_HOME | path join "github.com/amtoine/nu-git-manager" | path sanitize
)

let actual = git -C $repo remote --verbose
| lines
| parse --regex '(?<remote>[-_\w]+)\s+(?<url>.*) \((?<mode>\w+)\)'
| str trim
let expected = [
[remote, url, mode];

[test-remote-name, "https://github.com/amtoine/nu-git-manager", fetch],
[test-remote-name, "ssh://github.com/amtoine/nu-git-manager", push]
]
assert equal $actual $expected
}
}

export def status [] {
run-with-env {
let BASE_STATUS = {
root: {
path: ($env.GIT_REPOS_HOME | path sanitize),
exists: false
},
missing: null,
cache: {
path: ($env.GIT_REPOS_CACHE | path sanitize),
exists: false
},
should_update_cache: false
}

let actual = gm status
let expected = $BASE_STATUS | update should_update_cache true
assert equal $actual $expected

gm update-cache

let actual = gm status
let expected = $BASE_STATUS | update missing [] | update cache.exists true
assert equal $actual $expected

gm clone https://github.com/amtoine/nu-git-manager --depth 1

let actual = gm status
let expected = $BASE_STATUS
| update missing []
| update root.exists true
| update cache.exists true
assert equal $actual $expected

let repo = (
$env.GIT_REPOS_HOME | path join "github.com/amtoine/nu-git-manager" | path sanitize
)
rm $repo --recursive

let actual = gm status
let expected = $BASE_STATUS
| update missing [$repo]
| update root.exists true
| update cache.exists true
| update should_update_cache true
assert equal $actual $expected
}
}

export def remove [] {
run-with-env --prepare-cache {
gm clone https://github.com/amtoine/nu-git-manager --depth 1
gm clone https://github.com/nushell/nupm --depth 1

assert equal (gm list) ["github.com/amtoine/nu-git-manager", "github.com/nushell/nupm"]

# NOTE: true error
# ```
# Error: × no_matching_repository
# ╭─[entry #8:1:1]
# 1 │ gm remove "foo"
# · ──┬──
# · ╰── no repository matching this in .../repos
# ╰────
# ```
assert error { gm remove "not-in-store" --no-confirm }

# NOTE: true error
# ```
# Error: × invalid_arguments_and_options:
# │ no search pattern will match all projects and `--no-confirm` won't remove multiple directories
# ```
assert error { gm remove --no-confirm }

# NOTE: true error
# ```
# Error: × invalid_arguments_and_options
# ╭─[entry #3:1:1]
# 1 │ gm remove github --no-confirm
# · ───┬──
# · ╰── this pattern is too broad, multiple repos won't be removed by `--no-confirm`
# ╰────
# ```
assert error { gm remove "github" --no-confirm }

gm remove "github.com/amtoine/nu-git-manager" --no-confirm
assert not (
$env.GIT_REPOS_HOME
| path join "github.com/amtoine/nu-git-manager"
| path sanitize
| path exists
)
assert equal (gm list) ["github.com/nushell/nupm"]

gm remove "github.com/nushell/nupm" --no-confirm
assert not (
$env.GIT_REPOS_HOME | path join "github.com/nushell/nupm" | path sanitize | path exists
)
assert equal (gm list) []
}
}

0 comments on commit 0a7e901

Please sign in to comment.