diff --git a/tests/functional/completions.sh b/tests/functional/completions.sh deleted file mode 100644 index 378bd1c15..000000000 --- a/tests/functional/completions.sh +++ /dev/null @@ -1,84 +0,0 @@ -source common.sh - -cd "$TEST_ROOT" - -mkdir -p dep -cat < dep/flake.nix -{ - outputs = i: { }; -} -EOF -mkdir -p foo -cat < foo/flake.nix -{ - inputs.a.url = "path:$(realpath dep)"; - - outputs = i: { - sampleOutput = 1; - }; -} -EOF -mkdir -p bar -cat < bar/flake.nix -{ - inputs.b.url = "path:$(realpath dep)"; - - outputs = i: { - sampleOutput = 1; - }; -} -EOF -mkdir -p err -cat < err/flake.nix -throw "error" -EOF - -# Test the completion of a subcommand -[[ "$(NIX_GET_COMPLETIONS=1 nix buil)" == $'normal\nbuild\t' ]] -[[ "$(NIX_GET_COMPLETIONS=2 nix flake metad)" == $'normal\nmetadata\t' ]] - - -# Test how completion fails if the value cant be parsed as a number -NIX_GET_COMPLETIONS="-" expectStderr 1 nix \ - | grepQuiet "error: Invalid value for environment variable NIX_GET_COMPLETIONS:" - -# Test how completion fails if the number is not a valid index for the number of arguments -NIX_GET_COMPLETIONS=0 expectStderr 1 nix \ - | grepQuiet "error: Invalid word number to get completion for:" -NIX_GET_COMPLETIONS=4 expectStderr 1 nix build a \ - | grepQuiet "error: Invalid word number to get completion for:" - -# Filename completion -[[ "$(NIX_GET_COMPLETIONS=2 nix build ./f)" == $'filenames\n./foo\t' ]] -[[ "$(NIX_GET_COMPLETIONS=2 nix build ./nonexistent)" == $'filenames' ]] - -# Input override completion -[[ "$(NIX_GET_COMPLETIONS=4 nix build ./foo --override-input '')" == $'normal\na\t' ]] -[[ "$(NIX_GET_COMPLETIONS=5 nix flake show ./foo --override-input '')" == $'normal\na\t' ]] -cd ./foo -[[ "$(NIX_GET_COMPLETIONS=3 nix flake update '')" == $'normal\na\t' ]] -cd .. -[[ "$(NIX_GET_COMPLETIONS=5 nix flake update --flake './foo' '')" == $'normal\na\t' ]] -## With multiple input flakes -[[ "$(NIX_GET_COMPLETIONS=5 nix build ./foo ./bar --override-input '')" == $'normal\na\t\nb\t' ]] -## With tilde expansion -[[ "$(HOME=$PWD NIX_GET_COMPLETIONS=4 nix build '~/foo' --override-input '')" == $'normal\na\t' ]] -[[ "$(HOME=$PWD NIX_GET_COMPLETIONS=5 nix flake update --flake '~/foo' '')" == $'normal\na\t' ]] -## Out of order -[[ "$(NIX_GET_COMPLETIONS=3 nix build --override-input '' '' ./foo)" == $'normal\na\t' ]] -[[ "$(NIX_GET_COMPLETIONS=4 nix build ./foo --override-input '' '' ./bar)" == $'normal\na\t\nb\t' ]] - -# Cli flag completion -NIX_GET_COMPLETIONS=2 nix build --log-form | grep -- "--log-format" - -# Config option completion -## With `--option` -NIX_GET_COMPLETIONS=3 nix build --option allow-import-from | grep -- "allow-import-from-derivation" -## As a cli flag – not working atm -# NIX_GET_COMPLETIONS=2 nix build --allow-import-from | grep -- "allow-import-from-derivation" - -# Attr path completions -[[ "$(NIX_GET_COMPLETIONS=2 nix eval ./foo\#sam)" == $'attrs\n./foo#sampleOutput\t' ]] -[[ "$(NIX_GET_COMPLETIONS=4 nix eval --file ./foo/flake.nix outp)" == $'attrs\noutputs\t' ]] -[[ "$(NIX_GET_COMPLETIONS=4 nix eval --file ./err/flake.nix outp 2>&1)" == $'attrs' ]] -[[ "$(NIX_GET_COMPLETIONS=2 nix eval ./err\# 2>&1)" == $'attrs' ]] diff --git a/tests/functional/meson.build b/tests/functional/meson.build index 4fbff5adc..25d0f4933 100644 --- a/tests/functional/meson.build +++ b/tests/functional/meson.build @@ -148,7 +148,6 @@ functional_tests_scripts = [ 'nix-profile.sh', 'suggestions.sh', 'store-ping.sh', - 'completions.sh', 'flakes/show.sh', 'path-from-hash-part.sh', 'toString-path.sh', diff --git a/tests/functional2/cli/__init__.py b/tests/functional2/cli/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/functional2/cli/test_completions.py b/tests/functional2/cli/test_completions.py new file mode 100644 index 000000000..e9bded03f --- /dev/null +++ b/tests/functional2/cli/test_completions.py @@ -0,0 +1,165 @@ +from pathlib import Path +from textwrap import dedent + +import pytest + +from functional2.testlib.fixtures.file_helper import File, with_files, EnvTemplate +from functional2.testlib.fixtures.nix import Nix + +files = { + "dep": {"flake.nix": File("{outputs = i: { };}")}, + "foo": { + "flake.nix": EnvTemplate( + dedent(""" + { + inputs.a.url = "path:@HOME@/dep"; + + outputs = i: { + sampleOutput = 1; + }; + } + """) + ) + }, + "bar": { + "flake.nix": EnvTemplate( + dedent(""" + { + inputs.b.url = "path:@HOME@/dep"; + + outputs = i: { + sampleOutput = 1; + }; + } + """) + ) + }, + "err": {"flake.nix": File('throw "error"')}, +} + + +@pytest.fixture(autouse=True) +def nix_command_feature(nix: Nix): + # "flakes" seems to be the feature actually responsible for + # resolving the completions correctly + # + # Commentator2.0: no clue why... + nix.settings.feature("nix-command", "flakes") + + +def test_completions_valid(nix: Nix): + nix.env.set_env("NIX_GET_COMPLETIONS", "1") + res = nix.nix(["buil"]).run().ok() + assert res.stdout_s == "normal\nbuild\t\n" + + nix.env.set_env("NIX_GET_COMPLETIONS", "2") + res = nix.nix(["flake", "metad"]).run().ok() + assert res.stdout_s == "normal\nmetadata\t\n" + + +def test_completions_invalid_envar(nix: Nix): + nix.env.set_env("NIX_GET_COMPLETIONS", "-") + res = nix.nix([]).run().expect(1) + assert ( + "error: Invalid value for environment variable NIX_GET_COMPLETIONS: -\n" in res.stderr_plain + ) + + +@pytest.mark.parametrize("position", [0, 4]) +def test_completions_invalid_position(nix: Nix, position: int): + nix.env.set_env("NIX_GET_COMPLETIONS", str(position)) + res = nix.nix(["build", "a"]).run().expect(1) + assert f"error: Invalid word number to get completion for: {position}" in res.stderr_plain + + +@with_files({"foo": {}}) +def test_completions_existing_filename(nix: Nix): + nix.env.set_env("NIX_GET_COMPLETIONS", "2") + res = nix.nix(["build", "./f"]).run().ok() + assert res.stdout_s == "filenames\n./foo\t\n" + + +def test_completions_nonexisting_filename(nix: Nix): + nix.env.set_env("NIX_GET_COMPLETIONS", "2") + res = nix.nix(["build", "./nonexistent"]).run().ok() + assert res.stdout_s == "filenames\n" + + +@pytest.mark.parametrize( + ("args", "pos"), + [ + (["build", "./foo", "--override-input", ""], 4), + (["flake", "show", "./foo", "--override-input", ""], 5), + (["flake", "update", "--flake", "./foo", ""], 5), + # tilde expansion + (["build", "~/foo", "--override-input", ""], 4), + (["flake", "update", "--flake", "~/foo", ""], 5), + # Out of order + (["build", "--override-input", "", "", "./foo"], 3), + ], +) +@with_files(files) +def test_completions_input_override(nix: Nix, args: list[str], pos: int): + nix.env.set_env("NIX_GET_COMPLETIONS", str(pos)) + res = nix.nix(args).run().ok() + assert res.stdout_s == "normal\na\t\n" + + +@pytest.mark.parametrize( + ("args", "pos"), + [ + (["build", "./foo", "./bar", "--override-input", ""], 5), + (["build", "./foo", "--override-input", "", "", "./bar"], 4), + ], +) +@with_files(files) +def test_completions_multiple_input_flakes(nix: Nix, args: list[str], pos: int): + nix.env.set_env("NIX_GET_COMPLETIONS", f"{pos}") + res = nix.nix(args).run().ok() + assert res.stdout_s == "normal\na\t\nb\t\n" + + +@with_files(files) +def test_completions_flake_update(nix: Nix, files: Path): + cwd = files / "foo" + nix.env.set_env("NIX_GET_COMPLETIONS", "3") + cmd = nix.nix(["flake", "update", ""]) + cmd.cwd = cwd + res = cmd.run().ok() + assert res.stdout_s == "normal\na\t\n" + + +def test_flag_completion(nix: Nix): + nix.env["NIX_GET_COMPLETIONS"] = "2" + res = nix.nix(["build", "--log-form"]).run().ok() + assert "--log-format" in res.stdout_plain + assert "Set the format of log output; one of" in res.stdout_plain + + +def test_option_completion(nix: Nix): + nix.env["NIX_GET_COMPLETIONS"] = "3" + res = nix.nix(["build", "--option", "allow-import-"]).run().ok() + assert "allow-import-from-derivation" in res.stdout_plain + + +@pytest.mark.skip("SKIP(Hufschmitt 2022-07): Options as CLI-flags currently don't have completions") +def test_option_cli_flag_completion(nix: Nix): + nix.env["NIX_GET_COMPLETIONS"] = "2" + res = nix.nix(["build", "--allow-import-from"]).run().ok() + assert "allow-import-from-derivation" in res.stdout_plain + + +@pytest.mark.parametrize( + ("args", "pos", "exp"), + [ + (["./foo#sam"], 2, "attrs\n./foo#sampleOutput\t\n"), + (["./err#"], 2, "attrs\n"), + (["--file", "./foo/flake.nix", "outp"], 4, "attrs\noutputs\t\n"), + (["--file", "./err/flake.nix", "outp"], 4, "attrs\n"), + ], +) +@with_files(files) +def test_valid_attr_path_completion(nix: Nix, args: list[str], pos: int, exp: str): + nix.env["NIX_GET_COMPLETIONS"] = f"{pos}" + res = nix.nix(["eval", *args]).run().ok() + assert res.stdout_s == exp