Refactor serve tests to use recv_socket_packet for file operations

- Replaced direct file operations with the new recv_socket_packet method in multiple test functions to ensure WebSocket listeners are active before changes are made.
- This change helps avoid race conditions and improves the reliability of test outcomes by ensuring that actions triggering file changes are executed after the WebSocket connection is established.
This commit is contained in:
Joe 2026-02-05 17:12:07 -06:00
parent b1aa2a384f
commit 4a03d4bab5
2 changed files with 35 additions and 18 deletions

View file

@ -186,6 +186,21 @@ impl TestServeSession {
&self,
packet_type: SocketPacketType,
cursor: u32,
) -> Result<SocketPacket<'static>, Box<dyn std::error::Error>> {
self.recv_socket_packet(packet_type, cursor, || {})
}
/// Start listening on the WebSocket, then run the provided action (e.g. a
/// file modification), and wait for the expected packet.
///
/// This avoids race conditions where the file watcher hasn't processed a
/// change before the WebSocket connects: by connecting first, the listener
/// is guaranteed to be in place when the change is detected.
pub fn recv_socket_packet(
&self,
packet_type: SocketPacketType,
cursor: u32,
action: impl FnOnce(),
) -> Result<SocketPacket<'static>, Box<dyn std::error::Error>> {
let url = format!("ws://localhost:{}/api/socket/{}", self.port, cursor);
@ -200,6 +215,10 @@ impl TestServeSession {
stream.set_read_timeout(Some(Duration::from_millis(100)))?;
}
// Now that the WebSocket is connected and listening, perform the action
// that should trigger the change (e.g. writing/deleting a file).
action();
let start = std::time::Instant::now();
loop {

View file

@ -1,6 +1,4 @@
use std::fs;
use std::thread;
use std::time::Duration;
use insta::{assert_snapshot, assert_yaml_snapshot, with_settings};
use tempfile::tempdir;
@ -44,11 +42,11 @@ fn scripts() {
);
});
fs::write(session.path().join("src/foo.luau"), "Updated foo!").unwrap();
thread::sleep(Duration::from_millis(100));
let path = session.path().join("src/foo.luau");
let socket_packet = session
.get_api_socket_packet(SocketPacketType::Messages, 0)
.recv_socket_packet(SocketPacketType::Messages, 0, || {
fs::write(&path, "Updated foo!").unwrap();
})
.unwrap();
assert_yaml_snapshot!(
"scripts_subscribe",
@ -111,11 +109,11 @@ fn remove_file() {
read_response.intern_and_redact(&mut redactions, root_id)
);
fs::remove_file(session.path().join("src/hello.txt")).unwrap();
thread::sleep(Duration::from_millis(100));
let path = session.path().join("src/hello.txt");
let socket_packet = session
.get_api_socket_packet(SocketPacketType::Messages, 0)
.recv_socket_packet(SocketPacketType::Messages, 0, || {
fs::remove_file(&path).unwrap();
})
.unwrap();
assert_yaml_snapshot!(
"remove_file_subscribe",
@ -144,11 +142,11 @@ fn edit_init() {
read_response.intern_and_redact(&mut redactions, root_id)
);
fs::write(session.path().join("src/init.luau"), b"-- Edited contents").unwrap();
thread::sleep(Duration::from_millis(100));
let path = session.path().join("src/init.luau");
let socket_packet = session
.get_api_socket_packet(SocketPacketType::Messages, 0)
.recv_socket_packet(SocketPacketType::Messages, 0, || {
fs::write(&path, b"-- Edited contents").unwrap();
})
.unwrap();
assert_yaml_snapshot!(
"edit_init_subscribe",
@ -488,11 +486,11 @@ fn ref_properties_remove() {
read_response.intern_and_redact(&mut redactions, root_id)
);
fs::remove_file(session.path().join("src/target.model.json5")).unwrap();
thread::sleep(Duration::from_millis(100));
let path = session.path().join("src/target.model.json5");
let socket_packet = session
.get_api_socket_packet(SocketPacketType::Messages, 0)
.recv_socket_packet(SocketPacketType::Messages, 0, || {
fs::remove_file(&path).unwrap();
})
.unwrap();
assert_yaml_snapshot!(
"ref_properties_remove_subscribe",