use std::{fs::File, io::Read, path::Path};
pub use errors::{Result, ResultExt};
use crate::v2_1_0::PostmanCollection_v2_1_0;
pub mod v2_1_0;
const MINIMUM_POSTMAN_COLLECTION_VERSION: &str = ">= 1.0.0";
pub mod errors {
use error_chain::error_chain;
use crate::MINIMUM_POSTMAN_COLLECTION_VERSION;
error_chain! {
foreign_links {
Io(::std::io::Error);
Yaml(::serde_yaml::Error);
Serialize(::serde_json::Error);
SemVerError(::semver::Error);
}
errors {
UnsupportedSpecFileVersion(version: ::semver::Version) {
description("Unsupported Postman Collection file version")
display("Unsupported Postman Collection file version ({}). Expected {}", version, MINIMUM_POSTMAN_COLLECTION_VERSION)
}
}
}
}
pub fn from_path<P>(path: P) -> errors::Result<PostmanCollection_v2_1_0>
where
P: AsRef<Path>,
{
from_reader(File::open(path)?)
}
pub fn from_reader<R>(read: R) -> errors::Result<PostmanCollection_v2_1_0>
where
R: Read,
{
Ok(serde_yaml::from_reader::<R, PostmanCollection_v2_1_0>(read)?)
}
pub fn to_yaml(spec: &PostmanCollection_v2_1_0) -> errors::Result<String> {
Ok(serde_yaml::to_string(spec)?)
}
pub fn to_json(spec: &PostmanCollection_v2_1_0) -> errors::Result<String> {
Ok(serde_json::to_string_pretty(spec)?)
}
#[cfg(test)]
mod tests {
use std::fs::File;
use std::io::Write;
use glob::glob;
use super::*;
fn read_file<P>(path: P) -> String
where
P: AsRef<Path>,
{
let mut f = File::open(path).unwrap();
let mut content = String::new();
f.read_to_string(&mut content).unwrap();
content
}
fn write_to_file<P>(path: P, filename: &str, data: &str)
where
P: AsRef<Path> + std::fmt::Debug,
{
println!(" Saving string to {:?}...", path);
std::fs::create_dir_all(&path).unwrap();
let full_filename = path.as_ref().to_path_buf().join(filename);
let mut f = File::create(&full_filename).unwrap();
f.write_all(data.as_bytes()).unwrap();
}
fn convert_yaml_str_to_json(yaml_str: &str) -> String {
let yaml: serde_yaml::Value = serde_yaml::from_str(yaml_str).unwrap();
let json: serde_json::Value = serde_yaml::from_value(yaml).unwrap();
serde_json::to_string_pretty(&json).unwrap()
}
fn compare_spec_through_json(
input_file: &Path,
save_path_base: &Path,
) -> (String, String, String) {
let spec_yaml_str = read_file(&input_file);
let spec_json_str = convert_yaml_str_to_json(&spec_yaml_str);
let parsed_spec = from_path(&input_file).unwrap();
println!("{}", input_file.file_name().unwrap().to_str().unwrap());
dbg!(&parsed_spec);
let parsed_spec_json: serde_json::Value = serde_json::to_value(parsed_spec).unwrap();
let parsed_spec_json_str: String = serde_json::to_string_pretty(&parsed_spec_json).unwrap();
let api_filename = input_file
.file_name()
.unwrap()
.to_str()
.unwrap()
.replace(".yaml", ".json");
let mut save_path = save_path_base.to_path_buf();
save_path.push("yaml_to_json");
write_to_file(&save_path, &api_filename, &spec_json_str);
let mut save_path = save_path_base.to_path_buf();
save_path.push("yaml_to_spec_to_json");
write_to_file(&save_path, &api_filename, &parsed_spec_json_str);
(api_filename, parsed_spec_json_str, spec_json_str)
}
#[test]
fn can_deserialize() {
for entry in glob("/tests/fixtures/collection/*.json").expect("Failed to read glob pattern")
{
let entry = entry.unwrap();
let path = entry.as_path();
println!("Testing if {:?} is deserializable", path);
from_path(path).unwrap();
}
}
#[test]
fn can_deserialize_and_reserialize() {
let save_path_base: std::path::PathBuf =
["target", "tests", "can_deserialize_and_reserialize"]
.iter()
.collect();
let mut invalid_diffs = Vec::new();
for entry in glob("./tests/fixtures/collection/*.json").expect("Failed to read glob pattern")
{
let entry = entry.unwrap();
let path = entry.as_path();
println!("Testing if {:?} is deserializable", path);
let (api_filename, parsed_spec_json_str, spec_json_str) = compare_spec_through_json(path, &save_path_base);
if parsed_spec_json_str != spec_json_str {
invalid_diffs.push((api_filename, parsed_spec_json_str, spec_json_str));
}
}
for invalid_diff in &invalid_diffs {
println!("File {} failed JSON comparison!", invalid_diff.0);
}
assert_eq!(invalid_diffs.len(), 0);
}
}