,
) -> (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#"
@@ -93,7 +89,7 @@ fn emergency_wrap(message: &tera::Error) -> String {
Early Pre-Templating Error
This normally indicates a malformed template.
- {message}
+ {error:#?}
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);
+ }
+}
diff --git a/src/syntax/command.rs b/src/syntax/command.rs
index 0c55e4e..2ca7b01 100644
--- a/src/syntax/command.rs
+++ b/src/syntax/command.rs
@@ -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);
+ }
+}
diff --git a/src/syntax/serial.rs b/src/syntax/serial.rs
index 5fb87cf..7ed2a87 100644
--- a/src/syntax/serial.rs
+++ b/src/syntax/serial.rs
@@ -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 = 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());
+ }
+}
diff --git a/src/types.rs b/src/types.rs
index 809d78d..00d78e6 100644
--- a/src/types.rs
+++ b/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!("