// Copyright (c) 2026, Salesforce, Inc.,
// All rights reserved.
// For full license text, see the LICENSE.txt file
#[cfg(test)]
#[allow(clippy::module_inception)]
mod test_grammar {
    use std::path::PathBuf;

    use crate::dw::{dw_parser, AstNode, ComparisonType, ImportedElement, Location, LogicalType};

    #[test]
    fn str_interpolation() {
        test_scenario("str_interpolation".to_string());
    }

    #[test]
    fn test_complex() {
        test_scenario("complex".to_string());
    }

    #[test]
    fn simple_object() {
        test_scenario("simple_object".to_string());
    }

    #[test]
    fn selectors() {
        test_scenario("selectors".to_string());
    }

    #[test]
    fn simple_array() {
        test_scenario("simple_array".to_string());
    }

    #[test]
    fn namespaces() {
        test_scenario("namespace".to_string());
    }

    fn test_scenario(name: String) {
        let code = std::fs::read_to_string(weave_code(&name).as_os_str()).unwrap();
        let result = dw_parser::parse(code.as_str());
        let node = result.unwrap();
        let ast_string = node.to_string();
        let actual = ast_string.trim();
        let ast_expected = std::fs::read_to_string(expected_ast(&name).as_os_str()).unwrap();
        let expected = ast_expected.trim();
        if !actual.eq(expected) {
            println!("{actual}");
        }

        assert_eq!(actual.to_string(), expected.to_string());
    }

    fn expected_ast(name: &String) -> PathBuf {
        let mut d = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
        d.push(format!("./resources/test/parser/{name}.ast"));
        d
    }

    fn weave_code(name: &String) -> PathBuf {
        let mut d = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
        d.push(format!("./resources/test/parser/{name}.dwl"));
        d
    }

    #[test]
    fn output_directive_with_options() {
        let result = dw_parser::parse("output rust id=123 --- true");
        if let AstNode::Document { header, .. } = result.unwrap() {
            let directive = header.unwrap().first().unwrap().to_owned();
            assert_eq!(
                directive,
                AstNode::OutputDirective {
                    data_format: Box::new(AstNode::NameIdentifier {
                        name: vec!["rust".to_string()],
                        location: Location { start: 7, end: 11 },
                    }),
                    options: vec![AstNode::Option {
                        name: Box::new(AstNode::NameIdentifier {
                            name: vec!["id".to_string()],
                            location: Location { start: 12, end: 14 },
                        }),
                        value: Box::new(AstNode::Number {
                            value: "123".to_string(),
                            location: Location { start: 15, end: 18 },
                        }),
                        location: Location { start: 12, end: 18 },
                    }],
                    location: Location { start: 0, end: 18 },
                }
            )
        }
    }

    #[test]
    fn output_directive() {
        let result = dw_parser::parse("output application/rust\n --- \ntrue");
        if let AstNode::Document { header, .. } = result.unwrap() {
            let directive = header.unwrap().first().unwrap().to_owned();
            assert_eq!(
                directive,
                AstNode::OutputDirective {
                    data_format: Box::new(AstNode::ContentType {
                        value: "application/rust".to_string(),
                        location: Location { start: 7, end: 23 },
                    }),
                    options: vec![],
                    location: Location { start: 0, end: 25 },
                }
            )
        }
    }

    #[test]
    fn input_directive_with_options() {
        let result = dw_parser::parse("input value rust id=123 --- true");
        if let AstNode::Document { header, .. } = result.unwrap() {
            let directive = header.unwrap().first().unwrap().to_owned();
            assert_eq!(
                directive,
                AstNode::InputDirective {
                    name: Box::new(AstNode::NameIdentifier {
                        name: vec!["value".to_string()],
                        location: Location { start: 6, end: 11 },
                    }),
                    data_format: Box::new(AstNode::NameIdentifier {
                        name: vec!["rust".to_string()],
                        location: Location { start: 12, end: 16 },
                    }),
                    options: vec![AstNode::Option {
                        name: Box::new(AstNode::NameIdentifier {
                            name: vec!["id".to_string()],
                            location: Location { start: 17, end: 19 },
                        }),
                        value: Box::new(AstNode::Number {
                            value: "123".to_string(),
                            location: Location { start: 20, end: 23 },
                        }),
                        location: Location { start: 17, end: 23 },
                    }],
                    location: Location { start: 0, end: 23 },
                }
            )
        }
    }

