diff --git a/editor/CMakeLists.txt b/editor/CMakeLists.txt index 2491350..dec06cb 100644 --- a/editor/CMakeLists.txt +++ b/editor/CMakeLists.txt @@ -2134,4 +2134,8 @@ add_executable(step359_test tests/step359_test.cpp) target_include_directories(step359_test PRIVATE src) target_link_libraries(step359_test PRIVATE nlohmann_json::nlohmann_json) +add_executable(step360_test tests/step360_test.cpp) +target_include_directories(step360_test PRIVATE src) +target_link_libraries(step360_test PRIVATE nlohmann_json::nlohmann_json) + # Step 12: Dear ImGui shell scaffolding created (main.cpp exists but not built due to dependencies) diff --git a/editor/tests/step360_test.cpp b/editor/tests/step360_test.cpp new file mode 100644 index 0000000..20925ee --- /dev/null +++ b/editor/tests/step360_test.cpp @@ -0,0 +1,198 @@ +// Step 360: Phase 13d Integration + Sprint 13 Summary (8 tests) + +#include +#include +#include +#include +#include "PanelManager.h" +#include "ThemeData.h" +#include "KeybindingRegistry.h" +#include "KeySymbolRenderer.h" +#include "CommandPalette.h" +#include "MenuBar.h" +#include "KeyboardShortcutsPanel.h" +#include "panels/BreadcrumbBar.h" +#include "panels/StatusBar.h" +#include "panels/NavigationTools.h" +#include "panels/FindReplaceBar.h" +#include "ast/Function.h" + +int main() { + int passed = 0; + WhetstoneTheme theme = getDefaultDarkTheme(); + + // Shared module/project for navigation tests + Module mod("m1", "app", "python"); + auto* helper = new Function("f1", "helper"); + helper->setSpan(9, 0, 12, 0); + auto* caller = new Function("f2", "caller"); + caller->setSpan(19, 0, 24, 0); + mod.addChild("functions", helper); + mod.addChild("functions", caller); + std::vector> modules = {{"app.py", &mod}}; + + // Test 1: keyboard workflow + definition + breadcrumb click-back + { + FunctionCall call; + call.functionName = "helper"; + auto def = goToDefinition(&call, "app.py", modules); + assert(def.has_value()); + auto crumbs = buildBreadcrumbBar(&mod, def->node, theme); + assert(!crumbs.segments.empty()); + auto back = navigateBreadcrumbClick(crumbs, 0); + assert(back == &mod); + std::cout << "Test 1 PASSED: keyboard -> definition -> breadcrumb back\n"; + passed++; + } + + // Test 2: command palette -> find -> project search -> navigate to result + { + KeybindingRegistry reg; + reg.loadDefaults(); + CommandPalette palette; + palette.registerFromKeybindings(reg); + auto cmdMatches = palette.search("find"); + assert(!cmdMatches.empty()); + auto selected = palette.executeSelected(cmdMatches); + assert(selected.has_value()); + assert(selected.value().find("find") != std::string::npos); + + FindReplaceBar bar; + bar.openFind(); + bar.setQuery("helper", "helper()\n"); + auto results = bar.searchProject({{"app.py", "helper()\n"}, {"other.py", "x\n"}}); + assert(!results.empty()); + assert(results[0].filePath == "app.py"); + std::cout << "Test 2 PASSED: palette find -> project results\n"; + passed++; + } + + // Test 3: status bar reflects buffer switches + { + StatusBarInput py; + py.language = "python"; + py.filePath = "a.py"; + py.line = 4; + py.column = 2; + py.errorCount = 1; + auto a = buildStatusBar(py, theme); + + StatusBarInput cpp; + cpp.language = "cpp"; + cpp.filePath = "a.cpp"; + cpp.line = 30; + cpp.column = 1; + cpp.warningCount = 2; + auto b = buildStatusBar(cpp, theme); + + assert(a.languageBadge != b.languageBadge); + assert(a.centerText != b.centerText); + assert(a.diagnosticsText != b.diagnosticsText); + std::cout << "Test 3 PASSED: status bar reflects buffer switch\n"; + passed++; + } + + // Test 4: all panels docked (no floating windows in model) + { + PanelManager pm; + pm.registerDefaults(); + auto visible = pm.getVisiblePanels(); + assert(visible.size() == 8); + for (const auto& p : visible) { + assert(p.currentDock == DockPosition::Left || + p.currentDock == DockPosition::CenterTop || + p.currentDock == DockPosition::CenterBottom || + p.currentDock == DockPosition::Right || + p.currentDock == DockPosition::Bottom); + } + std::cout << "Test 4 PASSED: panels are docked\n"; + passed++; + } + + // Test 5: theme consistency across panels/navigation elements + { + auto crumbs = buildBreadcrumbBar(&mod, helper, theme); + StatusBarInput in; + in.filePath = "app.py"; + auto status = buildStatusBar(in, theme); + auto badge = KeySymbolRenderer::renderKeySymbol(KeyCombo::ctrl("S"), theme); + assert(crumbs.textColor.toHex() == theme.text.toHex()); + assert(status.textColor.toHex() == theme.text.toHex()); + assert(badge.textColor.toHex() == theme.text.toHex()); + std::cout << "Test 5 PASSED: theme consistency\n"; + passed++; + } + + // Test 6: key symbols visible in menu, palette, shortcuts panel + { + KeybindingRegistry reg; + reg.loadDefaults(); + auto menu = MenuBar::buildDefaults(reg, theme); + auto saveItem = menu.findItem("save-buffer"); + assert(!saveItem.symbols.empty()); + + CommandPalette palette; + palette.registerFromKeybindings(reg); + bool paletteHasSymbol = false; + for (const auto& entry : palette.all()) { + if (entry.id == "save-buffer") { + paletteHasSymbol = !entry.symbols.empty(); + } + } + assert(paletteHasSymbol); + + KeyboardShortcutsPanel panel; + panel.loadFromRegistry(reg); + bool panelHasSymbol = false; + for (const auto& row : panel.rows()) { + if (row.actionId == "save-buffer") panelHasSymbol = !row.symbols.empty(); + } + assert(panelHasSymbol); + std::cout << "Test 6 PASSED: key symbols visible everywhere\n"; + passed++; + } + + // Test 7: layout save/restart/restore + { + PanelManager pm; + pm.registerDefaults(); + pm.setVisible("workflow", false); + pm.movePanelToDock("diagnostics", DockPosition::Right); + auto snap = pm.toJson(); + auto restored = PanelManager::fromJson(snap); + assert(!restored.isVisible("workflow")); + assert(restored.getPanel("diagnostics").currentDock == DockPosition::Right); + std::cout << "Test 7 PASSED: layout restore\n"; + passed++; + } + + // Test 8: Sprint 13 summary gates operational + { + bool dockingOk = true; + bool themeOk = true; + bool keysOk = true; + bool navOk = true; + + PanelManager pm; + pm.registerDefaults(); + dockingOk = pm.panelCount() >= 8; + + KeybindingRegistry reg; + reg.loadDefaults(); + keysOk = reg.bindingCount() >= 15; + + auto st = buildStatusBar(StatusBarInput{"python", "app.py"}, theme); + themeOk = (st.bgColor.toHex() == theme.bgPanel.toHex()); + + auto symbols = collectFileSymbols(&mod, "app.py"); + navOk = !symbols.empty(); + + assert(dockingOk && themeOk && keysOk && navOk); + std::cout << "Test 8 PASSED: sprint summary gates\n"; + passed++; + } + + std::cout << "\nResults: " << passed << "/8\n"; + assert(passed == 8); + return 0; +} diff --git a/progress.md b/progress.md index 01e6c34..32c3158 100644 --- a/progress.md +++ b/progress.md @@ -2007,6 +2007,39 @@ Model behavior includes open/close modes, highlight state, and match counter tex - `step358_test` — PASS (12/12) regression coverage - `step359_test` — PASS (12/12) new step coverage +### Step 360: Phase 13d Integration + Sprint 13 Summary +**Status:** PASS (8/8 tests) + +Completed Phase 13d integration with end-to-end checks across keyboard navigation, +go-to-definition, breadcrumb navigation, command palette search flows, status bar +state transitions, key symbol visibility, and panel layout persistence. + +**Files created:** +- `editor/tests/step360_test.cpp` — 8 integration tests: + 1. keyboard workflow + definition jump + breadcrumb back-navigation + 2. command palette find flow + project result navigation + 3. status bar response to buffer/language/cursor/diagnostic changes + 4. docked-panel invariant (no floating model state) + 5. theme consistency across navigation components + 6. key symbols in menu + palette + shortcuts panel + 7. layout snapshot/restore roundtrip + 8. sprint-level operational gates (docking/theme/keys/navigation) + +**Files modified:** +- `editor/CMakeLists.txt` — `step360_test` target + +**Verification run:** +- `step358_test` — PASS (12/12) regression coverage +- `step359_test` — PASS (12/12) regression coverage +- `step360_test` — PASS (8/8) phase integration coverage + +**Key results:** +- Phase 13d complete: all 5 steps pass (56/56 tests across steps 356–360) +- Sprint 13 complete: all phases pass (212/212 tests across steps 342–360) +- Navigation foundation in place: breadcrumbs, status model, symbol navigation, + find/replace model, and full keyboard-centric integration path +- Key symbol consistency validated across all primary interaction surfaces + # Roadmap Planning — Sprints 12-25+ ## Status: Planning Complete (Sprints 12-19 detailed, 20-25 in roadmap.md)