Skip to content

test: add mock tests for 8 executor handler files#3

Open
retran wants to merge 1 commit intotest/visitor-coveragefrom
test/handler-mock-new
Open

test: add mock tests for 8 executor handler files#3
retran wants to merge 1 commit intotest/visitor-coveragefrom
test/handler-mock-new

Conversation

@retran
Copy link
Copy Markdown
Owner

@retran retran commented Apr 21, 2026

Summary

  • Add 49 tests across 8 new test files for executor handlers that previously had zero test coverage
  • Full mock coverage (happy-path, error-path, not-connected, edge cases) for: cmd_folders, cmd_move, cmd_rename, cmd_alter_page, cmd_features
  • Partial coverage (not-connected + error guards) for: cmd_styling, cmd_lint, cmd_import — happy paths depend on filesystem/DB connections not mockable through the Backend interface

Test Files

File Tests Coverage
cmd_folders_mock_test.go 9 Full (DropFolder + MoveFolder)
cmd_move_mock_test.go 6 Full (page moves, cross-module, errors)
cmd_rename_mock_test.go 11 Full (all 8 object types)
cmd_alter_page_mock_test.go 9 Full (properties, widgets, variables, layout)
cmd_features_mock_test.go 7 Full (ForVersion, AddedSince, connected)
cmd_styling_mock_test.go 5 Partial (not-connected guards)
cmd_lint_mock_test.go 1 Partial (not-connected guard)
cmd_import_mock_test.go 1 Partial (not-connected guard)

Stack

PR 0 (fix/dset-silent-failure) → PR A (test/enablers) → PR B (test/visitor-coverage) → PR C1 (this) → PR C2 → PR D1 → PR D2

Add 49 tests across 8 new test files covering executor handlers
that previously had zero test coverage:

- cmd_folders: 9 tests (DropFolder + MoveFolder paths)
- cmd_move: 6 tests (page moves, cross-module refs, error paths)
- cmd_rename: 11 tests (entity/module/microflow/page/enum/assoc/const/nanoflow)
- cmd_alter_page: 9 tests (set property, snippets, widgets, variables, layout)
- cmd_features: 7 tests (ForVersion, AddedSince, connected, invalid version)
- cmd_styling: 5 tests (not-connected guards for all 3 styling commands)
- cmd_lint: 1 test (not-connected guard)
- cmd_import: 1 test (not-connected guard)

Styling, lint, and import have partial coverage (not-connected + error
paths only) because their happy paths depend on filesystem or external
DB connections that cannot be mocked through the current Backend interface.
Copilot AI review requested due to automatic review settings April 21, 2026 11:46
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds mock-based unit tests for several mdl/executor command handlers that previously lacked coverage, focusing on connection guards plus selected happy/error paths using MockBackend and shared test helpers.

Changes:

  • Introduces new mock test suites for cmd_folders, cmd_move, cmd_rename, cmd_alter_page, and cmd_features with broader behavior coverage.
  • Adds minimal “not connected” guard tests for handlers with dependencies not easily mockable via the current Backend interface (cmd_styling, cmd_lint, cmd_import).

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
mdl/executor/cmd_styling_mock_test.go Adds connection/path guard tests for styling commands (includes a skipped test).
mdl/executor/cmd_rename_mock_test.go Adds rename tests covering several object types and key error paths.
mdl/executor/cmd_move_mock_test.go Adds move tests for pages (folder move, cross-module refs, errors).
mdl/executor/cmd_lint_mock_test.go Adds not-connected guard test for execLint.
mdl/executor/cmd_import_mock_test.go Adds not-connected guard test for execImport.
mdl/executor/cmd_folders_mock_test.go Adds tests for drop/move folder flows and backend errors.
mdl/executor/cmd_features_mock_test.go Adds tests for SHOW FEATURES modes (connected vs ForVersion/AddedSince).
mdl/executor/cmd_alter_page_mock_test.go Adds tests for ALTER PAGE/SNIPPET mutator flows and error handling.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

MovePageFunc: func(p *pages.Page) error { movedPage = p; return nil },
}
h := mkHierarchy(mod)
withContainer(h, pg.ID, mod.ID)
Copy link

Copilot AI Apr 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

withContainer is intended to be called with an element's ContainerID (see helper doc), but this passes the page's own ID. This makes the hierarchy setup misleading and won't exercise module resolution behavior if the page is ever placed under a non-module container (e.g., a folder). Use pg.ContainerID (and set it to a folder ID when relevant) when registering parentage.