    #[test]
    fn input_directive() {
        let result = dw_parser::parse("input value application/rust\n --- \ntrue");
        if let AstNode::Document { header, .. } = result.unwrap() {
            let directive = header.unwrap().first().unwrap().to_owned();
            assert_eq!(
                directive,
                AstNode::InputDirective {
                    name: Box::new(AstNode::NameIdentifier {
                        name: vec!["value".to_string()],
                        location: Location { start: 6, end: 11 },
                    }),
                    data_format: Box::new(AstNode::ContentType {
                        value: "application/rust".to_string(),
                        location: Location { start: 12, end: 28 },
                    }),
                    options: vec![],
                    location: Location { start: 0, end: 30 },
                }
            )
        }
    }

    #[test]
    fn import_star_directive() {
        let result = dw_parser::parse("import * from dw::Strings\n --- \ntrue");
        if let AstNode::Document { header, .. } = result.unwrap() {
            let directive = header.unwrap().first().unwrap().to_owned();
            assert_eq!(
                directive,
                AstNode::ImportDirective {
                    module: Box::new(ImportedElement {
                        name: Box::new(AstNode::NameIdentifier {
                            name: vec!["dw".to_string(), "Strings".to_string()],
                            location: Location { start: 14, end: 25 },
                        }),
                        alias: None,
                        location: Location { start: 13, end: 25 },
                    }),
                    elements: vec![ImportedElement {
                        name: Box::new(AstNode::NameIdentifier {
                            name: vec!["*".to_string()],
                            location: Location { start: 7, end: 8 },
                        }),
                        alias: None,
                        location: Location { start: 7, end: 8 },
                    }],
                    location: Location { start: 0, end: 25 },
                }
            )
        }
    }

    #[test]
    fn import_element_alias_directive() {
        let result = dw_parser::parse("import test as t  from dw::Strings\n --- \ntrue");
        if let AstNode::Document { header, .. } = result.unwrap() {
            let directive = header.unwrap().first().unwrap().to_owned();
            assert_eq!(
                directive,
                AstNode::ImportDirective {
                    module: Box::new(ImportedElement {
                        name: Box::new(AstNode::NameIdentifier {
                            name: vec!["dw".to_string(), "Strings".to_string()],
                            location: Location { start: 23, end: 34 },
                        }),
                        alias: None,
                        location: Location { start: 22, end: 34 },
                    }),
                    elements: vec![ImportedElement {
                        name: Box::new(AstNode::NameIdentifier {
                            name: vec!["test".to_string()],
                            location: Location { start: 7, end: 11 },
                        }),
                        alias: Some(AstNode::NameIdentifier {
                            name: vec!["t".to_string()],
                            location: Location { start: 15, end: 16 },
                        }),
                        location: Location { start: 7, end: 16 },
                    }],
                    location: Location { start: 0, end: 34 },
                }
            )
        }
    }

    #[test]
    fn import_module_directive() {
        let result = dw_parser::parse("import dw::Strings\n --- \ntrue");
        if let AstNode::Document { header, .. } = result.unwrap() {
            let directive = header.unwrap().first().unwrap().to_owned();
            assert_eq!(
                directive,
                AstNode::ImportDirective {
                    module: Box::new(ImportedElement {
                        name: Box::new(AstNode::NameIdentifier {
                            name: vec!["dw".to_string(), "Strings".to_string()],
                            location: Location { start: 7, end: 18 },
                        }),
                        alias: None,
                        location: Location { start: 7, end: 18 },
                    }),
                    elements: vec![],
                    location: Location { start: 0, end: 18 },
                }
            )
        }
    }

    #[test]
    fn import_element_directive() {
        let result = dw_parser::parse("import test from dw::Strings\n --- \ntrue");
        if let AstNode::Document { header, .. } = result.unwrap() {
            let directive = header.unwrap().first().unwrap().to_owned();
            assert_eq!(
                directive,
                AstNode::ImportDirective {
                    module: Box::new(ImportedElement {
                        name: Box::new(AstNode::NameIdentifier {
                            name: vec!["dw".to_string(), "Strings".to_string()],
                            location: Location { start: 17, end: 28 },
                        }),
                        alias: None,
                        location: Location { start: 16, end: 28 },
                    }),
                    elements: vec![ImportedElement {
                        name: Box::new(AstNode::NameIdentifier {
                            name: vec!["test".to_string()],
                            location: Location { start: 7, end: 11 },
                        }),
                        alias: None,
                        location: Location { start: 7, end: 11 },
                    }],
                    location: Location { start: 0, end: 28 },
                }
            )
        }
    }

    #[test]
    fn version_directive() {
        let result = dw_parser::parse("%dw 2.0\n --- \n|P12Y7M11D|");
        assert_eq!(
            result,
            Ok(AstNode::Document {
                header: Some(vec![AstNode::VersionDirective {
                    version: "2.0".to_string(),
                    location: Location { start: 0, end: 7 },
                }]),
                body: Box::new(AstNode::Period {
                    value: "P12Y7M11D".to_string(),
                    location: Location { start: 14, end: 25 },
                }),
                location: Location { start: 0, end: 25 },
            })
        );
    }

