Fix duplicated operator handling
Looking at this TS change !261 (merged) and comparing it with the Rust version, the Rust version seems to be allowing duplicate operators on the same field.
TS checks for different fields and operators:
// multiple operators on the same field
describe.each`
field
${"created"}
${"updated"}
${"closed"}
`("field: $field", ({ field }) => {
test.each`
operator | operatorDescription
${"="} | ${"equals"}
${">"} | ${"greater than"}
${">="} | ${"greater than or equal to"}
${"<"} | ${"less than"}
${"<="} | ${"less than or equal to"}
`(
`${field} $operator 2024-01-01 AND ${field} $operator 2024-01-01`,
({ operator, operatorDescription }) => {
expect(
compileGraphQL(
`${field} ${operator} 2024-01-01 AND ${field} ${operator} 2024-01-01`
)
).toBe(
`Error: Operator ${operatorDescription} (\`${operator}\`) can only be used once with \`${field}\`.`
);
}
);
});
describe.each`
field
${"confidential"}
`("field: $field", ({ field }) => {
test.each`
operator | operatorDescription
${"="} | ${"equals"}
`(
`${field} $operator true AND ${field} $operator false`,
({ operator, operatorDescription }) => {
expect(
compileGraphQL(
`${field} ${operator} true AND ${field} ${operator} false`
)
).toBe(
`Error: Operator ${operatorDescription} (\`${operator}\`) cansed once with \`${field}\`.`
);
}
);
});
While Rust version only validates duplicate `in` operators, not other operators
fn test_multiple_in_for_same_field() {
assert_eq!(
compile_graphql("label IN (\"foo\") AND label IN (\"bar\")"),
"Error: The is one of (`in`) operator can only be used once with `label`."
);
}
But if we translate the same test cases (feat. Duo), the test fails:
#[rstest]
#[case::created_equals("created", "=", "equals")]
#[case::created_gt("created", ">", "greater than")]
#[case::created_gte("created", ">=", "greater than or equal to")]
#[case::created_lt("created", "<", "less than")]
#[case::created_lte("created", "<=", "less than or equal to")]
#[case::updated_equals("updated", "=", "equals")]
#[case::updated_gt("updated", ">", "greater than")]
#[case::updated_gte("updated", ">=", "greater than or equal to")]
#[case::updated_lt("updated", "<", "less than")]
#[case::updated_lte("updated", "<=", "less than or equal to")]
#[case::closed_equals("closed", "=", "equals")]
#[case::closed_gt("closed", ">", "greater than")]
#[case::closed_gte("closed", ">=", "greater than or equal to")]
#[case::closed_lt("closed", "<", "less than")]
#[case::closed_lte("closed", "<=", "less than or equal to")]
fn test_duplicate_operator_on_date_field(
#[case] field: &str,
#[case] operator: &str,
#[case] operator_desc: &str,
) {
let query = format!("{} {} 2024-01-01 AND {} {} 2024-02-01", field, operator, field, operator);
let expected = format!(
"Error: Operator {} (`{}`) can only be used once with `{}`.",
operator_desc, operator, field
);
assert_eq!(compile_graphql(&query), expected);
}
#[test]
fn test_duplicate_equals_on_confidential() {
assert_eq!(
compile_graphql("confidential = true AND confidential = false"),
"Error: Operator equals (`=`) can only be used once with `confidential`."
);
}
#[test]
fn test_valid_different_operators_on_same_field() {
// This test verifies that DIFFERENT operators on the same field are allowed
// e.g., label = 'foo' AND label in ('bar') should work
assert_eq!(
compile_graphql("label = (\"foo\") AND label in (\"bar\")")
.lines()
.nth(1)
.unwrap(),
" issues(labelName: [\"foo\"], or: {labelNames: [\"bar\"]}, before: $before, after: $after, first: $limit) {"
);
}
failures:
test_duplicate_equals_on_confidential
test_duplicate_operator_on_date_field::case_01_created_equals
test_duplicate_operator_on_date_field::case_02_created_gt
test_duplicate_operator_on_date_field::case_03_created_gte
test_duplicate_operator_on_date_field::case_04_created_lt
test_duplicate_operator_on_date_field::case_05_created_lte
test_duplicate_operator_on_date_field::case_06_updated_equals
test_duplicate_operator_on_date_field::case_07_updated_gt
test_duplicate_operator_on_date_field::case_08_updated_gte
test_duplicate_operator_on_date_field::case_09_updated_lt
test_duplicate_operator_on_date_field::case_10_updated_lte
test_duplicate_operator_on_date_field::case_11_closed_equals
test_duplicate_operator_on_date_field::case_12_closed_gt
test_duplicate_operator_on_date_field::case_13_closed_gte
test_duplicate_operator_on_date_field::case_14_closed_lt
test_duplicate_operator_on_date_field::case_15_closed_lte
Edited by Daniele Rossetti