Skip to main content

max / quasi

3.9 KB · 135 lines History Blame Raw
1 //! Copy read from a content file is written out, once per entry.
2 //!
3 //! The production quasicoherent `98fbee62` added, tested where it can be:
4 //! `CARGO_MANIFEST_DIR` is what the path resolves against, so this has to be an
5 //! ordinary integration test of this crate rather than a trybuild case, whose
6 //! generated project has a manifest directory of its own.
7 //!
8 //! What is asserted is that the loop is gone. Two entries in the file produce
9 //! two rows built by one description that names neither of them, which is only
10 //! true if the macro read the file and wrote the members out.
11
12 use quasi_declare::declare;
13
14 declare! {
15 /// Every row the fixture names, in the order it names them.
16 shape rows() -> Node;
17
18 region "copy" as Pane {
19 list {
20 for entry in copy "tests/content/copy.toml" as rows {
21 row entry.label {
22 secondary entry.detail;
23 }
24 }
25 }
26 }
27 }
28
29 declare! {
30 /// A brace in copy, which is text and not a hole.
31 shape braces() -> Node;
32
33 region "braces" as Pane {
34 for entry in copy "tests/content/copy.toml" as braced {
35 text entry.label;
36 }
37 }
38 }
39
40 #[test]
41 fn the_file_supplies_one_member_per_entry() {
42 let rendered = format!("{:?}", rows());
43
44 assert!(rendered.contains("First"), "the first row is missing");
45 assert!(
46 rendered.contains("the one at the top"),
47 "its detail is missing"
48 );
49 assert!(rendered.contains("Second"), "the second row is missing");
50 assert!(
51 rendered.contains("the one under it"),
52 "its detail is missing"
53 );
54 }
55
56 declare! {
57 /// A binding named `copy`, which is a hole root and not the production.
58 shape bound(copy: &Fixture) -> Node;
59
60 region "bound" as Pane {
61 for word in copy.words.iter() {
62 text word;
63 }
64 }
65 }
66
67 /// Something to bind, so the case above is a real declaration rather than a
68 /// name that happens to parse.
69 pub struct Fixture {
70 pub words: Vec<String>,
71 }
72
73 #[test]
74 fn a_binding_called_copy_is_still_a_binding() {
75 // audiofiles' `importing` has one: `for weight in copy.weight.iter()`. The
76 // production is told from it by the string literal that follows the word,
77 // so adding it took no name away from any declaration in the tree.
78 let fixture = Fixture {
79 words: vec!["read".to_owned(), "me".to_owned()],
80 };
81 let rendered = format!("{:?}", bound(&fixture));
82
83 assert!(rendered.contains("read"), "the loop ran over the binding");
84 assert!(rendered.contains("me"), "the loop ran over the binding");
85 }
86
87 declare! {
88 /// A list field, read by a nested loop.
89 shape listed() -> Node;
90
91 region "listed" as Pane {
92 for profile in copy "tests/content/copy.toml" as listed {
93 section profile.title;
94 list {
95 for feature in profile.features {
96 row feature;
97 }
98 }
99 }
100 }
101 }
102
103 /// Both loops are gone, the inner one as much as the outer.
104 ///
105 /// Five rows from two entries is the assertion that matters: an inner loop that
106 /// survived would draw one row per entry, and one that ran once would draw two.
107 /// The binder of the inner loop is the element itself, which is what tells a
108 /// list read from a record read.
109 #[test]
110 fn a_list_field_is_unrolled_per_element() {
111 let rendered = format!("{:?}", listed());
112
113 for feature in [
114 "Lossless upload",
115 "Chapters",
116 "Cover art",
117 "Markdown",
118 "Scheduled publishing",
119 ] {
120 assert!(rendered.contains(feature), "{feature} is missing");
121 }
122 assert!(rendered.contains("Musicians"), "the first title is missing");
123 assert!(rendered.contains("Writers"), "the second title is missing");
124 }
125
126 #[test]
127 fn a_brace_in_copy_is_a_brace() {
128 let rendered = format!("{:?}", braces());
129
130 assert!(
131 rendered.contains("{not a hole}"),
132 "a brace in copy was read as an interpolation"
133 );
134 }
135