    #[test]
    fn period() {
        let result = dw_parser::parse("|P12Y7M11D|");
        assert_eq!(
            result,
            Ok(AstNode::Document {
                header: None,
                body: Box::new(AstNode::Period {
                    value: "P12Y7M11D".to_string(),
                    location: Location { start: 0, end: 11 },
                }),
                location: Location { start: 0, end: 11 },
            })
        );

        let result = dw_parser::parse("|P12Y5M|");
        assert_eq!(
            result,
            Ok(AstNode::Document {
                header: None,
                body: Box::new(AstNode::Period {
                    value: "P12Y5M".to_string(),
                    location: Location { start: 0, end: 8 },
                }),
                location: Location { start: 0, end: 8 },
            })
        );

        let result = dw_parser::parse("|P45DT9H20M8S|");
        assert_eq!(
            result,
            Ok(AstNode::Document {
                header: None,
                body: Box::new(AstNode::Period {
                    value: "P45DT9H20M8S".to_string(),
                    location: Location { start: 0, end: 14 },
                }),
                location: Location { start: 0, end: 14 },
            })
        );

        let result = dw_parser::parse("|PT9H20M8S|");
        assert_eq!(
            result,
            Ok(AstNode::Document {
                header: None,
                body: Box::new(AstNode::Period {
                    value: "PT9H20M8S".to_string(),
                    location: Location { start: 0, end: 11 },
                }),
                location: Location { start: 0, end: 11 },
            })
        );

        let result = dw_parser::parse("|P1DT1H10M10.5S|");
        assert_eq!(
            result,
            Ok(AstNode::Document {
                header: None,
                body: Box::new(AstNode::Period {
                    value: "P1DT1H10M10.5S".to_string(),
                    location: Location { start: 0, end: 16 },
                }),
                location: Location { start: 0, end: 16 },
            })
        );

        let result = dw_parser::parse("|P-12Y-7M-11D|");
        assert_eq!(
            result,
            Ok(AstNode::Document {
                header: None,
                body: Box::new(AstNode::Period {
                    value: "P-12Y-7M-11D".to_string(),
                    location: Location { start: 0, end: 14 },
                }),
                location: Location { start: 0, end: 14 },
            })
        );

        let result = dw_parser::parse("|PT-1H|");
        assert_eq!(
            result,
            Ok(AstNode::Document {
                header: None,
                body: Box::new(AstNode::Period {
                    value: "PT-1H".to_string(),
                    location: Location { start: 0, end: 7 },
                }),
                location: Location { start: 0, end: 7 },
            })
        );
    }

    #[test]
    fn time() {
        let result = dw_parser::parse("|23:50:30Z|");
        assert_eq!(
            result,
            Ok(AstNode::Document {
                header: None,
                body: Box::new(AstNode::Time {
                    value: "23:50:30Z".to_string(),
                    location: Location { start: 0, end: 11 },
                }),
                location: Location { start: 0, end: 11 },
            })
        );
    }

    #[test]
    fn local_time() {
        let result = dw_parser::parse("|23:57:59|");
        assert_eq!(
            result,
            Ok(AstNode::Document {
                header: None,
                body: Box::new(AstNode::LocalTime {
                    value: "23:57:59".to_string(),
                    location: Location { start: 0, end: 10 },
                }),
                location: Location { start: 0, end: 10 },
            })
        );

        let result = dw_parser::parse("|23:57:30.700|");
        assert_eq!(
            result,
            Ok(AstNode::Document {
                header: None,
                body: Box::new(AstNode::LocalTime {
                    value: "23:57:30.700".to_string(),
                    location: Location { start: 0, end: 14 },
                }),
                location: Location { start: 0, end: 14 },
            })
        );
    }

    #[test]
    fn date() {
        let result = dw_parser::parse("|2003-10-01|");
        assert_eq!(
            result,
            Ok(AstNode::Document {
                header: None,
                body: Box::new(AstNode::Date {
                    value: "2003-10-01".to_string(),
                    location: Location { start: 0, end: 12 },
                }),
                location: Location { start: 0, end: 12 },
            })
        );

        let result = dw_parser::parse("|2005-045|");
        assert_eq!(
            result,
            Ok(AstNode::Document {
                header: None,
                body: Box::new(AstNode::Date {
                    value: "2005-045".to_string(),
                    location: Location { start: 0, end: 10 },
                }),
                location: Location { start: 0, end: 10 },
            })
        );

        let result = dw_parser::parse("|2003-W14-3|");
        assert_eq!(
            result,
            Ok(AstNode::Document {
                header: None,
                body: Box::new(AstNode::Date {
                    value: "2003-W14-3".to_string(),
                    location: Location { start: 0, end: 12 },
                }),
                location: Location { start: 0, end: 12 },
            })
        );
    }