Suggested change
withContainer(h, pg.ID, mod.ID)
withContainer(h, pg.ContainerID, mod.ID)

Copilot uses AI. Check for mistakes.
},
}
h := mkHierarchy(srcMod, dstMod)
withContainer(h, pg.ID, srcMod.ID)
Copy link

Copilot AI Apr 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same issue here: withContainer(h, pg.ID, srcMod.ID) passes the unit ID instead of pg.ContainerID, so the hierarchy wiring doesn't reflect production behavior (FindModuleID is called with ContainerID). Prefer wiring pg.ContainerID (or a folder ID) to the owning module.

Suggested change
withContainer(h, pg.ID, srcMod.ID)
withContainer(h, pg.ContainerID, srcMod.ID)

Copilot uses AI. Check for mistakes.
MovePageFunc: func(p *pages.Page) error { return fmt.Errorf("disk full") },
}
h := mkHierarchy(mod)
withContainer(h, pg.ID, mod.ID)
Copy link

Copilot AI Apr 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same issue here: withContainer(h, pg.ID, mod.ID) uses the page ID rather than pg.ContainerID, so the hierarchy setup is inconsistent with how the executor resolves modules (FindModuleID(p.ContainerID)).

Suggested change
withContainer(h, pg.ID, mod.ID)
withContainer(h, pg.ContainerID, mod.ID)

Copilot uses AI. Check for mistakes.
Comment on lines +18 to +49
// ---------------------------------------------------------------------------
// Not connected
// ---------------------------------------------------------------------------

func TestRename_NotConnected(t *testing.T) {
mb := &mock.MockBackend{IsConnectedFunc: func() bool { return false }}
ctx, _ := newMockCtx(t, withBackend(mb))
err := execRename(ctx, &ast.RenameStmt{
ObjectType: "ENTITY",
Name: ast.QualifiedName{Module: "MyModule", Name: "OldName"},
NewName: "NewName",
})
assertError(t, err)
assertContainsStr(t, err.Error(), "not connected")
}

// ---------------------------------------------------------------------------
// Unsupported type
// ---------------------------------------------------------------------------

func TestRename_UnsupportedType(t *testing.T) {
mb := &mock.MockBackend{IsConnectedFunc: func() bool { return true }}
ctx, _ := newMockCtx(t, withBackend(mb))
err := execRename(ctx, &ast.RenameStmt{
ObjectType: "WORKFLOW",
Name: ast.QualifiedName{Module: "M", Name: "N"},
NewName: "X",
})
assertError(t, err)
assertContainsStr(t, err.Error(), "not supported")
}

Copy link

Copilot AI Apr 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR description says this file has "Full (all 8 object types)" coverage for RENAME, but the tests here only cover ENTITY, MICROFLOW, MODULE, ASSOCIATION, plus a PAGE not-found case. If full coverage is intended, add tests for NANOFLOW / ENUMERATION / CONSTANT and a PAGE happy path (and update the PR description/table if full coverage is not actually in scope).

Copilot uses AI. Check for mistakes.
Comment on lines +71 to +81

func TestAlterStyling_NotConnectedForWrite(t *testing.T) {
mb := &mock.MockBackend{
// Connected but read-only: IsConnected returns true but we need
// ConnectedForWrite to fail. ConnectedForWrite delegates to Connected()
// which calls IsConnected(), so we can't differentiate with the mock.
// Skip this test — ConnectedForWrite() == Connected() in current impl.
}
_ = mb
t.Skip("ConnectedForWrite delegates to Connected — cannot distinguish in mock")
}
Copy link

Copilot AI Apr 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TestAlterStyling_NotConnectedForWrite is permanently skipped, so it doesn't add coverage and can cause CI noise if skipped tests are tracked. Consider removing it, or (if you want to test the write-guard) introduce a test seam (e.g., make ConnectedForWrite depend on a backend capability flag that the mock can control).

Suggested change
func TestAlterStyling_NotConnectedForWrite(t *testing.T) {
mb := &mock.MockBackend{
// Connected but read-only: IsConnected returns true but we need
// ConnectedForWrite to fail. ConnectedForWrite delegates to Connected()
// which calls IsConnected(), so we can't differentiate with the mock.
// Skip this test — ConnectedForWrite() == Connected() in current impl.
}
_ = mb
t.Skip("ConnectedForWrite delegates to Connected — cannot distinguish in mock")
}

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants