use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ArtifactOutput {
pub pattern: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub content_type: Option<String>,
}
impl ArtifactOutput {
pub fn new(pattern: &str) -> Self {
Self {
pattern: pattern.to_string(),
content_type: None,
}
}
pub fn typed(pattern: &str, content_type: &str) -> Self {
Self {
pattern: pattern.to_string(),
content_type: Some(content_type.to_string()),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ArtifactInput {
pub step: String,
pub name: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub dest: Option<String>,
}
impl ArtifactInput {
pub fn new(step: &str, name: &str) -> Self {
Self {
step: step.to_string(),
name: name.to_string(),
dest: None,
}
}
pub fn at(mut self, dest: &str) -> Self {
self.dest = Some(dest.to_string());
self
}
pub fn destination(&self) -> &str {
self.dest.as_deref().unwrap_or(&self.name)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn output_defaults_to_a_guessed_type() {
assert!(ArtifactOutput::new("a.html").content_type.is_none());
}
#[test]
fn output_keeps_an_explicit_type() {
let output = ArtifactOutput::typed("a", "text/csv");
assert_eq!(output.content_type.as_deref(), Some("text/csv"));
}
#[test]
fn output_serde_omits_an_absent_content_type() {
let json = serde_json::to_string(&ArtifactOutput::new("a.html")).expect("serialize");
assert!(!json.contains("content_type"));
}
#[test]
fn output_serde_roundtrips() {
let output = ArtifactOutput::typed("a", "text/csv");
let json = serde_json::to_string(&output).expect("serialize");
let parsed: ArtifactOutput = serde_json::from_str(&json).expect("deserialize");
assert_eq!(parsed, output);
}
#[test]
fn input_destination_defaults_to_the_artifact_name() {
assert_eq!(ArtifactInput::new("build", "a.txt").destination(), "a.txt");
}
#[test]
fn input_destination_honours_an_override() {
assert_eq!(
ArtifactInput::new("build", "a.txt")
.at("in/a.txt")
.destination(),
"in/a.txt"
);
}
#[test]
fn input_serde_roundtrips() {
let input = ArtifactInput::new("build", "a.txt").at("in/a.txt");
let json = serde_json::to_string(&input).expect("serialize");
let parsed: ArtifactInput = serde_json::from_str(&json).expect("deserialize");
assert_eq!(parsed, input);
}
#[test]
fn input_deserializes_a_payload_without_dest() {
let parsed: ArtifactInput =
serde_json::from_str(r#"{"step":"build","name":"a.txt"}"#).expect("deserialize");
assert_eq!(parsed.destination(), "a.txt");
}
}