// Integration tests for grep --path-tree CLI flag // Phase 3, Step 4: Tests for CLI integration #include // removed: yams/app/cli.h (header no longer exists) #include #include #include #include #include #include #include using namespace yams; using namespace yams::metadata; struct GrepPathTreeIntegrationTest { GrepPathTreeIntegrationTest() { testDir_ = std::filesystem::temp_directory_path() / "yams_grep_path_tree_integration"; std::filesystem::create_directories(testDir_); dbPath_ = testDir_ / "yams.db"; // Initialize repository with test data ConnectionPoolConfig poolCfg; poolCfg.minConnections = 1; poolCfg.maxConnections = 2; pool_ = std::make_unique(dbPath_.string(), poolCfg); auto initRes = pool_->initialize(); REQUIRE(initRes.has_value()); repository_ = std::make_shared(*pool_); // Run migrations auto connRes = pool_->acquire(); REQUIRE(connRes.has_value()); auto& db = **connRes.value(); yams::metadata::MigrationManager mgr(db); mgr.registerMigrations(yams::metadata::YamsMetadataMigrations::getAllMigrations()); auto initRes2 = mgr.initialize(); REQUIRE(initRes2.has_value()); auto migrate = mgr.migrate(); REQUIRE(migrate.has_value()); // Seed test data seedTestDocuments(); } ~GrepPathTreeIntegrationTest() { repository_.reset(); pool_.reset(); std::error_code ec; std::filesystem::remove_all(testDir_, ec); } void seedTestDocuments() { // Create documents with path tree structure std::vector>> docs = { {"/project/src/main.cpp", "HASH001", {1.0F, 2.0F, 3.0F}}, {"/project/src/utils.cpp", "HASH002", {1.5F, 2.5F, 3.5F}}, {"/project/tests/test_main.cpp", "HASH003", {5.0F, 6.0F, 7.0F}}, {"/project/docs/README.md", "HASH004", {9.0F, 10.0F, 11.0F}}, }; for (const auto& [path, hash, embedding] : docs) { DocumentInfo doc; doc.sha256Hash = hash; doc.filePath = path; doc.mimeType = "text/plain"; doc.fileSize = 100; auto now = std::chrono::time_point_cast( std::chrono::system_clock::now()); doc.indexedTime = std::chrono::time_point_cast(now); doc.modifiedTime = std::chrono::time_point_cast(now); doc.createdTime = std::chrono::time_point_cast(now); auto insertRes = repository_->insertDocument(doc); REQUIRE(insertRes.has_value()); doc.id = insertRes.value(); // Build path tree with embeddings auto upsertRes = repository_->upsertPathTreeForDocument( doc, doc.id, true, std::span(embedding.data(), embedding.size())); REQUIRE(upsertRes.has_value()); } } std::filesystem::path testDir_; std::filesystem::path dbPath_; std::unique_ptr pool_; std::shared_ptr repository_; }; // TODO: These tests are stubs for Phase 3, Step 4 // Once grep_command.cpp is wired to call RetrievalService with PathTreeOptions, // these tests will exercise the full CLI → Service → Repository flow TEST_CASE_METHOD(GrepPathTreeIntegrationTest, "GrepWithPathTreeFlagParsesCorrectly", "[integration][greppathtreeintegrationtest]") { // This test verifies that the --path-tree flag is parsed without error // Expected behavior: CLI should accept the flag and pass it to the service layer // TODO: Once grep_command.cpp calls rsvc.grep(..., PathTreeOptions{...}), // this test should verify that PathTreeOptions.enabled = true when flag is set SKIP("CLI wiring pending - Phase 3, Step 3"); } TEST_CASE_METHOD(GrepPathTreeIntegrationTest, "GrepPathTreeReturnsChildNodes", "[integration][greppathtreeintegrationtest]") { // Test: yams grep --path-tree --paths "/project/src" should return child nodes // Expected: main.cpp and utils.cpp (2 docs under /project/src) // TODO: Implement once service layer returns synthetic matches with matchType="path_tree" SKIP("Service implementation pending"); } TEST_CASE_METHOD(GrepPathTreeIntegrationTest, "GrepPathTreeShowsDocCounts", "[integration][greppathtreeintegrationtest]") { // Test: Path-tree results should include doc counts in output // Expected: Each child node shows its doc_count SKIP("Service implementation pending"); } TEST_CASE_METHOD(GrepPathTreeIntegrationTest, "GrepPathTreeFallbackModeWorks", "[integration][greppathtreeintegrationtest]") { // Test: --path-tree mode=fallback should try path-tree first, fallback to normal grep // Expected: If path-tree query returns empty, normal grep runs SKIP("Service implementation pending"); } TEST_CASE_METHOD(GrepPathTreeIntegrationTest, "GrepPathTreePreferredModeSkipsFallback", "[integration][greppathtreeintegrationtest]") { // Test: --path-tree mode=preferred should only use path-tree, no fallback // Expected: If path-tree returns empty, command returns empty (no normal grep) SKIP("Service implementation pending"); } TEST_CASE_METHOD(GrepPathTreeIntegrationTest, "GrepPathTreeLimitsChildren", "[integration][greppathtreeintegrationtest]") { // Test: childLimit parameter should cap number of children returned // Expected: Only top N children by doc_count SKIP("Service implementation pending"); } // NOTE: To run these tests when Phase 3 is complete: // 1. Remove GTEST_SKIP() calls // 2. Add actual CLI invocation or service calls // 3. Verify output format matches expected synthetic GrepResponse structure