- Marked all planned integration tests for the two-way sync functionality as completed, ensuring coverage for critical operations such as source property writes, property persistence, instance renames, and lifecycle management. - Added a new test module specifically for two-way sync, enhancing overall test coverage and reliability of the sync system. - Updated the change processor to handle file path overrides during instance updates, improving the accuracy of source writes and file management.
7.6 KiB
| name | overview | todos | isProject | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Two-way sync integration tests | Add integration tests covering the critical untested two-way sync operations: instance rename, ClassName transitions, non-Source property persistence, removal with meta cleanup, and end-to-end bidirectional sync workflows. Tests validate that the plugin sync pipeline can eventually replace `rojo syncback` for keeping the filesystem in sync with Studio. |
|
false |
Two-Way Sync Integration Tests
Intent
The plugin's two-way sync (POST /api/write) should eventually supersede the rojo syncback command entirely. The goal is continuous bidirectional sync: connect to Studio, accept changes, and work in an external IDE while others work in Studio. These tests validate the core primitives that make this possible.
Coverage Gaps Addressed
The existing tests cover format transitions (standalone/directory) and stress testing but have zero coverage for:
- Instance rename (changed_name) — file/directory rename on disk, adjacent meta file rename
- ClassName transitions (changed_class_name) — script type changes, init file detection in directories
- Non-Source property persistence (changed_properties except Source) — writing to meta files
- Instance removal with meta file cleanup — deleting files plus their adjacent
.meta.json5 - End-to-end round-trip — add instance, modify it, rename it, verify filesystem at each step
Test Fixture
Use existing syncback_write fixture (rojo-test/serve-tests/syncback_write/). It has a minimal project: ReplicatedStorage mapped to src/ with one existing existing.luau (ModuleScript). This is ideal for testing write operations without interference from complex file structures.
For rename tests, we also use syncback_format_transitions which has directory-format scripts with init files.
New Test File
Add tests to tests/tests/two_way_sync.rs (new file). Register it via tests/end_to_end.rs.
All tests follow the established pattern:
run_serve_test(fixture_name, |session, _redactions| { ... })- Find parent ID via
get_api_rojo()+get_api_read() - Construct
WriteRequestwithadded,updated, orremoved - Call
session.post_api_write() - Assert filesystem state
Tests
1. update_source_writes_to_disk — Verify the basic Source write path
Send an InstanceUpdate with changed_properties: { Source: "-- new content" } for the existing existing.luau. Verify fs::read_to_string returns the new content. This is the most fundamental two-way sync operation.
2. update_non_source_property_creates_meta_file — Issue 2 coverage
Send an InstanceUpdate with a non-Source property (Attributes) for existing.luau. Verify:
existing.meta.json5is created adjacent toexisting.luau- The meta file contains the attribute value
existing.luauitself is unchanged
3. update_properties_for_directory_script_writes_init_meta — Issue 2 directory path
Use syncback_format_transitions fixture. Send property update for a directory-format script (DirModuleWithChildren). Verify init.meta.json5 is created inside the directory.
4. rename_standalone_script — Issue 8 rename coverage
Add a new ModuleScript OldName via added, wait for it to appear on disk. Then send an InstanceUpdate with changed_name: Some("NewName"). Verify:
OldName.luauis goneNewName.luauexists with same content
5. rename_preserves_adjacent_meta_file — Issue 8 meta rename
Add a ModuleScript, send a property update to create its meta file, then rename it. Verify both the .luau and .meta.json5 files are renamed together.
6. classname_change_standalone_module_to_script — Issue 8 ClassName coverage
Add a ModuleScript MyModule, then send changed_class_name: Some("Script"). Verify:
MyModule.luauis goneMyModule.server.luauexists
7. classname_change_directory_script_renames_init_file — Issue 8 directory ClassName
Use syncback_format_transitions. Send changed_class_name for DirModuleWithChildren (ModuleScript -> Script). Verify:
- Directory still exists
init.luauis goneinit.server.luauexists- Children still exist
8. remove_instance_deletes_file_and_meta — Issue 4 removal cleanup
Add a ModuleScript, create its meta file via property update, then remove it via removed. Verify both the .luau file and .meta.json5 are deleted.
9. remove_directory_instance — Issue 4 directory removal
Use syncback_format_transitions. Remove a directory-format instance. Verify the entire directory is deleted recursively.
10. round_trip_add_modify_rename_remove — End-to-end workflow
This test validates the complete lifecycle that makes two-way sync viable as a syncback replacement:
- Add a new Script
PlayerHandlerwith children - Verify directory created on disk
- Modify its Source property
- Verify file content updated
- Rename it to
GameHandler - Verify directory renamed
- Remove it
- Verify directory deleted
11. property_update_skips_project_node_instances — Post-fix coverage
Send property update for a Service (ReplicatedStorage) which has InstigatingSource::ProjectNode. Verify it does NOT corrupt the project file. The project file content should be unchanged.
12. echo_suppression_prevents_redundant_patches — Issue 7 coverage
Add a new instance, then immediately read the message queue. Count the WebSocket messages — there should be exactly one patch notification, not two (which would indicate echo from the VFS picking up the file write).
Key Implementation Details
InstanceUpdaterequiresUstrMap<Option<Variant>>forchanged_properties. Importrbx_dom_weak::{ustr, UstrMap}.- Finding existing instance IDs: read tree via
get_api_read(root_id), traverseinstancesto find by class/name. - After
post_api_write, sleep 200-500ms for change processor to handle VFS events. - Use
fs::read_to_stringto verify file content,fs::metadatato verify existence. - For rename/ClassName tests, the instance ID in
InstanceUpdatemust match the ID the server assigned (found viaget_api_readafter the initial add).
File Registration
Add mod two_way_sync; to tests/tests/mod.rs (or the test harness entry point tests/end_to_end.rs).