Add tests for explicit context setting that check failure conditions and implement a helper function to generate a new breadcrumb stack.
This commit is contained in:
		
							parent
							
								
									8121c93392
								
							
						
					
					
						commit
						4a21ae5af3
					
				| @ -37,4 +37,24 @@ Explicitly setting a context does not work on a reference, but it has revealed t | ||||
| Paths | ||||
| ----- | ||||
| 
 | ||||
| Explicit contexts do support deep paths | ||||
| Explicit contexts do support deep paths. | ||||
| 
 | ||||
| Else Blocks | ||||
| ----------- | ||||
| 
 | ||||
| Else blocks also use an explicit context. | ||||
| 
 | ||||
| Complete Failure | ||||
| ---------------- | ||||
| 
 | ||||
| If the walk destination does not exist, and the explicit context does not exist, then you end up with absolutely no context. | ||||
| 
 | ||||
| Regular Path Failure | ||||
| -------------------- | ||||
| 
 | ||||
| If the regular path fails but the explicit path succeeds then the context is set to the explicit path. | ||||
| 
 | ||||
| Falsey Explicit Path | ||||
| -------------------- | ||||
| 
 | ||||
| Since dust would not walk to a falsey path, theres no difference between a falsey path and a non-existent path. | ||||
|  | ||||
| @ -24,5 +24,6 @@ | ||||
|     "explicit": { | ||||
|       "pet": "cat" | ||||
|     } | ||||
|   } | ||||
|   }, | ||||
|   "empty_array": [] | ||||
| } | ||||
|  | ||||
| @ -157,3 +157,101 @@ Variable Explicit{~n} | ||||
|     {/person} | ||||
| {/loop} | ||||
| 
 | ||||
