pipedash-plugin-bitbucket 0.13.0

Monitor and trigger Bitbucket Cloud Pipelines CI/CD
Documentation
use super::*;

fn state(json: serde_json::Value) -> types::PipelineState {
    serde_json::from_value(json).unwrap()
}

#[test]
fn every_pipeline_and_step_state_maps_to_a_status() {
    let completed =
        |result: &str| serde_json::json!({"name": "COMPLETED", "result": {"name": result}});
    let cases = [
        (
            serde_json::json!({"name": "PENDING"}),
            PipelineStatus::Pending,
        ),
        (
            serde_json::json!({"name": "READY"}),
            PipelineStatus::Pending,
        ),
        (
            serde_json::json!({"name": "PARSING"}),
            PipelineStatus::Running,
        ),
        (
            serde_json::json!({"name": "IN_PROGRESS"}),
            PipelineStatus::Running,
        ),
        (
            serde_json::json!({"name": "IN_PROGRESS", "stage": {"name": "PAUSED"}}),
            PipelineStatus::Pending,
        ),
        (
            serde_json::json!({"name": "PAUSED"}),
            PipelineStatus::Pending,
        ),
        (
            serde_json::json!({"name": "HALTED"}),
            PipelineStatus::Pending,
        ),
        (completed("SUCCESSFUL"), PipelineStatus::Success),
        (completed("FAILED"), PipelineStatus::Failed),
        (completed("ERROR"), PipelineStatus::Failed),
        (completed("STOPPED"), PipelineStatus::Cancelled),
        (completed("EXPIRED"), PipelineStatus::Cancelled),
        (completed("NOT_RUN"), PipelineStatus::Skipped),
        (
            serde_json::json!({"name": "COMPLETED"}),
            PipelineStatus::Failed,
        ),
        (
            serde_json::json!({"name": "SOMETHING_NEW"}),
            PipelineStatus::Pending,
        ),
    ];
    for (json, status) in cases {
        assert_eq!(map_status(&state(json.clone())), status, "{json}");
    }
}

#[test]
fn steps_become_job_nodes_with_the_availability_of_their_log() {
    let steps: Vec<types::PipelineStep> = serde_json::from_str(
        r#"[
            {"uuid":"{a}","name":"Build","state":{"name":"COMPLETED","result":{"name":"SUCCESSFUL"}},
             "started_on":"2026-10-28T10:00:00.000Z","completed_on":"2026-10-28T10:01:15.000Z"},
            {"uuid":"{b}","name":" Test ","state":{"name":"COMPLETED","result":{"name":"FAILED"}},
             "started_on":"2026-10-28T10:01:16.000Z","completed_on":"2026-10-28T10:02:00.000Z"},
            {"uuid":"{c}","name":"Deploy","state":{"name":"IN_PROGRESS"},
             "started_on":"2026-10-28T10:02:01.000Z"},
            {"uuid":"{d}","name":"Approve","state":{"name":"PENDING","stage":{"name":"PAUSED"}}},
            {"uuid":"{e}","name":null,"state":{"name":"READY"}},
            {"uuid":"{f}","name":"Smoke","state":{"name":"COMPLETED","result":{"name":"NOT_RUN"}}},
            {"uuid":"{g}","name":"Release","state":{"name":"COMPLETED","result":{"name":"STOPPED"}},
             "started_on":"2026-10-28T10:03:00.000Z","completed_on":"2026-10-28T10:03:10.000Z"},
            {"uuid":"{h}","name":"Cleanup","state":{"name":"COMPLETED","result":{"name":"STOPPED"}}}
        ]"#,
    )
    .unwrap();

    let nodes = steps_to_log_nodes(&steps);

    let summary: Vec<_> = nodes
        .iter()
        .map(|node| (node.id.as_str(), node.name.as_str(), node.status, node.log))
        .collect();
    assert_eq!(
        summary,
        vec![
            (
                "{a}",
                "Build",
                PipelineStatus::Success,
                Some(LogAvailability::Ready)
            ),
            (
                "{b}",
                "Test",
                PipelineStatus::Failed,
                Some(LogAvailability::Ready)
            ),
            (
                "{c}",
                "Deploy",
                PipelineStatus::Running,
                Some(LogAvailability::Partial)
            ),
            (
                "{d}",
                "Approve",
                PipelineStatus::Pending,
                Some(LogAvailability::Pending)
            ),
            (
                "{e}",
                "Step 5",
                PipelineStatus::Pending,
                Some(LogAvailability::Pending)
            ),
            ("{f}", "Smoke", PipelineStatus::Skipped, None),
            (
                "{g}",
                "Release",
                PipelineStatus::Cancelled,
                Some(LogAvailability::Ready)
            ),
            ("{h}", "Cleanup", PipelineStatus::Cancelled, None),
        ]
    );
    assert!(nodes
        .iter()
        .all(|node| node.kind == LogNodeKind::Job && node.parent_id.is_none()));
    assert_eq!(
        nodes[0].finished_at.unwrap() - nodes[0].started_at.unwrap(),
        chrono::Duration::seconds(75)
    );
    assert!(nodes[2].started_at.is_some() && nodes[2].finished_at.is_none());
    assert!(nodes[3].started_at.is_none());
}