    #[test]
    fn local_date_time() {
        let result = dw_parser::parse("|2005-06-02T15:10:16|");
        assert_eq!(
            result,
            Ok(AstNode::Document {
                header: None,
                body: Box::new(AstNode::LocalDateTime {
                    value: "2005-06-02T15:10:16".to_string(),
                    location: Location { start: 0, end: 21 },
                }),
                location: Location { start: 0, end: 21 },
            })
        );
    }

    #[test]
    fn date_time() {
        let result = dw_parser::parse("|2005-06-02T15:10:16Z|");
        assert_eq!(
            result,
            Ok(AstNode::Document {
                header: None,
                body: Box::new(AstNode::DateTime {
                    value: "2005-06-02T15:10:16Z".to_string(),
                    location: Location { start: 0, end: 22 },
                }),
                location: Location { start: 0, end: 22 },
            })
        );

        let result = dw_parser::parse("|2005-06-02T15:10:16+03:00|");
        assert_eq!(
            result,
            Ok(AstNode::Document {
                header: None,
                body: Box::new(AstNode::DateTime {
                    value: "2005-06-02T15:10:16+03:00".to_string(),
                    location: Location { start: 0, end: 27 },
                }),
                location: Location { start: 0, end: 27 },
            })
        );

        let result = dw_parser::parse("|2020-10-08T11:44:45.476955-03:00|");
        assert_eq!(
            result,
            Ok(AstNode::Document {
                header: None,
                body: Box::new(AstNode::DateTime {
                    value: "2020-10-08T11:44:45.476955-03:00".to_string(),
                    location: Location { start: 0, end: 34 },
                }),
                location: Location { start: 0, end: 34 },
            })
        );
    }

    #[test]
    fn test_block_comments() {
        let result = dw_parser::parse("/*test*/payload  \n[\"name\"] ");
        assert_eq!(
            result,
            Ok(AstNode::Document {
                header: None,
                body: Box::new(AstNode::ValueSelector {
                    lhs: Box::new(AstNode::VariableReference {
                        reference: Box::new(AstNode::NameIdentifier {
                            name: vec!["payload".to_owned()],
                            location: Location { start: 8, end: 15 },
                        },),
                        location: Location { start: 8, end: 15 },
                    }),
                    rhs: Box::new(AstNode::Str {
                        value: "name".to_owned(),
                        quote: Some('"'),
                        location: Location { start: 19, end: 25 },
                    }),
                    location: Location { start: 8, end: 26 },
                }),
                location: Location { start: 0, end: 27 },
            })
        );
    }

    #[test]
    fn test_line_comments() {
        let result = dw_parser::parse("//test\npayload  \n[\"name\"] ");
        assert_eq!(
            result,
            Ok(AstNode::Document {
                header: None,
                body: Box::new(AstNode::ValueSelector {
                    lhs: Box::new(AstNode::VariableReference {
                        reference: Box::new(AstNode::NameIdentifier {
                            name: vec!["payload".to_owned()],
                            location: Location { start: 7, end: 14 },
                        }),
                        location: Location { start: 7, end: 14 },
                    }),
                    rhs: Box::new(AstNode::Str {
                        value: "name".to_owned(),
                        quote: Some('"'),
                        location: Location { start: 18, end: 24 },
                    }),
                    location: Location { start: 7, end: 25 },
                }),
                location: Location { start: 0, end: 26 },
            })
        );
    }

    #[test]
    fn test_value_selector_square() {
        let result = dw_parser::parse("payload[\"name\"]");
        assert_eq!(
            result,
            Ok(AstNode::Document {
                header: None,
                body: Box::new(AstNode::ValueSelector {
                    lhs: Box::new(AstNode::VariableReference {
                        reference: Box::new(AstNode::NameIdentifier {
                            name: vec!["payload".to_owned()],
                            location: Location { start: 0, end: 7 },
                        }),
                        location: Location { start: 0, end: 7 },
                    }),
                    rhs: Box::new(AstNode::Str {
                        value: "name".to_owned(),
                        quote: Some('"'),
                        location: Location { start: 8, end: 14 },
                    }),
                    location: Location { start: 0, end: 15 },
                }),
                location: Location { start: 0, end: 15 },
            })
        );
    }

