Add tests for all but the content syntax parser module
This commit is contained in:
parent
f48b2070bc
commit
e657eb6513
17 changed files with 1072 additions and 127 deletions
39
src/dev.rs
39
src/dev.rs
|
|
@ -52,3 +52,42 @@ macro_rules! log {
|
|||
|
||||
}};
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
||||
fn run_in_debug_level(level: &str) {
|
||||
#[allow(unsafe_code)]
|
||||
unsafe {
|
||||
std::env::set_var("DEBUG", level);
|
||||
log!("Debug is set to {level}");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn debug_var_set() {
|
||||
for level in 0..9 {
|
||||
run_in_debug_level(&level.to_string());
|
||||
}
|
||||
run_in_debug_level("");
|
||||
run_in_debug_level("駄目!");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn trait_stripping() {
|
||||
pub trait Loggable {
|
||||
fn test(&self);
|
||||
}
|
||||
|
||||
struct Logger {}
|
||||
|
||||
impl Loggable for Logger {
|
||||
fn test(&self) {
|
||||
log!("This is inside a trait implementation");
|
||||
}
|
||||
}
|
||||
|
||||
let logger = Logger {};
|
||||
logger.test();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
122
src/router.rs
122
src/router.rs
|
|
@ -54,3 +54,125 @@ pub fn new(graph: &Graph) -> Router {
|
|||
|
||||
router
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{
|
||||
syntax::serial::populate_graph,
|
||||
types::{Config, Meta},
|
||||
};
|
||||
|
||||
use super::*;
|
||||
use axum::{
|
||||
body::Body,
|
||||
http::{Request, StatusCode},
|
||||
response::Response,
|
||||
};
|
||||
use tower::ServiceExt as _;
|
||||
|
||||
async fn request(uri: &str, config: Option<&Config>) -> Response<Body> {
|
||||
let default_graph = populate_graph();
|
||||
let graph = Graph {
|
||||
meta: Meta {
|
||||
config: config
|
||||
.map(|c| c.to_owned())
|
||||
.unwrap_or(default_graph.meta.config),
|
||||
..default_graph.meta
|
||||
},
|
||||
..default_graph
|
||||
};
|
||||
let router = new(&graph);
|
||||
|
||||
router
|
||||
.oneshot(Request::builder().uri(uri).body(Body::empty()).unwrap())
|
||||
.await
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn smoke() {
|
||||
let router = axum::Router::new();
|
||||
let response = router
|
||||
.oneshot(Request::builder().uri("/").body(Body::empty()).unwrap())
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(response.status(), StatusCode::NOT_FOUND);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn routes() {
|
||||
let routes = [
|
||||
"/",
|
||||
"/about",
|
||||
"/tree",
|
||||
"/node/Syntax",
|
||||
"/static/style.css",
|
||||
"/static/favicon.svg",
|
||||
"/graph/json",
|
||||
"/graph/toml",
|
||||
];
|
||||
|
||||
for route in routes {
|
||||
let response = request(route, None).await;
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn no_about_page() {
|
||||
let config = Config {
|
||||
about: false,
|
||||
..populate_graph().meta.config
|
||||
};
|
||||
|
||||
let response = request("/about", Some(&config)).await;
|
||||
assert_eq!(response.status(), StatusCode::NOT_FOUND);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn no_tree_page() {
|
||||
let config = Config {
|
||||
tree: false,
|
||||
..populate_graph().meta.config
|
||||
};
|
||||
|
||||
let response = request("/tree", Some(&config)).await;
|
||||
assert_eq!(response.status(), StatusCode::NOT_FOUND);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn no_toml_raw_graph() {
|
||||
let config = Config {
|
||||
raw_toml: false,
|
||||
..populate_graph().meta.config
|
||||
};
|
||||
|
||||
let response = request("/graph/toml", Some(&config)).await;
|
||||
assert_eq!(response.status(), StatusCode::NOT_FOUND);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn no_json_raw_graph() {
|
||||
let config = Config {
|
||||
raw_json: false,
|
||||
..populate_graph().meta.config
|
||||
};
|
||||
|
||||
let response = request("/graph/json", Some(&config)).await;
|
||||
assert_eq!(response.status(), StatusCode::NOT_FOUND);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn no_raw_graph() {
|
||||
let config = Config {
|
||||
raw: false,
|
||||
..populate_graph().meta.config
|
||||
};
|
||||
|
||||
let toml_response = request("/graph/toml", Some(&config)).await;
|
||||
assert_eq!(toml_response.status(), StatusCode::NOT_FOUND);
|
||||
let json_response = request("/graph/json", Some(&config)).await;
|
||||
assert_eq!(json_response.status(), StatusCode::NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,3 +56,33 @@ pub async fn not_found() -> Response<Body> {
|
|||
Some("The page you tried to access could not be found."),
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use axum::{
|
||||
http::{StatusCode},
|
||||
};
|
||||
use super::*;
|
||||
|
||||
#[tokio::test]
|
||||
async fn not_found() {
|
||||
let response = super::not_found().await;
|
||||
assert_eq!(response.status(), StatusCode::NOT_FOUND);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn internal_error() {
|
||||
assert!(by_code(Some(201), None).status() == 201);
|
||||
assert!(by_code(Some(304), None).status() == 304);
|
||||
assert!(by_code(Some(418), None).status() == 418);
|
||||
assert!(by_code(Some(505), None).status() == 505);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn custom_message() {
|
||||
let pattern = "sibPtt0mvHPWS9HQ0YBQfGu8cUs954LZ";
|
||||
let body = make_body(Some(501), Some(pattern));
|
||||
assert!(body.contains(pattern));
|
||||
assert!(!body.contains(&pattern.chars().rev().collect::<String>()));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,11 +25,7 @@ pub async fn file(file_path: &str, content_type: &str) -> Response<Body> {
|
|||
let header = header::CONTENT_TYPE;
|
||||
|
||||
if let Ok(header_value) = HeaderValue::from_str(content_type) {
|
||||
if let Some(h) = response.headers_mut().insert(header, header_value) {
|
||||
log!(
|
||||
"Overwrote existing header {h:?} because a header for the same key existed"
|
||||
);
|
||||
}
|
||||
response.headers_mut().append(header, header_value);
|
||||
} else {
|
||||
log!("Failed to create content type header value from {content_type}");
|
||||
}
|
||||
|
|
@ -43,15 +39,70 @@ pub async fn serial(format: &Format) -> Response<Body> {
|
|||
let body = serialize_graph(format, &graph);
|
||||
|
||||
match *format {
|
||||
Format::Toml => handlers::raw::make_response(
|
||||
Format::TOML => handlers::raw::make_response(
|
||||
&body,
|
||||
200,
|
||||
&[(header::CONTENT_TYPE, "text/plain")],
|
||||
),
|
||||
Format::Json => handlers::raw::make_response(
|
||||
Format::JSON => handlers::raw::make_response(
|
||||
&body,
|
||||
200,
|
||||
&[(header::CONTENT_TYPE, "application/json")],
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[tokio::test]
|
||||
async fn serial_toml() {
|
||||
let response = serial(&Format::TOML).await;
|
||||
assert!(response.status() == 200);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn serial_toml_content_type() {
|
||||
let response = serial(&Format::TOML).await;
|
||||
assert!(
|
||||
response.headers().get(header::CONTENT_TYPE).unwrap()
|
||||
== "text/plain"
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn serial_json_content_type() {
|
||||
let response = serial(&Format::JSON).await;
|
||||
assert!(
|
||||
response.headers().get(header::CONTENT_TYPE).unwrap()
|
||||
== "application/json"
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn file_valid_header() {
|
||||
let payload = "y1mgMhjeIMFsRNZ1tskP52DfWuvhvbRP";
|
||||
let response = file("./static/graph.toml", payload).await;
|
||||
assert_eq!(
|
||||
response.headers().get(header::CONTENT_TYPE).unwrap(),
|
||||
payload
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn file_invalid_header() {
|
||||
let response = file("./static/graph.toml", "\n").await;
|
||||
println!("{response:#?}");
|
||||
assert!(response.headers().get(header::CONTENT_TYPE).is_none());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[should_panic(
|
||||
expected = "Failed to read IvnhZhdHb1xDnUw4hYDDNIERoaOojkiu \
|
||||
contents: No such file or directory (os error 2)"
|
||||
)]
|
||||
async fn file_invalid_path() {
|
||||
drop(file("IvnhZhdHb1xDnUw4hYDDNIERoaOojkiu", "text/plain").await);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,3 +40,44 @@ pub async fn node(Path(id): Path<String>) -> Response<Body> {
|
|||
not_found,
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use axum::{
|
||||
http::{HeaderName, StatusCode},
|
||||
};
|
||||
|
||||
use super::*;
|
||||
|
||||
#[tokio::test]
|
||||
async fn syntax() {
|
||||
let response = node(Path("Syntax".to_string())).await;
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn syntax_content_type() {
|
||||
let response = node(Path("Syntax".to_string())).await;
|
||||
assert!(
|
||||
response
|
||||
.headers()
|
||||
.get(HeaderName::from_static("content-type"),)
|
||||
.unwrap()
|
||||
.to_str()
|
||||
.unwrap()
|
||||
== "text/html"
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn not_found() {
|
||||
let response = node(Path("InexistentNode".to_string())).await;
|
||||
assert_eq!(response.status(), StatusCode::NOT_FOUND);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn redirect() {
|
||||
let response = node(Path("syntax".to_string())).await;
|
||||
assert_eq!(response.status(), StatusCode::PERMANENT_REDIRECT);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,3 +29,38 @@ pub async fn search(Form(query): Form<Query>) -> Redirect {
|
|||
pub struct Query {
|
||||
node: String,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use axum::{
|
||||
http::{StatusCode},
|
||||
};
|
||||
use super::*;
|
||||
|
||||
#[tokio::test]
|
||||
async fn search_redirect() {
|
||||
let query = Form(Query {
|
||||
node: String::from("duZzBrgCzMhVY15wehxasezsGNatOKIq"),
|
||||
});
|
||||
let response = search(query).await;
|
||||
assert!(response.status_code() == StatusCode::PERMANENT_REDIRECT);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn about_page_ok() {
|
||||
let response = page("about.html").await;
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn tree_page_ok() {
|
||||
let response = page("tree.html").await;
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn inexistent_page_error() {
|
||||
let response = page("HBvcwqT8wLk6hxk1GdvNcEzJ6IiZ2Fod").await;
|
||||
assert_eq!(response.status(), StatusCode::INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,9 +27,39 @@ pub(in crate::router::handlers) fn make_response(
|
|||
);
|
||||
}
|
||||
} else {
|
||||
log!("Failed to wrap header value {}", header.1);
|
||||
log!("Failed to create header value from {}", header.1);
|
||||
}
|
||||
}
|
||||
|
||||
response
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn repeated_header() {
|
||||
let headers = [
|
||||
(header::ACCEPT, "Not really"),
|
||||
(header::ACCEPT, "This again?"),
|
||||
];
|
||||
let response = make_response("", 418, &headers);
|
||||
assert!(response.headers().get_all(header::ACCEPT).iter().count() == 1);
|
||||
assert_eq!(
|
||||
response
|
||||
.headers()
|
||||
.get(header::ACCEPT)
|
||||
.unwrap()
|
||||
.to_str()
|
||||
.unwrap(),
|
||||
"This again?",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn invalid_header() {
|
||||
let response = make_response("", 418, &[(header::MAX_FORWARDS, "\n")]);
|
||||
assert!(response.headers().get(header::MAX_FORWARDS).is_none());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,14 +27,9 @@ pub(in crate::router::handlers) fn render(
|
|||
error_message: Option<String>,
|
||||
) -> (String, u16) {
|
||||
// TODO just return an Option/String> here
|
||||
let tera = match tera::Tera::new(concat!(
|
||||
env!("CARGO_MANIFEST_DIR"),
|
||||
"/templates/**/*"
|
||||
)) {
|
||||
let tera = match tera::Tera::new("./templates/**/*") {
|
||||
Ok(t) => t,
|
||||
Err(e) => {
|
||||
let early_error_message = format!("{e:#?}");
|
||||
log!("{}", early_error_message);
|
||||
return (emergency_wrap(&e), 500);
|
||||
},
|
||||
};
|
||||
|
|
@ -73,7 +68,8 @@ pub(in crate::router::handlers) fn render(
|
|||
}
|
||||
}
|
||||
|
||||
fn emergency_wrap(message: &tera::Error) -> String {
|
||||
fn emergency_wrap(error: &tera::Error) -> String {
|
||||
log!("{error:#?}");
|
||||
format!(
|
||||
r#"<!DOCTYPE html>
|
||||
<html>
|
||||
|
|
@ -93,7 +89,7 @@ fn emergency_wrap(message: &tera::Error) -> String {
|
|||
<h2><strong>Early Pre-Templating Error</strong></h2>
|
||||
<p>This normally indicates a malformed template.</p>
|
||||
<pre>
|
||||
{message}
|
||||
{error:#?}
|
||||
</pre>
|
||||
<p>
|
||||
If you haven't modified templates, plese consider
|
||||
|
|
@ -104,3 +100,104 @@ fn emergency_wrap(message: &tera::Error) -> String {
|
|||
"#
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn by_filename_forced_error() {
|
||||
let response =
|
||||
by_filename("index.html", &tera::Context::new(), 418, None, true);
|
||||
assert_eq!(response.status(), 418);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn by_filename_index() {
|
||||
let response =
|
||||
by_filename("index.html", &tera::Context::new(), 418, None, false);
|
||||
assert_eq!(response.status(), 200);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn by_filename_file_not_found() {
|
||||
let response = by_filename(
|
||||
"bwbl3BnWsluIgbO2NV9t3vtihwcjuF6t",
|
||||
&tera::Context::new(),
|
||||
418,
|
||||
None,
|
||||
false,
|
||||
);
|
||||
assert_eq!(response.status(), 500);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn by_filename_empty() {
|
||||
let response = by_filename("", &tera::Context::new(), 418, None, false);
|
||||
assert_eq!(response.status(), 500);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn render_with_context() {
|
||||
let payload = "dBgIw8DnNHxJojiXzu445qUC4UpxwZCy";
|
||||
let mut context = tera::Context::new();
|
||||
let node = crate::types::Node::new(Some(payload.to_string()));
|
||||
let graph = crate::syntax::serial::populate_graph();
|
||||
context.insert("node", &node);
|
||||
context.insert("text", &crate::syntax::content::parse(&node.text));
|
||||
context.insert("incoming", &graph.incoming.get(&node.id));
|
||||
context.insert("config", &graph.meta.config.parse_text());
|
||||
let (body, status) = render("node.html", &context, None);
|
||||
assert_eq!(status, 200);
|
||||
assert!(body.matches(payload).count() == 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn render_custom_error_message() {
|
||||
let payload = "dBgIw8DnNHxJojiXzu445qUC4UpxwZCy";
|
||||
let (body, status) = render(
|
||||
"ObH9jYUl4wMhUNcXnuqwVVzHoqx4ufyN",
|
||||
&tera::Context::new(),
|
||||
Some(payload.to_string()),
|
||||
);
|
||||
assert_eq!(status, 500);
|
||||
assert!(body.matches(payload).count() == 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn render_empty() {
|
||||
let (body, status) = render(
|
||||
"R8D1pxwHZDxcH5SMjR7rZEnIzmpkiHkH",
|
||||
&tera::Context::new(),
|
||||
None,
|
||||
);
|
||||
assert_eq!(status, 500);
|
||||
assert!(body.matches("Template render failed").count() == 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn render_not_found() {
|
||||
let payload = "OL6kb9qHe7Iwr7wFIRKUTeFhF34BRsQo";
|
||||
let (body, status) = render(payload, &tera::Context::new(), None);
|
||||
|
||||
assert!(body.matches("TemplateNotFound").count() > 0);
|
||||
assert!(body.matches(payload).count() > 0);
|
||||
assert_eq!(status, 500);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn render_bad_context() {
|
||||
let (body, status) = render("node.html", &tera::Context::new(), None);
|
||||
assert!(body.matches("Template render failed.").count() > 0);
|
||||
assert_eq!(status, 500);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn emergency_wrap_custom_message() {
|
||||
let payload = "JLaTtsnd2IFukIOvqFNymeuiaS6nMaUc";
|
||||
let error = tera::Error::msg(payload);
|
||||
let html = emergency_wrap(&error);
|
||||
assert!(html.matches(payload).count() == 1);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use std::path::PathBuf;
|
|||
|
||||
use crate::prelude::*;
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
#[derive(Clone, Debug, Default, PartialEq)]
|
||||
pub struct Arguments {
|
||||
pub hostname: String,
|
||||
pub port: u16,
|
||||
|
|
@ -57,3 +57,58 @@ fn parse(defaults: &Arguments, args: &[String]) -> Arguments {
|
|||
}
|
||||
out_args
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn address() {
|
||||
let args = Arguments {
|
||||
hostname: String::from("localhost"),
|
||||
port: 3007,
|
||||
graph_path: PathBuf::new(),
|
||||
};
|
||||
|
||||
assert_eq!(args.make_address(), "localhost:3007");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hostname() {
|
||||
let defaults = Arguments::new();
|
||||
|
||||
let payload = String::from("olUCu7vWcUAsumv2xpj2Z55EDheWLTEu");
|
||||
let args =
|
||||
parse(&defaults, &[String::from("-h"), String::from(&payload)]);
|
||||
assert_eq!(args.hostname, payload);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn port() {
|
||||
let defaults = Arguments::new();
|
||||
|
||||
let payload = 3901;
|
||||
let args = parse(&defaults, &[String::from("-p"), payload.to_string()]);
|
||||
assert_eq!(args.port, payload);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn graph_path() {
|
||||
let defaults = Arguments::new();
|
||||
|
||||
let payload = PathBuf::from("/tmp/");
|
||||
let args = parse(
|
||||
&defaults,
|
||||
&[String::from("-g"), payload.to_str().unwrap().to_string()],
|
||||
);
|
||||
assert_eq!(args.graph_path, payload);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn empty() {
|
||||
let defaults = Arguments::new();
|
||||
|
||||
let args = parse(&defaults, &[]);
|
||||
assert_eq!(defaults, args);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -128,11 +128,97 @@ pub fn deserialize_graph(in_format: &Format, serial: &str) -> Graph {
|
|||
match *in_format {
|
||||
Format::TOML => match toml::from_str(serial) {
|
||||
Ok(g) => g,
|
||||
Err(error) => Graph::new(Some(error.to_string())),
|
||||
Err(error) => Graph::new(Some(&error.to_string())),
|
||||
},
|
||||
Format::JSON => match serde_json::from_str(serial) {
|
||||
Ok(g) => g,
|
||||
Err(error) => Graph::new(Some(error.to_string())),
|
||||
Err(error) => Graph::new(Some(&error.to_string())),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn good_json() {
|
||||
let json = r#"
|
||||
{
|
||||
"nodes": {
|
||||
"JSON": {
|
||||
"text": "",
|
||||
"title": "JSON",
|
||||
"links": [],
|
||||
"id": "JSON",
|
||||
"hidden": false,
|
||||
"connections": []
|
||||
}
|
||||
},
|
||||
"root_node": "JSON"
|
||||
}
|
||||
"#;
|
||||
|
||||
let graph = deserialize_graph(&Format::JSON, json);
|
||||
assert!(graph.meta.messages.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bad_json() {
|
||||
let graph = deserialize_graph(&Format::JSON, ":::");
|
||||
let message = graph.meta.messages.first().unwrap();
|
||||
assert!(message.contains("expected value at line 1 column 1"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn detached_node() {
|
||||
let node = Node {
|
||||
id: String::from("SomeNode"),
|
||||
text: String::new(),
|
||||
title: String::new(),
|
||||
links: vec![String::new()],
|
||||
hidden: false,
|
||||
connections: Some(vec![Edge {
|
||||
anchor: String::from("SomeAnchor"),
|
||||
from: String::new(),
|
||||
to: String::new(),
|
||||
detached: false,
|
||||
}]),
|
||||
};
|
||||
|
||||
let mut map: HashMap<String, Node> = HashMap::new();
|
||||
map.insert(String::from("SomeNode"), node);
|
||||
|
||||
let modulated_map = modulate_nodes(&map);
|
||||
let modulated_node = modulated_map.get("SomeNode").unwrap().clone();
|
||||
let modulated_connections = modulated_node.connections.unwrap();
|
||||
let modulated_connection = modulated_connections.first().unwrap();
|
||||
assert!(modulated_connection.anchor == "SomeAnchor");
|
||||
assert!(modulated_connection.detached);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod serial_tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn bad_graph_path() {
|
||||
println!("T");
|
||||
let original_working_directory = std::env::current_dir().unwrap();
|
||||
|
||||
assert!(
|
||||
std::env::set_current_dir(std::path::Path::new(
|
||||
"tests/mocks/no_graph"
|
||||
))
|
||||
.is_ok()
|
||||
);
|
||||
|
||||
let graph = populate_graph();
|
||||
let message = graph.meta.messages.first().unwrap();
|
||||
assert!(message.contains("TOML parse error"));
|
||||
assert!(message.contains("No such file or directory"));
|
||||
|
||||
assert!(std::env::set_current_dir(original_working_directory).is_ok());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
81
src/types.rs
81
src/types.rs
|
|
@ -198,3 +198,84 @@ impl Config {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::syntax::serial::populate_graph;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn empty_graph() {
|
||||
let graph = Graph::new(Some("ISryQFd9peG6eYz9CFRQFWeD1GnPo0oj"));
|
||||
assert!(graph.nodes.is_empty());
|
||||
assert!(graph.incoming.is_empty());
|
||||
assert_eq!(
|
||||
graph.meta.messages.first().unwrap(),
|
||||
"ISryQFd9peG6eYz9CFRQFWeD1GnPo0oj"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn empty_node_message() {
|
||||
let node = Node::new(None);
|
||||
assert_eq!(node.text, "Node is empty, missing or wasn't found.");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn empty_footer_text() {
|
||||
let default_graph = populate_graph();
|
||||
|
||||
let config = Config {
|
||||
footer_text: String::new(),
|
||||
..default_graph.meta.config
|
||||
};
|
||||
|
||||
let parsed_config = config.parse_text();
|
||||
|
||||
println!("{:?}", parsed_config.footer_text);
|
||||
assert!(parsed_config.footer_text.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn config_footer_text() {
|
||||
let payload = "0kqBrdS8NPrU4xVxh2xW0hUzAw926JCQ";
|
||||
let default_graph = populate_graph();
|
||||
|
||||
let config = Config {
|
||||
footer_text: format!("`{payload}`"),
|
||||
..default_graph.meta.config
|
||||
};
|
||||
|
||||
let parsed_config = config.parse_text();
|
||||
|
||||
assert!(
|
||||
parsed_config
|
||||
.footer_text
|
||||
.matches(format!("<code>{payload}</code>").as_str())
|
||||
.count()
|
||||
== 1
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn config_about_text() {
|
||||
let payload = "ZqPFl84JlzSS0QUo61RwTUPONIE78Lmw";
|
||||
let default_graph = populate_graph();
|
||||
|
||||
let config = Config {
|
||||
about_text: format!("`{payload}`"),
|
||||
..default_graph.meta.config
|
||||
};
|
||||
|
||||
let parsed_config = config.parse_text();
|
||||
|
||||
assert!(
|
||||
parsed_config
|
||||
.about_text
|
||||
.matches(format!("<code>{payload}</code>").as_str())
|
||||
.count()
|
||||
== 1
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue