nushell/crates/nu-std/tests/test_dirs.nu
Bob Hyman 8e7405bf49
std dirs simply stays in sync with CD changes to PWD (#9267)
# Description
<!--
Thank you for improving Nushell. Please, check our [contributing
guide](../CONTRIBUTING.md) and talk to the core team before making major
changes.

Description of your pull request goes here. **Provide examples and/or
screenshots** if your changes affect the user experience.
-->
Fixes https://github.com/nushell/nushell/issues/9229.
Supersedes #9234

The reported problem was that `shells` list of active shells (a.k.a `std
dirs show` would show an inaccurate active
working directory if user changed it via `cd` command.

The fix here is for the `std dirs` module to let `$env.PWD` mask the
active slot of `$env.DIRS_LIST`. The user is free to invoke CD (or write
to `$env.PWD`) and `std dirs show` will display that as the active
working directory.

When user changes the active slot (via `n`, `p`, `add` or `drop`) `std
dirs` remembers the then current PWD in the about-to-be-vacated active
slot in `$env.DIRS_LIST`, so it is there if you come back to that slot.

# User-Facing Changes
<!-- List of all changes that impact the user experience here. This
helps us keep track of breaking changes. -->
None. It just works™️

# Tests + Formatting
<!--
Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect -A clippy::result_large_err` to check that
you're using the standard code style
- `cargo test --workspace` to check that all tests pass
- `cargo run -- crates/nu-std/tests/run.nu` to run the tests for the
standard library

> **Note**
> from `nushell` you can also use the `toolkit` as follows
> ```bash
> [x] use toolkit.nu # or use an `env_change` hook to activate it
automatically
> toolkit check pr
> ```
-->

# After Submitting
<!-- If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
-->
2023-05-23 06:24:39 -05:00

135 lines
4.4 KiB
Plaintext

use std assert
use std "assert length"
use std "assert equal"
use std "assert not equal"
use std "assert error"
use std "log info"
use std "log debug"
# A couple of nuances to understand when testing module that exports environment:
# Each 'use' for that module in the test script will execute the export def-env block.
# PWD at the time of the `use` will be what the export def-env block will see.
export def setup [] {
# need some directories to play with
let base_path = ($nu.temp-path | path join $"test_dirs_(random uuid)")
let path_a = ($base_path | path join "a")
let path_b = ($base_path | path join "b")
mkdir $base_path $path_a $path_b
{base_path: $base_path, path_a:$path_a, path_b: $path_b}
}
export def teardown [] {
let base_path = $in.base_path
cd $base_path
cd ..
rm -r $base_path
}
def cur_dir_check [expect_dir, scenario] {
log debug $"check dir ($expect_dir), scenario ($scenario)"
assert equal $expect_dir $env.PWD $"expected not PWD after ($scenario)"
}
def cur_ring_check [expect_dir:string, expect_position: int scenario:string] {
log debug $"check ring ($expect_dir), position ($expect_position) scenario ($scenario)"
assert ($expect_position < ($env.DIRS_LIST | length)) $"ring big enough after ($scenario)"
assert equal $expect_position $env.DIRS_POSITION $"position in ring after ($scenario)"
}
export def test_dirs_command [] {
# careful with order of these statements!
# must capture value of $in before executing `use`s
let $c = $in
# must set PWD *before* doing `use` that will run the export def-env block in dirs module.
cd $c.base_path
# must execute these uses for the UOT commands *after* the test and *not* just put them at top of test module.
# the export def-env gets messed up
use std "dirs next"
use std "dirs prev"
use std "dirs add"
use std "dirs drop"
use std "dirs show"
use std "dirs goto"
assert equal [$c.base_path] $env.DIRS_LIST "list is just pwd after initialization"
dirs next
assert equal $c.base_path $env.DIRS_LIST.0 "next wraps at end of list"
dirs prev
assert equal $c.base_path $env.DIRS_LIST.0 "prev wraps at top of list"
dirs add $c.path_b $c.path_a
assert equal $c.path_b $env.PWD "add changes PWD to first added dir"
assert length $env.DIRS_LIST 3 "add in fact adds to list"
assert equal $c.path_a $env.DIRS_LIST.2 "add in fact adds to list"
dirs next 2
# assert (not) equal requires span.start of first arg < span.end of 2nd
assert equal $env.PWD $c.base_path "next wraps at end of list"
dirs prev 1
assert equal $c.path_a $env.PWD "prev wraps at start of list"
cur_dir_check $c.path_a "prev wraps to end from start of list"
dirs drop
assert length $env.DIRS_LIST 2 "drop removes from list"
assert equal $env.PWD $c.path_b "drop changes PWD to previous in list (before dropped element)"
assert equal (dirs show) [[active path]; [false $c.base_path] [true $c.path_b]] "show table contains expected information"
}
export def test_dirs_next [] {
# must capture value of $in before executing `use`s
let $c = $in
# must set PWD *before* doing `use` that will run the export def-env block in dirs module.
cd $c.base_path
assert equal $env.PWD $c.base_path "test setup"
use std "dirs next"
use std "dirs add"
cur_dir_check $c.base_path "use module test setup"
dirs add $c.path_a $c.path_b
cur_ring_check $c.path_a 1 "add 2, but pwd is first one added"
dirs next
cur_ring_check $c.path_b 2 "next to third"
dirs next
cur_ring_check $c.base_path 0 "next from top wraps to bottom of ring"
}
export def test_dirs_cd [] {
# must capture value of $in before executing `use`s
let $c = $in
# must set PWD *before* doing `use` that will run the export def-env block in dirs module.
cd $c.base_path
use std # necessary to define $env.config??
use std "dirs next"
use std "dirs add"
use std "dirs drop"
cur_dir_check $c.base_path "use module test setup"
cd $c.path_b
cur_ring_check $c.path_b 0 "cd with empty ring"
dirs add $c.path_a
cur_dir_check $c.path_a "can add 2nd directory"
cd $c.path_b
cur_ring_check $c.path_b 1 "cd at 2nd item on ring"
dirs next
cur_ring_check $c.path_b 0 "cd updates current position in non-empty ring"
assert equal [$c.path_b $c.path_b] $env.DIRS_LIST "cd updated both positions in ring"
}