    #[test]
    fn test_function_call() {
        let result = dw_parser::parse("max(123)");
        assert_eq!(
            result,
            Ok(AstNode::Document {
                header: None,
                body: Box::new(AstNode::FunctionCall {
                    lhs: Box::new(AstNode::VariableReference {
                        reference: Box::new(AstNode::NameIdentifier {
                            name: vec!["max".to_owned()],
                            location: Location { start: 0, end: 3 },
                        }),
                        location: Location { start: 0, end: 3 },
                    }),
                    args: vec![AstNode::Number {
                        value: "123".to_string(),
                        location: Location { start: 4, end: 7 },
                    }],
                    location: Location { start: 0, end: 8 },
                }),
                location: Location { start: 0, end: 8 },
            })
        );
    }

    #[test]
    fn test_not_word() {
        let result = dw_parser::parse("not true <= false");
        assert_eq!(
            result,
            Ok(AstNode::Document {
                header: None,
                body: Box::new(AstNode::Not {
                    rhs: Box::new(AstNode::Comparison {
                        lhs: Box::new(AstNode::Boolean {
                            value: true,
                            location: Location { start: 4, end: 8 },
                        }),
                        rhs: Box::new(AstNode::Boolean {
                            value: false,
                            location: Location { start: 12, end: 17 },
                        }),
                        comp: ComparisonType::LessEqual,
                        location: Location { start: 3, end: 17 },
                    }),
                    location: Location { start: 0, end: 17 },
                }),
                location: Location { start: 0, end: 17 },
            })
        );
    }

    #[test]
    fn test_not_excl() {
        let result = dw_parser::parse("!true <= false");
        assert_eq!(
            result,
            Ok(AstNode::Document {
                header: None,
                body: Box::new(AstNode::Comparison {
                    lhs: Box::new(AstNode::Not {
                        rhs: Box::new(AstNode::Boolean {
                            value: true,
                            location: Location { start: 1, end: 5 },
                        }),
                        location: Location { start: 0, end: 6 },
                    }),
                    rhs: Box::new(AstNode::Boolean {
                        value: false,
                        location: Location { start: 9, end: 14 },
                    }),
                    comp: ComparisonType::LessEqual,
                    location: Location { start: 0, end: 14 },
                }),
                location: Location { start: 0, end: 14 },
            })
        );
    }

    #[test]
    fn test_less_eq() {
        let result = dw_parser::parse("true <= false");
        assert_eq!(
            result,
            Ok(AstNode::Document {
                header: None,
                body: Box::new(AstNode::Comparison {
                    lhs: Box::new(AstNode::Boolean {
                        value: true,
                        location: Location { start: 0, end: 4 },
                    }),
                    rhs: Box::new(AstNode::Boolean {
                        value: false,
                        location: Location { start: 8, end: 13 },
                    }),
                    comp: ComparisonType::LessEqual,
                    location: Location { start: 0, end: 13 },
                }),
                location: Location { start: 0, end: 13 },
            })
        );
    }

    #[test]
    fn test_less() {
        let result = dw_parser::parse("true < false");
        assert_eq!(
            result,
            Ok(AstNode::Document {
                header: None,
                body: Box::new(AstNode::Comparison {
                    lhs: Box::new(AstNode::Boolean {
                        value: true,
                        location: Location { start: 0, end: 4 },
                    }),
                    rhs: Box::new(AstNode::Boolean {
                        value: false,
                        location: Location { start: 7, end: 12 },
                    }),
                    comp: ComparisonType::Less,
                    location: Location { start: 0, end: 12 },
                }),
                location: Location { start: 0, end: 12 },
            })
        );
    }

    #[test]
    fn test_greater_eq() {
        let result = dw_parser::parse("true >= false");
        assert_eq!(
            result,
            Ok(AstNode::Document {
                header: None,
                body: Box::new(AstNode::Comparison {
                    lhs: Box::new(AstNode::Boolean {
                        value: true,
                        location: Location { start: 0, end: 4 },
                    }),
                    rhs: Box::new(AstNode::Boolean {
                        value: false,
                        location: Location { start: 8, end: 13 },
                    }),
                    comp: ComparisonType::GreaterEqual,
                    location: Location { start: 0, end: 13 },
                }),
                location: Location { start: 0, end: 13 },
            })
        );
    }

    #[test]
    fn test_greater() {
        let result = dw_parser::parse("true > false");
        assert_eq!(
            result,
            Ok(AstNode::Document {
                header: None,
                body: Box::new(AstNode::Comparison {
                    lhs: Box::new(AstNode::Boolean {
                        value: true,
                        location: Location { start: 0, end: 4 },
                    }),
                    rhs: Box::new(AstNode::Boolean {
                        value: false,
                        location: Location { start: 7, end: 12 },
                    }),
                    comp: ComparisonType::Greater,
                    location: Location { start: 0, end: 12 },
                }),
                location: Location { start: 0, end: 12 },
            })
        );
    }

