use crate::{helpers::spawn_http_server, support::TestWorkspace};

#[test]
fn run_outputs_junit_report_for_assertion_failures() {
    let server_url = spawn_http_server(
        200,
        "OK",
        "application/json",
        r#"{"ok":false,"service":"hen"}"#,
    );
    let workspace = TestWorkspace::new();
    workspace.write_file(
        "collection.hen",
        &format!(
            r#"JUnit Fixture

Exercises CI-oriented test reporting.

---

Fail fixture

GET {server_url}

[ true == false ] ^ & body.service == 'hen'
^ & body.ok == true
"#
        ),
    );

    let output = workspace.run_hen(["run", "collection.hen", "--output", "junit"]);

    assert_eq!(output.status_code, 1, "stderr: {}", output.stderr);
    assert!(output.stderr.is_empty(), "stderr: {}", output.stderr);
    assert!(output.stdout.contains("<testsuite"), "stdout: {}", output.stdout);
    assert!(output.stdout.contains("<testcase"), "stdout: {}", output.stdout);
    assert!(output.stdout.contains("tests=\"2\""), "stdout: {}", output.stdout);
    assert!(
        output.stdout.contains("<failure type=\"assertion\""),
        "stdout: {}",
        output.stdout
    );
    assert!(output.stdout.contains("Assertion failed"), "stdout: {}", output.stdout);
    assert!(
        output.stdout.contains("<skipped message=\"guard evaluated to false\"/>"),
        "stdout: {}",
        output.stdout
    );
    assert!(
        output.stdout.contains("#0 GET") && output.stdout.contains(":: ^ &amp; body.ok == true"),
        "stdout: {}",
        output.stdout
    );
}

#[test]
fn run_outputs_junit_report_for_passed_and_skipped_assertions() {
    let server_url = spawn_http_server(
        200,
        "OK",
        "application/json",
        r#"{"ok":true,"service":"hen"}"#,
    );
    let workspace = TestWorkspace::new();
    workspace.write_file(
        "collection.hen",
        &format!(
            r#"JUnit Success Fixture

Exercises assertion-level success reporting.

---

Fetch fixture

GET {server_url}

^ & body.ok == true
[ true == false ] ^ & body.service == 'hen'
"#
        ),
    );

    let output = workspace.run_hen(["run", "collection.hen", "--output", "junit"]);

    assert_eq!(output.status_code, 0, "stderr: {}", output.stderr);
    assert!(output.stderr.is_empty(), "stderr: {}", output.stderr);
    assert!(output.stdout.contains("tests=\"2\""), "stdout: {}", output.stdout);
    assert!(
        output.stdout.contains(":: ^ &amp; body.ok == true"),
        "stdout: {}",
        output.stdout
    );
    assert!(
        output.stdout.contains(":: [ true == false ] ^ &amp; body.service == &apos;hen&apos;"),
        "stdout: {}",
        output.stdout
    );
    assert!(
        output.stdout.contains("<skipped message=\"guard evaluated to false\"/>"),
        "stdout: {}",
        output.stdout
    );
}

#[test]
fn run_outputs_junit_report_for_dependency_capture_assertions() {
    let user_server_url = spawn_http_server(
        200,
        "OK",
        "application/json",
        r#"{"id":1,"email":"user@example.com","address":{"zipcode":"90210"}}"#,
    );
    let posts_server_url = spawn_http_server(
        200,
        "OK",
        "application/json",
        r#"[{"userId":1,"id":10,"title":"hello world"}]"#,
    );
    let workspace = TestWorkspace::new();
    workspace.write_file(
        "collection.hen",
        &format!(
            r#"name = JUnit Dependency Capture Fixture
description = Exercises dependency captures followed by assertions.

---

Get User

GET {user_server_url}

& body.id -> $USER_ID
^ & status == 200

---

Get Posts

> requires: Get User

GET {posts_server_url}

& body.[0].title -> $FIRST_POST_TITLE
&[Get User].body.email -> $USER_EMAIL
&[Get User].body.address.zipcode -> $USER_ZIPCODE

^ & status == 200
^ & body.[0].userId == $USER_ID
^ $FIRST_POST_TITLE != ''
^ $USER_EMAIL ~= /@/
^ $USER_ZIPCODE == '90210'
"#
        ),
    );

    let output = workspace.run_hen(["run", "collection.hen", "all", "--output", "junit"]);

    assert_eq!(output.status_code, 0, "stderr: {}", output.stderr);
    assert!(output.stderr.is_empty(), "stderr: {}", output.stderr);
    assert!(output.stdout.contains("tests=\"6\""), "stdout: {}", output.stdout);
    assert!(
        output.stdout.contains("#1 GET") && output.stdout.contains(":: ^ $USER_EMAIL ~= /@/"),
        "stdout: {}",
        output.stdout
    );
    assert!(
        output.stdout.contains(":: ^ $USER_ZIPCODE == &apos;90210&apos;"),
        "stdout: {}",
        output.stdout
    );
}