From 73cb40ef152457342c7376e519b0c4bf70329129 Mon Sep 17 00:00:00 2001 From: "John T. Wodder II" Date: Thu, 15 Feb 2024 07:09:32 -0500 Subject: [PATCH 1/2] Test HTML rendering --- src/dav/html.rs | 150 ++++++++++++++++++++++++- src/dav/mod.rs | 21 +--- src/dav/templates/collection.html.tera | 35 +++--- src/dav/types.rs | 7 -- src/testdata/render-collection.html | 103 +++++++++++++++++ 5 files changed, 270 insertions(+), 46 deletions(-) create mode 100644 src/testdata/render-collection.html diff --git a/src/dav/html.rs b/src/dav/html.rs index 4c4dc9b..047408d 100644 --- a/src/dav/html.rs +++ b/src/dav/html.rs @@ -51,6 +51,33 @@ pub(super) struct CollectionContext { pub(super) package_commit: Option<&'static str>, } +impl CollectionContext { + pub(super) fn new( + entries: Vec, + title: &str, + pathparts: Vec, + ) -> CollectionContext { + let mut rows = entries.into_iter().map(ColRow::from).collect::>(); + rows.sort_unstable(); + if let Some((_, pp)) = pathparts.split_last() { + rows.insert( + 0, + ColRow::parentdir(Href::from_path(&abs_dir_from_components(pp))), + ); + } + let title_path = abs_dir_from_components(&pathparts); + let full_title = format!("{title} \u{2014} {title_path}"); + CollectionContext { + title: full_title, + breadcrumbs: make_breadcrumbs(pathparts), + rows, + package_url: env!("CARGO_PKG_REPOSITORY"), + package_version: env!("CARGO_PKG_VERSION"), + package_commit: option_env!("GIT_COMMIT"), + } + } +} + #[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub(super) struct Link { name: String, @@ -158,7 +185,7 @@ fn maybe_timestamp( } } -pub(super) fn make_breadcrumbs(pathparts: Vec) -> Vec { +fn make_breadcrumbs(pathparts: Vec) -> Vec { let mut links = Vec::with_capacity(pathparts.len().saturating_add(1)); let mut cumpath = String::from("/"); links.push(Link { @@ -175,3 +202,124 @@ pub(super) fn make_breadcrumbs(pathparts: Vec) -> Vec { } links } + +fn abs_dir_from_components<'a, I>(iter: I) -> String +where + I: IntoIterator, +{ + let mut s = String::from("/"); + for p in iter { + s.push_str(p); + s.push('/'); + } + s +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::dav::DavContent; + use pretty_assertions::assert_eq; + use std::borrow::Cow; + use time::macros::datetime; + + #[test] + fn test_render_collection() { + let templater = Templater::load().unwrap(); + + let entries = vec![ + DavResource::Collection(DavCollection { + path: Some("foo/bar/baz/a.zarr/".parse().unwrap()), + created: Some(datetime!(2021-01-01 01:23:45 UTC)), + modified: Some(datetime!(2023-12-31 12:34:56 UTC)), + size: Some(1234567890), + kind: ResourceKind::Zarr, + metadata_url: None, + }), + DavResource::Collection(DavCollection { + path: Some(r#"foo/bar/baz/"quoted"/"#.parse().unwrap()), + created: None, + modified: None, + size: None, + kind: ResourceKind::Directory, + metadata_url: None, + }), + DavResource::Item(DavItem { + path: "foo/bar/baz/empty.txt".parse().unwrap(), + created: Some(datetime!(2024-02-14 22:13:22 -5)), + modified: Some(datetime!(2024-02-14 22:13:35 -5)), + content_type: "text/plain".into(), + size: Some(0), + etag: Some(r#""00000000""#.into()), + kind: ResourceKind::Blob, + content: DavContent::Redirect( + "https://dandiarchive-test.s3.amazonaws.com/blobs/empty.txt" + .parse() + .unwrap(), + ), + metadata_url: Some( + "https://api-test.dandiarchive.org/blobs/?name=empty.txt" + .parse() + .unwrap(), + ), + }), + DavResource::Item(DavItem { + path: "foo/bar/baz/spaced file.dat".parse().unwrap(), + created: Some(datetime!(2021-02-03 06:47:50 UTC)), + modified: Some(datetime!(2022-03-10 12:03:29 UTC)), + content_type: "application/octet-stream".into(), + size: Some(123456), + etag: Some(r#""abcdefgh""#.into()), + kind: ResourceKind::Blob, + content: DavContent::Redirect( + "https://dandiarchive-test.s3.amazonaws.com/blobs/spaced%20file.dat" + .parse() + .unwrap(), + ), + metadata_url: Some( + "https://api-test.dandiarchive.org/blobs/?name=spaced%20file.dat" + .parse() + .unwrap(), + ), + }), + DavResource::Item(DavItem { + path: "foo/bar/baz/dandiset.yaml".parse().unwrap(), + created: None, + modified: None, + content_type: "text/yaml".into(), + size: Some(42), + etag: None, + kind: ResourceKind::VersionMetadata, + content: DavContent::Blob(Vec::new()), + metadata_url: None, + }), + ]; + + let context = CollectionContext::new( + entries, + "Dandidav Test", + vec![ + "foo".parse().unwrap(), + "bar".parse().unwrap(), + "baz".parse().unwrap(), + ], + ); + let rendered = templater.render_collection(context).unwrap(); + let commit_str = match option_env!("GIT_COMMIT") { + Some(s) => Cow::from(format!(", commit {s}")), + None => Cow::from(""), + }; + let expected = include_str!(concat!( + env!("CARGO_MANIFEST_DIR"), + "/src/testdata/render-collection.html" + )) + .replacen( + "{package_url}", + &env!("CARGO_PKG_REPOSITORY").replace('/', "/"), + 1, + ) + .replacen("{version}", env!("CARGO_PKG_VERSION"), 1) + .replacen("{commit}", &commit_str, 1); + assert_eq!(rendered, expected); + } +} diff --git a/src/dav/mod.rs b/src/dav/mod.rs index b83223a..7ee10d4 100644 --- a/src/dav/mod.rs +++ b/src/dav/mod.rs @@ -93,25 +93,8 @@ impl DandiDav { pathparts: Vec, ) -> Result, DavError> { match self.resolve_with_children(path).await? { - DavResourceWithChildren::Collection { col, children } => { - let mut rows = children.into_iter().map(ColRow::from).collect::>(); - rows.sort_unstable(); - if path != &DavPath::Root { - rows.insert(0, ColRow::parentdir(col.parent_web_link())); - } - let mut title = format!("{} \u{2014} /", self.title); - for p in &pathparts { - title.push_str(p); - title.push('/'); - } - let context = CollectionContext { - title, - breadcrumbs: make_breadcrumbs(pathparts), - rows, - package_url: env!("CARGO_PKG_REPOSITORY"), - package_version: env!("CARGO_PKG_VERSION"), - package_commit: option_env!("GIT_COMMIT"), - }; + DavResourceWithChildren::Collection { children, .. } => { + let context = CollectionContext::new(children, &self.title, pathparts); let html = self.templater.render_collection(context)?; Ok(([(CONTENT_TYPE, HTML_CONTENT_TYPE)], html).into_response()) } diff --git a/src/dav/templates/collection.html.tera b/src/dav/templates/collection.html.tera index e284193..b5646ce 100644 --- a/src/dav/templates/collection.html.tera +++ b/src/dav/templates/collection.html.tera @@ -6,8 +6,8 @@ @@ -18,39 +18,36 @@ - {% for r in rows %} + {%- for r in rows %} + - - - {% if r.size is defined %} + {%- if r.size is defined %} - {% else %} + {%- else %} - {% endif %} - - {% if r.created is defined %} + {%- endif %} + {%- if r.created is defined %} - {% else %} + {%- else %} - {% endif %} - - {% if r.modified is defined %} + {%- endif %} + {%- if r.modified is defined %} - {% else %} + {%- else %} - {% endif %} + {%- endif %} - {% endfor %} + {%- endfor %}
Created Modified
{{r.kind}}{{r.size}}{{r.created}}{{r.modified}}