    #[test]
    fn test_not_eq() {
        let result = dw_parser::parse("true != false");
        assert_eq!(
            result,
            Ok(AstNode::Document {
                header: None,
                body: Box::new(AstNode::Comparison {
                    lhs: Box::new(AstNode::Boolean {
                        value: true,
                        location: Location { start: 0, end: 4 },
                    }),
                    rhs: Box::new(AstNode::Boolean {
                        value: false,
                        location: Location { start: 8, end: 13 },
                    }),
                    comp: ComparisonType::NotEqual,
                    location: Location { start: 0, end: 13 },
                }),
                location: Location { start: 0, end: 13 },
            })
        );
    }

    #[test]
    fn test_similar() {
        let result = dw_parser::parse("true = false");
        assert_eq!(
            result,
            Ok(AstNode::Document {
                header: None,
                body: Box::new(AstNode::Comparison {
                    lhs: Box::new(AstNode::Boolean {
                        value: true,
                        location: Location { start: 0, end: 4 },
                    }),
                    rhs: Box::new(AstNode::Boolean {
                        value: false,
                        location: Location { start: 7, end: 12 },
                    }),
                    comp: ComparisonType::Similar,
                    location: Location { start: 0, end: 12 },
                }),
                location: Location { start: 0, end: 12 },
            })
        );
    }

    #[test]
    fn test_eq() {
        let result = dw_parser::parse("true == false");
        assert_eq!(
            result,
            Ok(AstNode::Document {
                header: None,
                body: Box::new(AstNode::Comparison {
                    lhs: Box::new(AstNode::Boolean {
                        value: true,
                        location: Location { start: 0, end: 4 },
                    }),
                    rhs: Box::new(AstNode::Boolean {
                        value: false,
                        location: Location { start: 8, end: 13 },
                    }),
                    comp: ComparisonType::Equal,
                    location: Location { start: 0, end: 13 },
                }),
                location: Location { start: 0, end: 13 },
            })
        );
    }

    #[test]
    fn test_or() {
        let result = dw_parser::parse("true or false");
        assert_eq!(
            result,
            Ok(AstNode::Document {
                header: None,
                body: Box::new(AstNode::Logical {
                    lhs: Box::new(AstNode::Boolean {
                        value: true,
                        location: Location { start: 0, end: 4 },
                    }),
                    rhs: Box::new(AstNode::Boolean {
                        value: false,
                        location: Location { start: 8, end: 13 },
                    }),
                    comp: LogicalType::Or,
                    location: Location { start: 0, end: 13 },
                }),
                location: Location { start: 0, end: 13 },
            })
        );
    }

    #[test]
    fn test_or_chain() {
        let result = dw_parser::parse("true or false or true and true");
        assert_eq!(
            result,
            Ok(AstNode::Document {
                header: None,
                body: Box::new(AstNode::Logical {
                    lhs: Box::new(AstNode::Logical {
                        lhs: Box::new(AstNode::Boolean {
                            value: true,
                            location: Location { start: 0, end: 4 },
                        }),
                        rhs: Box::new(AstNode::Boolean {
                            value: false,
                            location: Location { start: 8, end: 13 },
                        }),
                        comp: LogicalType::Or,
                        location: Location { start: 0, end: 14 },
                    }),
                    rhs: Box::new(AstNode::Logical {
                        lhs: Box::new(AstNode::Boolean {
                            value: true,
                            location: Location { start: 17, end: 21 },
                        }),
                        rhs: Box::new(AstNode::Boolean {
                            value: true,
                            location: Location { start: 26, end: 30 },
                        }),
                        comp: LogicalType::And,
                        location: Location { start: 17, end: 30 },
                    }),
                    comp: LogicalType::Or,
                    location: Location { start: 0, end: 30 },
                }),
                location: Location { start: 0, end: 30 },
            })
        );
    }

    #[test]
    fn test_and() {
        let result = dw_parser::parse("true and false");
        assert_eq!(
            result,
            Ok(AstNode::Document {
                header: None,
                body: Box::new(AstNode::Logical {
                    lhs: Box::new(AstNode::Boolean {
                        value: true,
                        location: Location { start: 0, end: 4 },
                    }),
                    rhs: Box::new(AstNode::Boolean {
                        value: false,
                        location: Location { start: 9, end: 14 },
                    }),
                    comp: LogicalType::And,
                    location: Location { start: 0, end: 14 },
                }),
                location: Location { start: 0, end: 14 },
            })
        );
    }

