Loading crates/integration-testkit/src/query_scenario/format.rs +13 −0 Changes for crates/integration-testkit/src/query_scenario/format.rs: 13 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -293,4 +293,17 @@ pub struct PathEdgeExpect { pub to: Option<String>, #[serde(default)] pub to_id: Option<i64>, #[serde(default)] pub step: Option<usize>, } impl PathEdgeExpect { pub fn has_assertions(&self) -> bool { self.from.is_some() || self.from_id.is_some() || self.edge_type.is_some() || self.to.is_some() || self.to_id.is_some() || self.step.is_some() } } crates/integration-testkit/src/query_scenario/mod.rs +43 −3 Changes for crates/integration-testkit/src/query_scenario/mod.rs: 43 added lines, 3 removed lines. Original line number Diff line number Diff line Loading @@ -660,6 +660,14 @@ fn apply_expect(view: &ResponseView, expect: &QueryExpect, label: &str) { } } if !expect.path_edges.is_empty() { for (pi, path_exp) in expect.path_edges.iter().enumerate() { for (ei, edge_exp) in path_exp.iter().enumerate() { assert!( edge_exp.has_assertions(), "{label}: path_edges[{pi}][{ei}] has no assertions (all fields omitted)" ); } } let pids = view.path_ids(); assert_eq!( pids.len(), Loading @@ -668,14 +676,43 @@ fn apply_expect(view: &ResponseView, expect: &QueryExpect, label: &str) { expect.path_edges.len(), pids.len() ); for (i, (&pid, expected_edges)) in pids.iter().zip(&expect.path_edges).enumerate() { let actual = view.path(pid); // Sort both actual paths and expected paths by destination ID // so the zip is deterministic regardless of path_ids() ordering. let mut actual_paths: Vec<_> = pids .iter() .map(|&pid| { let edges = view.path(pid); let dest_id = edges.last().map_or(0, |e| e.to_id); (dest_id, edges) }) .collect(); actual_paths.sort_by_key(|(dest, _)| *dest); let mut expected_indexed: Vec<_> = expect .path_edges .iter() .enumerate() .map(|(i, edges)| { let dest_id = edges.last().and_then(|e| e.to_id).unwrap_or_else(|| { assert!( expect.path_edges.len() == 1, "{label}: path_edges[{i}] must set to_id on its last edge \ when more than one path is expected" ); 0 }); (dest_id, i, edges) }) .collect(); expected_indexed.sort_by_key(|(dest, _, _)| *dest); for (i, ((_, actual), (_, _, expected_edges))) in actual_paths.iter().zip(&expected_indexed).enumerate() { assert_eq!( actual.len(), expected_edges.len(), "{label}: path {i} edge count mismatch" ); for (j, (edge, exp)) in actual.iter().zip(expected_edges).enumerate() { for (j, (edge, exp)) in actual.iter().zip(*expected_edges).enumerate() { if let Some(ref from) = exp.from { assert_eq!(&edge.from, from, "{label}: path {i} edge {j} from entity"); } Loading @@ -691,6 +728,9 @@ fn apply_expect(view: &ResponseView, expect: &QueryExpect, label: &str) { if let Some(to_id) = exp.to_id { assert_eq!(edge.to_id, to_id, "{label}: path {i} edge {j} to_id"); } if let Some(step) = exp.step { assert_eq!(edge.step, Some(step), "{label}: path {i} edge {j} step"); } } } } Loading crates/integration-tests/tests/server/data_correctness/scenarios/pagination/null_sort_keys_desc.yaml 0 → 100644 +22 −0 Changes for crates/integration-tests/tests/server/data_correctness/scenarios/pagination/null_sort_keys_desc.yaml: 22 added lines, 0 removed lines. Original line number Diff line number Diff line # source: crates/integration-tests/tests/server/data_correctness/pagination.rs::cursor_pages_across_null_sort_keys description: Pages across NULL merged_at sort keys in DESC order cover all 6 MRs query: json: | { "query_type": "traversal", "nodes": [{"id": "mr", "entity": "MergeRequest", "id_range": {"start": 1, "end": 10000}, "columns": ["title"]}], "order_by": "-mr.merged_at", "cursor": {"page_size": 2} } expect: all_pages: node_ids: MergeRequest: [2000, 2001, 2002, 2003, 2004, 2005] no_duplicate_ids: true pages: - skip_requirements: [cursor, node_count, order_by] - skip_requirements: [cursor, node_count, order_by] - skip_requirements: [cursor, node_count, order_by] crates/integration-tests/tests/server/data_correctness/scenarios/path_finding/consecutive_edges_connect.yaml +4 −4 Changes for crates/integration-tests/tests/server/data_correctness/scenarios/path_finding/consecutive_edges_connect.yaml: 4 added lines, 4 removed lines. Original line number Diff line number Diff line Loading @@ -19,7 +19,7 @@ expect: path_destinations: Project: [1000, 1004] path_edges: - - { from: User, from_id: 1, type: MEMBER_OF } - { type: CONTAINS, to: Project } - - { from: User, from_id: 1, type: MEMBER_OF } - { type: CONTAINS, to: Project } - [{ from: User, from_id: 1, type: MEMBER_OF }, { type: CONTAINS, to: Project, to_id: 1000 }] - [{ from: User, from_id: 1, type: MEMBER_OF }, { type: CONTAINS, to: Project, to_id: 1004 }] crates/integration-tests/tests/server/data_correctness/scenarios/path_finding/filtered_start_endpoint.yaml +2 −2 Changes for crates/integration-tests/tests/server/data_correctness/scenarios/path_finding/filtered_start_endpoint.yaml: 2 added lines, 2 removed lines. Original line number Diff line number Diff line Loading @@ -21,5 +21,5 @@ expect: filters: username: { eq: alice } path_edges: - - { from: User, from_id: 1, type: MEMBER_OF } - { type: CONTAINS, to: Project, to_id: 1004 } - [{ from: User, from_id: 1, type: MEMBER_OF }, { type: CONTAINS, to: Project, to_id: 1004 }] Loading
crates/integration-testkit/src/query_scenario/format.rs +13 −0 Changes for crates/integration-testkit/src/query_scenario/format.rs: 13 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -293,4 +293,17 @@ pub struct PathEdgeExpect { pub to: Option<String>, #[serde(default)] pub to_id: Option<i64>, #[serde(default)] pub step: Option<usize>, } impl PathEdgeExpect { pub fn has_assertions(&self) -> bool { self.from.is_some() || self.from_id.is_some() || self.edge_type.is_some() || self.to.is_some() || self.to_id.is_some() || self.step.is_some() } }
crates/integration-testkit/src/query_scenario/mod.rs +43 −3 Changes for crates/integration-testkit/src/query_scenario/mod.rs: 43 added lines, 3 removed lines. Original line number Diff line number Diff line Loading @@ -660,6 +660,14 @@ fn apply_expect(view: &ResponseView, expect: &QueryExpect, label: &str) { } } if !expect.path_edges.is_empty() { for (pi, path_exp) in expect.path_edges.iter().enumerate() { for (ei, edge_exp) in path_exp.iter().enumerate() { assert!( edge_exp.has_assertions(), "{label}: path_edges[{pi}][{ei}] has no assertions (all fields omitted)" ); } } let pids = view.path_ids(); assert_eq!( pids.len(), Loading @@ -668,14 +676,43 @@ fn apply_expect(view: &ResponseView, expect: &QueryExpect, label: &str) { expect.path_edges.len(), pids.len() ); for (i, (&pid, expected_edges)) in pids.iter().zip(&expect.path_edges).enumerate() { let actual = view.path(pid); // Sort both actual paths and expected paths by destination ID // so the zip is deterministic regardless of path_ids() ordering. let mut actual_paths: Vec<_> = pids .iter() .map(|&pid| { let edges = view.path(pid); let dest_id = edges.last().map_or(0, |e| e.to_id); (dest_id, edges) }) .collect(); actual_paths.sort_by_key(|(dest, _)| *dest); let mut expected_indexed: Vec<_> = expect .path_edges .iter() .enumerate() .map(|(i, edges)| { let dest_id = edges.last().and_then(|e| e.to_id).unwrap_or_else(|| { assert!( expect.path_edges.len() == 1, "{label}: path_edges[{i}] must set to_id on its last edge \ when more than one path is expected" ); 0 }); (dest_id, i, edges) }) .collect(); expected_indexed.sort_by_key(|(dest, _, _)| *dest); for (i, ((_, actual), (_, _, expected_edges))) in actual_paths.iter().zip(&expected_indexed).enumerate() { assert_eq!( actual.len(), expected_edges.len(), "{label}: path {i} edge count mismatch" ); for (j, (edge, exp)) in actual.iter().zip(expected_edges).enumerate() { for (j, (edge, exp)) in actual.iter().zip(*expected_edges).enumerate() { if let Some(ref from) = exp.from { assert_eq!(&edge.from, from, "{label}: path {i} edge {j} from entity"); } Loading @@ -691,6 +728,9 @@ fn apply_expect(view: &ResponseView, expect: &QueryExpect, label: &str) { if let Some(to_id) = exp.to_id { assert_eq!(edge.to_id, to_id, "{label}: path {i} edge {j} to_id"); } if let Some(step) = exp.step { assert_eq!(edge.step, Some(step), "{label}: path {i} edge {j} step"); } } } } Loading
crates/integration-tests/tests/server/data_correctness/scenarios/pagination/null_sort_keys_desc.yaml 0 → 100644 +22 −0 Changes for crates/integration-tests/tests/server/data_correctness/scenarios/pagination/null_sort_keys_desc.yaml: 22 added lines, 0 removed lines. Original line number Diff line number Diff line # source: crates/integration-tests/tests/server/data_correctness/pagination.rs::cursor_pages_across_null_sort_keys description: Pages across NULL merged_at sort keys in DESC order cover all 6 MRs query: json: | { "query_type": "traversal", "nodes": [{"id": "mr", "entity": "MergeRequest", "id_range": {"start": 1, "end": 10000}, "columns": ["title"]}], "order_by": "-mr.merged_at", "cursor": {"page_size": 2} } expect: all_pages: node_ids: MergeRequest: [2000, 2001, 2002, 2003, 2004, 2005] no_duplicate_ids: true pages: - skip_requirements: [cursor, node_count, order_by] - skip_requirements: [cursor, node_count, order_by] - skip_requirements: [cursor, node_count, order_by]
crates/integration-tests/tests/server/data_correctness/scenarios/path_finding/consecutive_edges_connect.yaml +4 −4 Changes for crates/integration-tests/tests/server/data_correctness/scenarios/path_finding/consecutive_edges_connect.yaml: 4 added lines, 4 removed lines. Original line number Diff line number Diff line Loading @@ -19,7 +19,7 @@ expect: path_destinations: Project: [1000, 1004] path_edges: - - { from: User, from_id: 1, type: MEMBER_OF } - { type: CONTAINS, to: Project } - - { from: User, from_id: 1, type: MEMBER_OF } - { type: CONTAINS, to: Project } - [{ from: User, from_id: 1, type: MEMBER_OF }, { type: CONTAINS, to: Project, to_id: 1000 }] - [{ from: User, from_id: 1, type: MEMBER_OF }, { type: CONTAINS, to: Project, to_id: 1004 }]
crates/integration-tests/tests/server/data_correctness/scenarios/path_finding/filtered_start_endpoint.yaml +2 −2 Changes for crates/integration-tests/tests/server/data_correctness/scenarios/path_finding/filtered_start_endpoint.yaml: 2 added lines, 2 removed lines. Original line number Diff line number Diff line Loading @@ -21,5 +21,5 @@ expect: filters: username: { eq: alice } path_edges: - - { from: User, from_id: 1, type: MEMBER_OF } - { type: CONTAINS, to: Project, to_id: 1004 } - [{ from: User, from_id: 1, type: MEMBER_OF }, { type: CONTAINS, to: Project, to_id: 1004 }]