1# Automatically generated from specification file: 'inverted.json' 2# 3# Inverted Section tags and End Section tags are used in combination to wrap a 4# section of the template. 5# 6# These tags' content MUST be a non-whitespace character sequence NOT 7# containing the current closing delimiter; each Inverted Section tag MUST be 8# followed by an End Section tag with the same content within the same 9# section. 10# 11# This tag's content names the data to replace�the tag. Name resolution is as 12# follows: 13# 1) Split the name on periods; the first part is the name to resolve, any 14# remaining parts should be retained. 15# 2) Walk the context stack from top to bottom, finding the first context 16# that is a) a hash containing the name as a key OR b) an object responding 17# to a method with the given name. 18# 3) If the context is a hash, the data is the value associated with the 19# name. 20# 4) If the context is an object and the method with the given name has an 21# arity of 1, the method SHOULD be called with a String containing the 22# unprocessed contents of the sections; the data is the value returned. 23# 5) Otherwise, the data is the value returned by calling the method with 24# the given name. 25# 6) If any name parts were retained in step 1, each should be resolved 26# against a context stack containing only the result from the former 27# resolution. If any part fails resolution, the result should be considered 28# falsey, and should interpolate as the empty string. 29# If the data is not of a list type, it is coerced into a list as follows: if 30# the data is truthy (e.g. `!!data == true`), use a single-element list 31# containing the data, otherwise use an empty list. 32# 33# This section MUST NOT be rendered unless the data list is empty. 34# 35# Inverted Section and End Section tags SHOULD be treated as standalone when 36# appropriate. 37# 38library(testthat) 39context('Spec v1.1, inverted') 40 41test_that( "Falsey", { 42 #"Falsey sections should have their contents rendered." 43 template <- "\"{{^boolean}}This should be rendered.{{/boolean}}\"" 44 data <- list(boolean = FALSE) 45 46 47 str <- whisker.render(template, data=data) 48 49 expect_equal(str, "\"This should be rendered.\"", label=deparse(str), info="Falsey sections should have their contents rendered.") 50}) 51 52test_that( "Truthy", { 53 #"Truthy sections should have their contents omitted." 54 template <- "\"{{^boolean}}This should not be rendered.{{/boolean}}\"" 55 data <- list(boolean = TRUE) 56 57 58 str <- whisker.render(template, data=data) 59 60 expect_equal(str, "\"\"", label=deparse(str), info="Truthy sections should have their contents omitted.") 61}) 62 63test_that( "Context", { 64 #"Objects and hashes should behave like truthy values." 65 template <- "\"{{^context}}Hi {{name}}.{{/context}}\"" 66 data <- list(context = list(name = "Joe")) 67 68 69 str <- whisker.render(template, data=data) 70 71 expect_equal(str, "\"\"", label=deparse(str), info="Objects and hashes should behave like truthy values.") 72}) 73 74test_that( "List", { 75 #"Lists should behave like truthy values." 76 template <- "\"{{^list}}{{n}}{{/list}}\"" 77 data <- list(list = list(list(n = 1), list(n = 2), list(n = 3))) 78 79 80 str <- whisker.render(template, data=data) 81 82 expect_equal(str, "\"\"", label=deparse(str), info="Lists should behave like truthy values.") 83}) 84 85test_that( "Empty List", { 86 #"Empty lists should behave like falsey values." 87 template <- "\"{{^list}}Yay lists!{{/list}}\"" 88 data <- list(list = list()) 89 90 91 str <- whisker.render(template, data=data) 92 93 expect_equal(str, "\"Yay lists!\"", label=deparse(str), info="Empty lists should behave like falsey values.") 94}) 95 96test_that( "Doubled", { 97 #"Multiple inverted sections per template should be permitted." 98 template <- "{{^bool}}\n* first\n{{/bool}}\n* {{two}}\n{{^bool}}\n* third\n{{/bool}}\n" 99 data <- list(two = "second", bool = FALSE) 100 101 102 str <- whisker.render(template, data=data) 103 104 expect_equal(str, "* first\n* second\n* third\n", label=deparse(str), info="Multiple inverted sections per template should be permitted.") 105}) 106 107test_that( "Nested (Falsey)", { 108 #"Nested falsey sections should have their contents rendered." 109 template <- "| A {{^bool}}B {{^bool}}C{{/bool}} D{{/bool}} E |" 110 data <- list(bool = FALSE) 111 112 113 str <- whisker.render(template, data=data) 114 115 expect_equal(str, "| A B C D E |", label=deparse(str), info="Nested falsey sections should have their contents rendered.") 116}) 117 118test_that( "Nested (Truthy)", { 119 #"Nested truthy sections should be omitted." 120 template <- "| A {{^bool}}B {{^bool}}C{{/bool}} D{{/bool}} E |" 121 data <- list(bool = TRUE) 122 123 124 str <- whisker.render(template, data=data) 125 126 expect_equal(str, "| A E |", label=deparse(str), info="Nested truthy sections should be omitted.") 127}) 128 129test_that( "Context Misses", { 130 #"Failed context lookups should be considered falsey." 131 template <- "[{{^missing}}Cannot find key 'missing'!{{/missing}}]" 132 data <- list() 133 134 135 str <- whisker.render(template, data=data) 136 137 expect_equal(str, "[Cannot find key 'missing'!]", label=deparse(str), info="Failed context lookups should be considered falsey.") 138}) 139 140test_that( "Dotted Names - Truthy", { 141 #"Dotted names should be valid for Inverted Section tags." 142 template <- "\"{{^a.b.c}}Not Here{{/a.b.c}}\" == \"\"" 143 data <- list(a = list(b = list(c = TRUE))) 144 145 146 str <- whisker.render(template, data=data) 147 148 expect_equal(str, "\"\" == \"\"", label=deparse(str), info="Dotted names should be valid for Inverted Section tags.") 149}) 150 151test_that( "Dotted Names - Falsey", { 152 #"Dotted names should be valid for Inverted Section tags." 153 template <- "\"{{^a.b.c}}Not Here{{/a.b.c}}\" == \"Not Here\"" 154 data <- list(a = list(b = list(c = FALSE))) 155 156 157 str <- whisker.render(template, data=data) 158 159 expect_equal(str, "\"Not Here\" == \"Not Here\"", label=deparse(str), info="Dotted names should be valid for Inverted Section tags.") 160}) 161 162test_that( "Dotted Names - Broken Chains", { 163 #"Dotted names that cannot be resolved should be considered falsey." 164 template <- "\"{{^a.b.c}}Not Here{{/a.b.c}}\" == \"Not Here\"" 165 data <- list(a = list()) 166 167 168 str <- whisker.render(template, data=data) 169 170 expect_equal(str, "\"Not Here\" == \"Not Here\"", label=deparse(str), info="Dotted names that cannot be resolved should be considered falsey.") 171}) 172 173test_that( "Surrounding Whitespace", { 174 #"Inverted sections should not alter surrounding whitespace." 175 template <- " | {{^boolean}}\t|\t{{/boolean}} | \n" 176 data <- list(boolean = FALSE) 177 178 179 str <- whisker.render(template, data=data) 180 181 expect_equal(str, " | \t|\t | \n", label=deparse(str), info="Inverted sections should not alter surrounding whitespace.") 182}) 183 184test_that( "Internal Whitespace", { 185 #"Inverted should not alter internal whitespace." 186 template <- " | {{^boolean}} {{! Important Whitespace }}\n {{/boolean}} | \n" 187 data <- list(boolean = FALSE) 188 189 190 str <- whisker.render(template, data=data) 191 192 expect_equal(str, " | \n | \n", label=deparse(str), info="Inverted should not alter internal whitespace.") 193}) 194 195test_that( "Indented Inline Sections", { 196 #"Single-line sections should not alter surrounding whitespace." 197 template <- " {{^boolean}}NO{{/boolean}}\n {{^boolean}}WAY{{/boolean}}\n" 198 data <- list(boolean = FALSE) 199 200 201 str <- whisker.render(template, data=data) 202 203 expect_equal(str, " NO\n WAY\n", label=deparse(str), info="Single-line sections should not alter surrounding whitespace.") 204}) 205 206test_that( "Standalone Lines", { 207 #"Standalone lines should be removed from the template." 208 template <- "| This Is\n{{^boolean}}\n|\n{{/boolean}}\n| A Line\n" 209 data <- list(boolean = FALSE) 210 211 212 str <- whisker.render(template, data=data) 213 214 expect_equal(str, "| This Is\n|\n| A Line\n", label=deparse(str), info="Standalone lines should be removed from the template.") 215}) 216 217test_that( "Standalone Indented Lines", { 218 #"Standalone indented lines should be removed from the template." 219 template <- "| This Is\n {{^boolean}}\n|\n {{/boolean}}\n| A Line\n" 220 data <- list(boolean = FALSE) 221 222 223 str <- whisker.render(template, data=data) 224 225 expect_equal(str, "| This Is\n|\n| A Line\n", label=deparse(str), info="Standalone indented lines should be removed from the template.") 226}) 227 228test_that( "Standalone Line Endings", { 229 #"\"\\r\\n\" should be considered a newline for standalone tags." 230 template <- "|\r\n{{^boolean}}\r\n{{/boolean}}\r\n|" 231 data <- list(boolean = FALSE) 232 233 234 str <- whisker.render(template, data=data) 235 236 expect_equal(str, "|\r\n|", label=deparse(str), info="\"\\r\\n\" should be considered a newline for standalone tags.") 237}) 238 239test_that( "Standalone Without Previous Line", { 240 #"Standalone tags should not require a newline to precede them." 241 template <- " {{^boolean}}\n^{{/boolean}}\n/" 242 data <- list(boolean = FALSE) 243 244 245 str <- whisker.render(template, data=data) 246 247 expect_equal(str, "^\n/", label=deparse(str), info="Standalone tags should not require a newline to precede them.") 248}) 249 250test_that( "Standalone Without Newline", { 251 #"Standalone tags should not require a newline to follow them." 252 template <- "^{{^boolean}}\n/\n {{/boolean}}" 253 data <- list(boolean = FALSE) 254 255 256 str <- whisker.render(template, data=data) 257 258 expect_equal(str, "^\n/\n", label=deparse(str), info="Standalone tags should not require a newline to follow them.") 259}) 260 261test_that( "Padding", { 262 #"Superfluous in-tag whitespace should be ignored." 263 template <- "|{{^ boolean }}={{/ boolean }}|" 264 data <- list(boolean = FALSE) 265 266 267 str <- whisker.render(template, data=data) 268 269 expect_equal(str, "|=|", label=deparse(str), info="Superfluous in-tag whitespace should be ignored.") 270}) 271 272