    #[test]
    fn test_binary_function_call() {
        let result = dw_parser::parse("\"123\" concat 123");
        assert_eq!(
            result,
            Ok(AstNode::Document {
                header: None,
                body: Box::new(AstNode::InfixFunctionCall {
                    lhs: Box::new(AstNode::Str {
                        value: "123".to_owned(),
                        quote: Some('"'),
                        location: Location { start: 0, end: 5 },
                    }),
                    func: Box::new(AstNode::VariableReference {
                        reference: Box::new(AstNode::NameIdentifier {
                            name: vec!["concat".to_owned()],
                            location: Location { start: 6, end: 12 },
                        }),
                        location: Location { start: 6, end: 12 },
                    }),
                    rhs: Box::new(AstNode::Number {
                        value: "123".to_string(),
                        location: Location { start: 13, end: 16 },
                    }),
                    location: Location { start: 0, end: 16 },
                }),
                location: Location { start: 0, end: 16 },
            })
        );
    }

    #[test]
    fn test_if_expr() {
        let result = dw_parser::parse("if (false) 1 else 2");
        assert_eq!(
            result,
            Ok(AstNode::Document {
                header: None,
                body: Box::new(AstNode::IfElse {
                    condition: Box::new(AstNode::Boolean {
                        value: false,
                        location: Location { start: 4, end: 9 },
                    }),
                    if_branch: Box::new(AstNode::Number {
                        value: "1".to_string(),
                        location: Location { start: 11, end: 12 },
                    }),
                    else_branch: Box::new(AstNode::Number {
                        value: "2".to_string(),
                        location: Location { start: 18, end: 19 },
                    }),
                    location: Location { start: 0, end: 19 },
                }),
                location: Location { start: 0, end: 19 },
            })
        );
    }

    #[test]
    fn test_name_identifier() {
        let result = dw_parser::parse("payload");
        assert_eq!(
            result,
            Ok(AstNode::Document {
                header: None,
                body: Box::new(AstNode::VariableReference {
                    reference: Box::new(AstNode::NameIdentifier {
                        name: vec!["payload".to_owned()],
                        location: Location { start: 0, end: 7 },
                    }),
                    location: Location { start: 0, end: 7 },
                }),
                location: Location { start: 0, end: 7 },
            })
        );
    }

    #[test]
    fn enclosed_expression() {
        let result = dw_parser::parse("(payload)");
        assert_eq!(
            result,
            Ok(AstNode::Document {
                header: None,
                body: Box::new(AstNode::VariableReference {
                    reference: Box::new(AstNode::NameIdentifier {
                        name: vec!["payload".to_owned()],
                        location: Location { start: 1, end: 8 },
                    }),
                    location: Location { start: 1, end: 8 },
                }),
                location: Location { start: 0, end: 9 },
            })
        );
    }

    #[test]
    fn test_fqn_identifier() {
        let result = dw_parser::parse("dw::Core::map");
        assert_eq!(
            result,
            Ok(AstNode::Document {
                header: None,
                body: Box::new(AstNode::VariableReference {
                    reference: Box::new(AstNode::NameIdentifier {
                        name: vec!["dw".to_owned(), "Core".to_owned(), "map".to_owned()],
                        location: Location { start: 0, end: 13 },
                    }),
                    location: Location { start: 0, end: 13 },
                }),
                location: Location { start: 0, end: 13 },
            })
        );
    }

    #[test]
    fn test_default_expression() {
        let result = dw_parser::parse("\"a DataWeave Strings\" default 123");
        assert_eq!(
            result,
            Ok(AstNode::Document {
                header: None,
                body: Box::new(AstNode::Default {
                    lhs: Box::new(AstNode::Str {
                        value: "a DataWeave Strings".to_owned(),
                        quote: Some('"'),
                        location: Location { start: 0, end: 21 },
                    }),
                    rhs: Box::new(AstNode::Number {
                        value: "123".to_string(),
                        location: Location { start: 30, end: 33 },
                    }),
                    location: Location { start: 0, end: 33 },
                }),
                location: Location { start: 0, end: 33 },
            })
        );
    }

    #[test]
    fn test_default_selector_expression() {
        let result = dw_parser::parse("payload default \"payload.b\"");
        assert_eq!(
            result,
            Ok(AstNode::Document {
                header: None,
                body: Box::new(AstNode::Default {
                    lhs: Box::new(AstNode::VariableReference {
                        reference: Box::new(AstNode::NameIdentifier {
                            name: vec!["payload".to_owned()],
                            location: Location { start: 0, end: 7 },
                        }),
                        location: Location { start: 0, end: 7 },
                    }),
                    rhs: Box::new(AstNode::Str {
                        value: "payload.b".to_string(),
                        quote: Some('"'),
                        location: Location { start: 16, end: 27 },
                    }),
                    location: Location { start: 0, end: 27 },
                }),
                location: Location { start: 0, end: 27 },
            })
        );
    }

