Skip to main content
Glama

Jinni: Bring Your Project Into Context

by smat-dev
test_integration_cli.py15.6 kB
from pathlib import Path from conftest import run_jinni_cli, CONTEXT_FILENAME # Import helper and constant import pytest # Import pytest for fixture usage if needed later # --- CLI Tests (Synchronous) --- def test_cli_with_contextfiles(test_environment: Path): """Test CLI run respecting hierarchical .contextfiles (dynamic rule application).""" test_dir = test_environment # Run with the project directory as the root, no specific target stdout, stderr = run_jinni_cli(["-r", str(test_dir), "--no-copy"]) # Expected includes based on conftest.py setup and dynamic rules: # Root .contextfiles: file_root.txt, *.md, src/, dir_c/, dir_e/, dir_f/, !*.log, !*.tmp # dir_a .contextfiles: *.txt, !file_a1.txt, important.log, !local.md # dir_c .contextfiles: !*.data # dir_e .contextfiles: !last_rule.txt # Defaults exclude: .*, build/, etc. # Check included content assert "```path=file_root.txt" in stdout assert "Root file content" in stdout assert "```path=README.md" in stdout assert "# Readme" in stdout assert "```path=main.py" in stdout # Included by default '*' assert "```path=src/app.py" in stdout # Included via root src/ assert "print('app')" in stdout assert "```path=src/utils.py" in stdout # Included via root src/ assert "def helper(): pass" in stdout assert "```path=src/nested/deep.py" in stdout # Included via root src/ assert "# Deep" in stdout assert "```path=dir_a/important.log" in stdout # Included by local override of root !*.log assert "Important Log Content" in stdout assert "```path=dir_c/file_c1.txt" in stdout # Included via root dir_c/ assert "Content C1" in stdout assert "```path=dir_f/file_f.txt" in stdout # Included via root dir_f/ assert "```path=docs/index.md" in stdout # Included via root *.md assert "```path=docs/config/options.md" in stdout # Included via root *.md # Check excluded content assert "root.log" not in stdout # Excluded by root !*.log assert "temp.tmp" not in stdout # Excluded by root !*.tmp assert ".hidden_root_file" not in stdout # Excluded by default .* assert "binary_file.bin" not in stdout # Binary file assert "dir_a/file_a1.txt" not in stdout # Excluded locally by !file_a1.txt assert "dir_a/file_a2.log" not in stdout # Excluded by root !*.log assert "dir_a/local.md" not in stdout # Excluded locally by !local.md assert "```path=dir_b/file_b1.py" in stdout # dir_b included by default '*' assert "```path=dir_b/sub_dir_b/include_me.txt" in stdout # dir_b included by default '*' assert "dir_c/file_c2.data" not in stdout # Excluded locally by !*.data assert "```path=dir_d/file_d.txt" in stdout # dir_d included by default '*' assert "dir_e/last_rule.txt" not in stdout # Excluded locally by !last_rule.txt assert "src/config.log" not in stdout # Excluded by root !*.log assert "src/nested/data.log" not in stdout # Excluded by root !*.log assert ".hidden_dir" not in stdout # Excluded by default .* assert "```path=.contextfiles" not in stdout # Excluded by default .* assert "build/" not in stdout # Excluded by default build/ assert stderr.strip() == "" def test_cli_list_only(test_environment: Path): """Test the --list-only CLI flag with dynamic rules.""" test_dir = test_environment stdout, stderr = run_jinni_cli(["-r", str(test_dir), "--list-only", "--no-copy"]) expected_files = sorted([ "README.md", "file_root.txt", "main.py", # Included by default '*' "dir_a/important.log", "dir_b/file_b1.py", # Included by default '*' "dir_b/sub_dir_b/include_me.txt", # Included by default '*' "dir_c/file_c1.txt", # .contextfiles in dir_c should be excluded by default "dir_d/file_d.txt", # Included by default '*' "dir_f/file_f.txt", # .contextfiles in dir_f should be excluded by default "lib/somelib.py", # Included by default '*' now that it exists "src/app.py", # .hidden_in_src should be excluded by default "src/nested/deep.py", "src/utils.py", "docs/index.md", "docs/config/options.md", "src/nested/other.txt", # Add missing file ]) actual_files = sorted([line.strip() for line in stdout.strip().splitlines()]) assert actual_files == expected_files, f"Expected {expected_files}, got {actual_files}" assert stderr.strip() == "" def test_cli_overrides(test_environment: Path): # Renamed from test_cli_global_config """Test the --overrides CLI flag.""" test_dir = test_environment overrides_path = test_dir / "override.rules" overrides_path.write_text( "# Override Rules\n" "**/*.py\n" # Include python files recursively "!main.py\n" # But exclude main.py at the root "dir_b/\n" # Include dir_b "lib/**\n" # Explicitly include lib/ and its contents "README.md\n" # Include README "src/\n" # Explicitly include src directory for traversal , encoding='utf-8' ) # Use --overrides with project root stdout, stderr = run_jinni_cli(["-r", str(test_dir), "--overrides", str(overrides_path), "--no-copy", "--debug-explain"]) # Expected includes based on contextfiles + override rules + defaults: # Contextfiles include: file_root.txt, *.md, main.py, src/, dir_c/, dir_e/, dir_f/ # Overrides add: **/*.py, !main.py, dir_b/, lib/**, README.md, src/ # Defaults exclude: .*, build/, etc. # Check included assert "```path=README.md" in stdout # Included by override assert "```path=src/app.py" in stdout # Included by override **/*.py assert "```path=src/utils.py" in stdout # Included by override **/*.py assert "```path=src/nested/deep.py" in stdout # Included by override **/*.py assert "```path=dir_b/file_b1.py" in stdout # Included by override **/*.py and dir_b/ assert "```path=lib/somelib.py" in stdout # Included by override **/*.py (and lib/ inclusion) # Check excluded assert "```path=main.py" not in stdout # Excluded by override !main.py # With the new design, .contextfiles are still respected when using overrides assert "```path=file_root.txt" in stdout # Included by .contextfiles assert "```path=dir_a/important.log" in stdout # Included by .contextfiles in dir_a assert "```path=dir_c/file_c1.txt" in stdout # Included by .contextfiles (dir_c/) assert "```path=dir_f/file_f.txt" in stdout # Included by .contextfiles (dir_f/) assert "```path=docs/index.md" in stdout # Included by .contextfiles (*.md matches at any depth) assert "config.yaml" not in stdout # Not included by override rules assert ".env" not in stdout # Excluded by default assert "build/" not in stdout # Excluded by default # Check stderr for debug info, but not for critical errors assert "INFO:jinni.core_logic:Override rules provided as high-priority additions to normal rules." in stderr assert "DEBUG:jinni.context_walker:Active spec patterns:" in stderr assert "DEBUG:jinni.context_walker:FILE MATCH CHECK:" in stderr def test_cli_debug_explain(test_environment: Path): """Test the --debug-explain CLI flag with dynamic rules.""" test_dir = test_environment stdout, stderr = run_jinni_cli(["-r", str(test_dir), "--debug-explain"]) # Check stderr for expected explanation patterns (may need adjustment based on exact logging) # Look for dynamic spec source descriptions assert "DEBUG:jinni.context_walker:Compiled spec for" in stderr # Check for log from context_walker assert "from Default+Gitignore+Contextfiles at root" in stderr # Root context assert "from Default+Gitignore+Contextfiles up to ./src" in stderr # Src context assert "from Default+Gitignore+Contextfiles up to ./dir_a" in stderr # Dir_a context # Check specific inclusion/exclusion reasons based on the dynamic context # Check for the log message from the context walker module assert "DEBUG:jinni.context_walker:Including File:" in stderr assert "DEBUG:jinni.context_walker:Excluding File:" in stderr # Check context_walker logger assert "DEBUG:jinni.context_walker:Pruning Directory" in stderr # Check context_walker logger # Example specific checks (adapt based on actual log output) assert "Including File: " in stderr and "file_root.txt" in stderr and "Default+Gitignore+Contextfiles at root" in stderr assert "Excluding File: " in stderr and "root.log" in stderr and "Default+Gitignore+Contextfiles at root" in stderr assert "Including File: " in stderr and "src/app.py" in stderr and "Default+Gitignore+Contextfiles up to ./src" in stderr assert "Excluding File: " in stderr and "dir_a/file_a1.txt" in stderr and "Default+Gitignore+Contextfiles up to ./dir_a" in stderr assert "Including File: " in stderr and "dir_a/important.log" in stderr and "Default+Gitignore+Contextfiles up to ./dir_a" in stderr assert "Keeping Directory: " in stderr and "dir_b" in stderr and "Default+Gitignore+Contextfiles at root" in stderr # Check stdout is still correct (same as test_cli_with_contextfiles) assert "```path=file_root.txt" in stdout assert "```path=src/app.py" in stdout assert "```path=dir_b/file_b1.py" in stdout # Should be included by default '*' # Test removed as CLI now takes only one optional target # def test_cli_multi_path_input(test_environment: Path): # (Content removed) def test_cli_project_root(test_environment: Path): """Test the -r/--root flag.""" test_dir = test_environment # Include just src/app.py for simplicity (test_dir / CONTEXT_FILENAME).write_text("src/app.py", encoding='utf-8') # Run with project root set to test_dir, target is src/app.py stdout_root, _ = run_jinni_cli(["-r", str(test_dir), str(test_dir / "src/app.py")]) assert "```path=src/app.py" in stdout_root # Relative to root # Run with project root set to test_dir/src, target is app.py (relative to CWD, resolves inside root) stdout_src, _ = run_jinni_cli(["-r", str(test_dir / "src"), str(test_dir / "src" / "app.py")]) # Pass absolute path for target assert "```path=app.py" in stdout_src # Relative to root (which is src) assert "```path=src/app.py" not in stdout_src # Run with project root set to test_dir.parent, target is project/src/app.py stdout_parent, _ = run_jinni_cli(["-r", str(test_dir.parent), str(test_dir / "src/app.py")]) assert f"```path={test_dir.name}/src/app.py" in stdout_parent # Relative to root (parent) def test_cli_target_dir_uses_project_rules(test_environment: Path): """Test CLI targeting a dir within project uses project root rules.""" test_dir = test_environment # Root rule excludes utils.py (test_dir / CONTEXT_FILENAME).write_text("!**/utils.py", encoding='utf-8') # Local rule in src excludes data.json (test_dir / "src" / CONTEXT_FILENAME).write_text("!data.json", encoding='utf-8') # Run targeting the src directory, with project root set to test_dir stdout, stderr = run_jinni_cli(["-r", str(test_dir), str(test_dir / "src"), "--debug-explain"]) # Expected behavior: src is within project root, so rules start from project root # Expected includes: # - app.py (included by default *) # - nested/deep.py (included by default *) # - nested/other.txt (included by default *) # Expected excludes: # - utils.py (excluded by root !**/utils.py) # - data.json (excluded by src/.contextfiles !data.json) # - .hidden_in_src (excluded by default !.*) # Check included assert "```path=src/app.py" in stdout assert "```path=src/nested/deep.py" in stdout assert "```path=src/nested/other.txt" in stdout # Check excluded assert "```path=src/utils.py" not in stdout # Excluded by root rule assert "```path=src/data.json" not in stdout # Excluded by local rule assert "```path=src/.hidden_in_src" not in stdout # Excluded by default rule # Check files outside target are not included assert "```path=main.py" not in stdout assert "```path=README.md" not in stdout # assert stderr.strip() == "" # Removed assertion as debug logs are expected def test_cli_target_dot_directory(test_environment: Path): """Test targeting a dot-directory directly includes its non-dot files.""" test_dir = test_environment target_dot_dir = test_dir / ".testdir" # Run targeting the .testdir directory, with project root set to test_dir stdout, stderr = run_jinni_cli(["-r", str(test_dir), str(target_dot_dir)]) # Expected includes: # - yes (included by default '*' rule applied within .testdir) # Expected excludes: # - .nope (excluded by default '!.*' rule applied within .testdir) # Check included assert f"```path={target_dot_dir.name}/yes" in stdout # Path relative to root assert "it worked" in stdout # Check excluded assert f"```path={target_dot_dir.name}/.nope" not in stdout # Check files outside target are not included assert "```path=main.py" not in stdout assert "```path=README.md" not in stdout assert stderr.strip() == "" @pytest.mark.skip(reason="Cannot test NUL handling in CLI subprocess: Python/OS will reject argument before app code runs") def test_cli_nul_in_path_triggers_valueerror(test_environment: Path): """Test that a path with an embedded NUL triggers a clean ValueError and does not crash.""" test_dir = test_environment # Insert a NUL in the path bad_path = str(test_dir) + "\x00bad" import sys from conftest import run_jinni_cli import pytest with pytest.raises(SystemExit): stdout, stderr = run_jinni_cli([bad_path, "--no-copy"]) assert "Embedded NUL" in stderr or "\x00" in stderr def test_cli_list_token(test_environment: Path): """Test the --list-token CLI flag.""" test_dir = test_environment # Run with the project directory as the root, no specific target stdout, stderr = run_jinni_cli(["-r", str(test_dir), "-L", "--no-copy"]) # Expected files are the same as test_cli_list_only expected_files_base = sorted([ "README.md", "file_root.txt", "main.py", "dir_a/important.log", "dir_b/file_b1.py", "dir_b/sub_dir_b/include_me.txt", "dir_c/file_c1.txt", "dir_d/file_d.txt", "dir_f/file_f.txt", "lib/somelib.py", "src/app.py", "src/nested/deep.py", "src/utils.py", "docs/index.md", "docs/config/options.md", "src/nested/other.txt", ]) lines = stdout.strip().splitlines() # Check the file lines (ignoring exact token count, just check format) output_files = [] total_tokens = 0 for line in lines[:-2]: # Exclude separator and total assert ":" in line assert "tokens" in line path_part = line.split(":")[0].strip() token_part = line.split(":")[1].strip().split()[0] output_files.append(path_part) assert token_part.isdigit() # Check token count is a number total_tokens += int(token_part) assert sorted(output_files) == expected_files_base # Check the separator and total line assert lines[-2] == "---" assert lines[-1].startswith("Total:") assert f"{total_tokens} tokens" in lines[-1] # Check stderr contains only the expected INFO log, not errors assert "INFO:jinni.core_logic:Processed" in stderr assert "ERROR" not in stderr assert "WARNING" not in stderr

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/smat-dev/jinni'

If you have feedback or need assistance with the MCP directory API, please join our Discord server