0
0
Fork 0
Codesys-MCP-SP21-plus/tests/integration
Karstein Phobic Nyvold Kvistad d414c779a5 fix(add_library): refuse to save unresolvable placeholders
Prior behaviour: lm.add_library(LIBRARY_NAME) was called with a string,
which always hits the placeholder overload of ScriptLibManObject.add_library
(see helpme-codesys.com "ScriptLibManObject" / local SP22 stub
ScriptLib/Stubs/scriptengine/ScriptLibManObject.pyi). If the named
placeholder is not registered in the IDE, the resulting reference fails
to resolve at load time and the next project open throws

  Library Manager: Error: Could not open library 'X'.
  (Reason: The placeholder library 'X' could not be resolved.)

after which script_engine.projects.primary returns None and the project
is effectively bricked until the binary is reverted. add_library reported
SUCCESS in this scenario.

Fix:
  1. Pre-resolve LIBRARY_NAME via the IDE-level
     library_manager.find_library(name) global. If found, pass the
     resulting ManagedLib to lm.add_library(...) -- the V3.5.5.0 ManagedLib
     overload which produces a managed reference instead of a placeholder.
  2. After the add, walk lm.references to locate the new entry and verify
     it resolved (managed -> always; placeholder -> non-empty
     effective_resolution per ScriptPlaceholderReference in the stub).
  3. If the reference did not resolve, call lm.remove_library(name) to back
     out the bad reference and refuse to save the project, returning an
     actionable error instead.

Also tightened the libman lookup to use the documented
has_library_manager / get_library_manager() container API
(ScriptLibManObjectContainer in the stub) instead of name-searching for
"Library Manager" as a tree node, matching what list_project_libraries.py
already does. The legacy name-search fallback is preserved for older SPs.

Regression test added in tests/integration/e2e.test.ts asserting the
rendered script template carries the resolution gate, the managed-overload
preference, the back-out call, and that primary_project.save() in the
add_library body lives downstream of the _is_resolved gate.

Followup: lm.remove_library(name) is documented for SP22 and is the
clean back-out path. On SPs that lack remove_library (none observed in
the 3.5.21+ docs but possible on truly old branches) the script reports
the constraint and exits non-zero rather than silently saving a bad
reference.
2026-04-26 19:44:00 +02:00
..
e2e.test.ts fix(add_library): refuse to save unresolvable placeholders 2026-04-26 19:44:00 +02:00
README.md Initial release: MCP server for CODESYS with persistent UI instance 2026-02-08 18:59:16 +10:00

Manual CODESYS Integration Tests

These tests require a real CODESYS installation and cannot run in CI.

Prerequisites

  • CODESYS 3.5 SP19 or SP21 installed
  • No other CODESYS instances running
  • Node.js 18+

Steps

1. Build the package

npm run build

2. Test persistent mode

node dist/bin.js \
  --codesys-path "C:\path\to\CODESYS.exe" \
  --codesys-profile "CODESYS V3.5 SP21 Patch 3" \
  --mode persistent \
  --verbose

Verify:

  • CODESYS UI opens
  • Console shows "CODESYS watcher is ready"
  • The MCP server accepts connections

3. Test headless fallback

node dist/bin.js \
  --codesys-path "C:\path\to\CODESYS.exe" \
  --codesys-profile "CODESYS V3.5 SP21 Patch 3" \
  --mode headless

4. Test --detect flag

node dist/bin.js --detect

Verify: Lists installed CODESYS versions.

5. Ctrl+C shutdown

  • Press Ctrl+C during persistent mode
  • Verify CODESYS shuts down cleanly