    #[test]
    fn test_chained_default_expression() {
        let result = dw_parser::parse("\"a DataWeave Strings\" default 123 default 456");
        assert_eq!(
            result,
            Ok(AstNode::Document {
                header: None,
                body: Box::new(AstNode::Default {
                    lhs: Box::new(AstNode::Default {
                        lhs: Box::new(AstNode::Str {
                            value: "a DataWeave Strings".to_owned(),
                            quote: Some('"'),
                            location: Location { start: 0, end: 21 },
                        }),
                        rhs: Box::new(AstNode::Number {
                            value: "123".to_string(),
                            location: Location { start: 30, end: 33 },
                        }),
                        location: Location { start: 0, end: 34 },
                    }),
                    rhs: Box::new(AstNode::Number {
                        value: "456".to_string(),
                        location: Location { start: 42, end: 45 },
                    }),
                    location: Location { start: 0, end: 45 },
                }),
                location: Location { start: 0, end: 45 },
            })
        );
    }

    #[test]
    fn test_string() {
        let result = dw_parser::parse("\"a DataWeave Strings\"");
        assert_eq!(
            result,
            Ok(AstNode::Document {
                header: None,
                body: Box::new(AstNode::Str {
                    value: "a DataWeave Strings".to_owned(),
                    quote: Some('"'),
                    location: Location { start: 0, end: 21 },
                }),
                location: Location { start: 0, end: 21 },
            })
        );
    }

    #[test]
    fn test_null() {
        let result = dw_parser::parse("null");
        assert_eq!(
            result,
            Ok(AstNode::Document {
                header: None,
                body: Box::new(AstNode::Null {
                    location: Location { start: 0, end: 4 }
                }),
                location: Location { start: 0, end: 4 },
            })
        );
    }

    #[test]
    fn test_array() {
        let result = dw_parser::parse("[3,4,5]");
        assert_eq!(
            result,
            Ok(AstNode::Document {
                header: None,
                body: Box::new(AstNode::Array {
                    items: vec![
                        AstNode::Number {
                            value: "3".to_string(),
                            location: Location { start: 1, end: 2 },
                        },
                        AstNode::Number {
                            value: "4".to_string(),
                            location: Location { start: 3, end: 4 },
                        },
                        AstNode::Number {
                            value: "5".to_string(),
                            location: Location { start: 5, end: 6 },
                        },
                    ],
                    location: Location { start: 0, end: 7 },
                }),
                location: Location { start: 0, end: 7 },
            })
        );
    }

    #[test]
    fn test_boolean_true() {
        let result = dw_parser::parse("true");
        assert_eq!(
            result,
            Ok(AstNode::Document {
                header: None,
                body: Box::new(AstNode::Boolean {
                    value: true,
                    location: Location { start: 0, end: 4 },
                }),
                location: Location { start: 0, end: 4 },
            })
        );
    }

    #[test]
    fn test_boolean_false() {
        let result = dw_parser::parse("false");
        assert_eq!(
            result,
            Ok(AstNode::Document {
                header: None,
                body: Box::new(AstNode::Boolean {
                    value: false,
                    location: Location { start: 0, end: 5 },
                }),
                location: Location { start: 0, end: 5 },
            })
        );
    }

    #[test]
    fn test_int_number() {
        let result = dw_parser::parse("123");
        assert_eq!(
            result,
            Ok(AstNode::Document {
                header: None,
                body: Box::new(AstNode::Number {
                    value: "123".to_string(),
                    location: Location { start: 0, end: 3 },
                }),
                location: Location { start: 0, end: 3 },
            })
        );
    }

    #[test]
    fn test_negative_number() {
        let result = dw_parser::parse("-123");
        assert_eq!(
            result,
            Ok(AstNode::Document {
                header: None,
                body: Box::new(AstNode::Number {
                    value: "-123".to_string(),
                    location: Location { start: 0, end: 4 },
                }),
                location: Location { start: 0, end: 4 },
            })
        );
    }

    #[test]
    fn test_double_number() {
        let result = dw_parser::parse("123.234");
        assert_eq!(
            result,
            Ok(AstNode::Document {
                header: None,
                body: Box::new(AstNode::Number {
                    value: "123.234".to_string(),
                    location: Location { start: 0, end: 7 },
                }),
                location: Location { start: 0, end: 7 },
            })
        );
    }
}
