Files
lix/tests/functional2/cli/test_completions.py
T
Rebecca Turnerandrootile cb34b56fea tests/functional2: Fix Python LSP by adjusting imports
See: cl/4840

When importing Python modules, we include `functional2` in the module
path, like this:

    from functional2.testlib.fixtures.env import ManagedEnv

This means that python expects to see a file like
`functional2/testlib/fixtures/env.py`. We run `pytest` from `tests/` in
the `justfile` and have `tests/functional2/__init__.py` so `pytest` in
`meson` is able to find these imports.

However, language servers generally consider the `pyproject.toml` to be
the project root, so (e.g.) `pyright` is unable to follow any of the
`functional2` imports, leading to lots of spurious errors.

In cl/4840 I moved `tests/functional2/pyproject.toml` to
`tests/pyproject.toml`, which worked but was considered aesthetically
unappealing.

This diff is much larger but it's a more elegant solution.

Change-Id: I2983c7b87f88f59a4e3521451a9f5acd6a6a6964
2026-01-23 15:06:51 +01:00

166 lines
5.0 KiB
Python

from pathlib import Path
from textwrap import dedent
import pytest
from testlib.fixtures.file_helper import File, with_files, EnvTemplate
from 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", "--dry"]).run().ok()
assert "--dry-run" in res.stdout_plain
assert "Show what this command would do without doing it" 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