| {! What context is set on else blocks? !} | ||||
| Else Block Regular{~n} | ||||
| =================={~n} | ||||
| {#loop} | ||||
|     {#empty_array} | ||||
|         MAIN {$idx}: {name} has a pet {pet} but not a {some_global}{~n} | ||||
|     {:else} | ||||
|         ELSE {$idx}: {name} has a pet {pet} but not a {some_global}{~n} | ||||
|     {/empty_array} | ||||
| {/loop} | ||||
| 
 | ||||
| Else Block Explicit{~n} | ||||
| ==================={~n} | ||||
| {#loop} | ||||
|     {#empty_array:explicit} | ||||
|         MAIN {$idx}: {person.name} has a pet {pet} but not a {some_global}{~n} | ||||
|     {:else} | ||||
|         ELSE {$idx}: {person.name} has a pet {pet} but not a {some_global}{~n} | ||||
|     {/empty_array} | ||||
| {/loop} | ||||
| 
 | ||||
| {! What context is set when the explicit context path does not exist? !} | ||||
| Failed Explicit Regular{~n} | ||||
| ======================={~n} | ||||
| {#loop} | ||||
|     {#person} | ||||
|         {$idx}: {name} has a pet {pet} but not a {some_global}{~n} | ||||
|     {/person} | ||||
| {/loop} | ||||
| 
 | ||||
| Failed Explicit Explicit{~n} | ||||
| ========================{~n} | ||||
| {#loop} | ||||
|     {#person:foobar} | ||||
|         {$idx}: {name} has a pet {pet} but not a {some_global}{~n} | ||||
|     {/person} | ||||
| {/loop} | ||||
| 
 | ||||
| {! What context is set when the regular path and explicit context path does not exist? !} | ||||
| Failed Everything Regular{~n} | ||||
| ========================={~n} | ||||
| BEFORE {.|js}{~n} | ||||
| {#foo} | ||||
|     MAIN {.|js}{~n} | ||||
| {:else} | ||||
|     ELSE {.|js}{~n} | ||||
| {/foo} | ||||
| 
 | ||||
| Failed Everything Explicit{~n} | ||||
| =========================={~n} | ||||
| {#foo:bar} | ||||
|     MAIN {.|js}{~n} | ||||
| {:else} | ||||
|     ELSE {.|js}{~n} | ||||
| {/foo} | ||||
| 
 | ||||
| {! What context is set when the regular context path does not exist? !} | ||||
| Failed Regular Path Regular{~n} | ||||
| ==========================={~n} | ||||
| {#loop} | ||||
|     {#foo} | ||||
|         MAIN {$idx}: {name} has a pet {pet} but not a {some_global}{~n} | ||||
|     {:else} | ||||
|         ELSE {$idx}: {name} has a pet {pet} but not a {some_global}{~n} | ||||
|     {/foo} | ||||
| {/loop} | ||||
| 
 | ||||
| Failed Regular Path Explicit{~n} | ||||
| ============================{~n} | ||||
| {#loop} | ||||
|     {#foo:explicit} | ||||
|         MAIN {$idx}: {name} has a pet {pet} but not a {some_global}{~n} | ||||
|     {:else} | ||||
|         ELSE {$idx}: {name} has a pet {pet} but not a {some_global}{~n} | ||||
|     {/foo} | ||||
| {/loop} | ||||
| 
 | ||||
| {! What context is set when the explicit path is falsey? !} | ||||
| Falsey Explicit Path Regular{~n} | ||||
| ============================{~n} | ||||
| {#loop} | ||||
|     {#foo} | ||||
|         MAIN {$idx}: {name} has a pet {pet} but not a {some_global}{~n} | ||||
|     {:else} | ||||
|         ELSE {$idx}: {name} has a pet {pet} but not a {some_global}{~n} | ||||
|     {/foo} | ||||
| {/loop} | ||||
| 
 | ||||
| Falsey Explicit Path Explicit{~n} | ||||
| ============================={~n} | ||||
| {#loop} | ||||
|     {#foo:empty_array} | ||||
|         MAIN {$idx}: {name} has a pet {pet} but not a {some_global}{~n} | ||||
|     {:else} | ||||
|         ELSE {$idx}: {name} has a pet {pet} but not a {some_global}{~n} | ||||
|         {.|js}{~n} | ||||
|     {/foo} | ||||
| {/loop} | ||||
|  | ||||
| @ -9,6 +9,7 @@ pub use parser::Filter; | ||||
| pub use parser::KVPair; | ||||
| pub use parser::OwnedLiteral; | ||||
| pub use parser::PartialNameElement; | ||||
| pub use parser::Path; | ||||
| pub use parser::RValue; | ||||
| pub use parser::Special; | ||||
| pub use parser::Template; | ||||
|  | ||||
| @ -3,6 +3,7 @@ use crate::parser::Body; | ||||
| use crate::parser::DustTag; | ||||
| use crate::parser::KVPair; | ||||
| use crate::parser::PartialNameElement; | ||||
| use crate::parser::Path; | ||||
| use crate::parser::RValue; | ||||
| use crate::parser::Special; | ||||
| use crate::parser::Template; | ||||
| @ -551,6 +552,61 @@ impl<'a> DustRenderer<'a> { | ||||
|         } | ||||
|         final_filters | ||||
|     } | ||||
| 
 | ||||
|     /// Generate a new breadcrumbs object
 | ||||
|     ///
 | ||||
|     /// This function generates a new breadcrumbs object based on the
 | ||||
|     /// new context information provided.
 | ||||
|     ///
 | ||||
|     /// explicit_context is for contexts specified with a `:path`
 | ||||
|     /// inside a dust tag.
 | ||||
|     ///
 | ||||
|     /// injected_context is for any generated context. This includes
 | ||||
|     /// both parameters on a tag and also the handling of $idx and
 | ||||
|     /// $len.
 | ||||
|     ///
 | ||||
|     /// New context element is the element is an element to append to
 | ||||
|     /// the end, generally for use in section tags which walk to a new
 | ||||
|     /// context.
 | ||||
|     ///
 | ||||
|     /// If explicit_context is not None, then the final breadcrumb stack will be:
 | ||||
|     ///
 | ||||
|     /// ```
 | ||||
|     /// breadcrumbs
 | ||||
|     /// injected_context
 | ||||
|     /// new_context_element
 | ||||
|     /// ```
 | ||||
|     ///
 | ||||
|     /// However, if explicit_context is not None, then the old
 | ||||
|     /// breadcrumbs are omitted, leading to the new breadcrumb stack
 | ||||
|     /// as:
 | ||||
|     ///
 | ||||
|     /// ```
 | ||||
|     /// injected_context
 | ||||
|     /// explicit_context
 | ||||
|     /// new_context_element
 | ||||
|     /// ```
 | ||||
|     fn new_breadcrumbs<'b>( | ||||
|         breadcrumbs: &'b Vec<&'b dyn ContextElement>, | ||||
|         injected_context: Option<&'b dyn ContextElement>, | ||||
|         explicit_context: &Option<Path<'b>>, | ||||
|         new_context_element: Option<&'b dyn ContextElement>, | ||||
|     ) -> Vec<&'b dyn ContextElement> { | ||||
|         let mut new_stack = match explicit_context { | ||||
|             Some(_) => Vec::with_capacity(3), | ||||
|             None => breadcrumbs.clone(), | ||||
|         }; | ||||
|         injected_context.map(|ctx| new_stack.push(ctx)); | ||||
|         explicit_context.as_ref().map(|path| { | ||||
|             walk_path(breadcrumbs, &path.keys).map(|val| { | ||||
|                 if val.is_truthy() { | ||||
|                     new_stack.push(val) | ||||
|                 } | ||||
|             }); | ||||
|         }); | ||||
|         new_context_element.map(|ctx| new_stack.push(ctx)); | ||||
|         new_stack | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[cfg(test)] | ||||
|  | ||||
| @ -42,6 +42,12 @@ where | ||||
|     B: Borrow<dyn ContextElement + 'a>, | ||||
|     P: Borrow<str>, | ||||
| { | ||||
|     if breadcrumbs.is_empty() { | ||||
|         // This happens when you use a section with an explicit
 | ||||
|         // context path, where both the path and the explicit context
 | ||||
|         // path fail, leaving you with absolutely no context.
 | ||||
|         return Err(WalkError::CantWalk); | ||||
|     } | ||||
|     if path.is_empty() { | ||||
|         return Ok(breadcrumbs | ||||
|             .last() | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Tom Alexander
						Tom Alexander