• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

sunng87 / handlebars-rust / 17296949898

29 Jul 2025 03:04AM UTC coverage: 84.017% (+1.6%) from 82.399%
17296949898

push

github

web-flow
chore(deps): update criterion requirement from 0.6 to 0.7 (#719)

Updates the requirements on [criterion](https://github.com/bheisler/criterion.rs) to permit the latest version.
- [Changelog](https://github.com/bheisler/criterion.rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/bheisler/criterion.rs/compare/0.6.0...0.7.0)

---
updated-dependencies:
- dependency-name: criterion
  dependency-version: 0.7.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

1619 of 1927 relevant lines covered (84.02%)

7.38 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

95.83
/src/partial.rs
1
use std::collections::{HashMap, VecDeque};
2

3
use serde_json::Value as Json;
4

5
use crate::block::BlockContext;
6
use crate::context::{merge_json, Context};
7
use crate::error::RenderError;
8
use crate::output::Output;
9
use crate::registry::Registry;
10
use crate::render::{Decorator, Evaluable, RenderContext, Renderable};
11
use crate::template::Template;
12
use crate::{Path, RenderErrorReason};
13

14
pub(crate) const PARTIAL_BLOCK: &str = "@partial-block";
15

16
fn find_partial<'reg: 'rc, 'rc>(
6✔
17
    rc: &RenderContext<'reg, 'rc>,
18
    r: &'reg Registry<'reg>,
19
    d: &Decorator<'rc>,
20
    name: &str,
21
) -> Result<Option<&'rc Template>, RenderError> {
22
    if let Some(partial) = rc.get_partial(name) {
5✔
23
        return Ok(Some(partial));
3✔
24
    }
25

26
    if let Some(t) = rc.get_dev_mode_template(name) {
3✔
27
        return Ok(Some(t));
×
28
    }
29

30
    if let Some(t) = r.get_template(name) {
3✔
31
        return Ok(Some(t));
3✔
32
    }
33

34
    if let Some(tpl) = d.template() {
1✔
35
        return Ok(Some(tpl));
1✔
36
    }
37

38
    Ok(None)
1✔
39
}
40

41
pub fn expand_partial<'reg: 'rc, 'rc>(
6✔
42
    d: &Decorator<'rc>,
43
    r: &'reg Registry<'reg>,
44
    ctx: &'rc Context,
45
    rc: &mut RenderContext<'reg, 'rc>,
46
    out: &mut dyn Output,
47
) -> Result<(), RenderError> {
48
    // try eval inline partials first
49
    if let Some(t) = d.template() {
5✔
50
        t.eval(r, ctx, rc)?;
1✔
51
    }
52

53
    let tname = d.name();
6✔
54

55
    let current_template_before = rc.get_current_template_name();
5✔
56
    let indent_before = rc.get_indent_string().cloned();
6✔
57

58
    if rc.is_current_template(tname) {
11✔
59
        return Err(RenderErrorReason::CannotIncludeSelf.into());
2✔
60
    }
61

62
    let partial = find_partial(rc, r, d, tname)?;
11✔
63

64
    let Some(partial) = partial else {
5✔
65
        return Err(RenderErrorReason::PartialNotFound(tname.to_owned()).into());
2✔
66
    };
67

68
    let is_partial_block = tname == PARTIAL_BLOCK;
11✔
69

70
    // add partial block depth there are consecutive partial
71
    // blocks in the stack.
72
    if is_partial_block {
6✔
73
        rc.inc_partial_block_depth();
2✔
74
    } else {
75
        // depth cannot be lower than 0, which is guaranted in the
76
        // `dec_partial_block_depth` method
77
        rc.dec_partial_block_depth();
10✔
78
    }
79

80
    // hash
81
    let hash_ctx = d
×
82
        .hash()
83
        .iter()
84
        .map(|(k, v)| (*k, v.value()))
12✔
85
        .collect::<HashMap<&str, &Json>>();
86

87
    let mut partial_include_block = BlockContext::new();
5✔
88
    // evaluate context for partial
89
    let merged_context = if let Some(p) = d.param(0) {
11✔
90
        if let Some(relative_path) = p.relative_path() {
6✔
91
            // path as parameter provided
92
            merge_json(rc.evaluate(ctx, relative_path)?.as_json(), &hash_ctx)
9✔
93
        } else {
94
            // literal provided
95
            merge_json(p.value(), &hash_ctx)
2✔
96
        }
97
    } else {
98
        // use current path
99
        merge_json(rc.evaluate2(ctx, &Path::current())?.as_json(), &hash_ctx)
23✔
100
    };
101
    partial_include_block.set_base_value(merged_context);
6✔
102

103
    // replace and hold blocks from current render context
104
    let current_blocks = rc.replace_blocks(VecDeque::with_capacity(1));
6✔
105
    rc.push_block(partial_include_block);
7✔
106

107
    // @partial-block
108
    if let Some(pb) = d.template() {
5✔
109
        rc.push_partial_block(pb);
2✔
110
    }
111

112
    // indent
113
    rc.set_indent_string(d.indent().cloned());
11✔
114

115
    let result = partial.render(r, ctx, rc, out);
5✔
116

117
    // cleanup
118
    let trailing_newline = rc.get_trailine_newline();
10✔
119

120
    if d.template().is_some() {
5✔
121
        rc.pop_partial_block();
1✔
122
    }
123

124
    let _ = rc.replace_blocks(current_blocks);
10✔
125
    rc.set_trailing_newline(trailing_newline);
5✔
126
    rc.set_current_template_name(current_template_before);
5✔
127
    rc.set_indent_string(indent_before);
5✔
128

129
    result
5✔
130
}
131

132
#[cfg(test)]
133
mod test {
134
    use crate::context::Context;
135
    use crate::error::RenderError;
136
    use crate::output::Output;
137
    use crate::registry::Registry;
138
    use crate::render::{Helper, RenderContext};
139

140
    #[test]
141
    fn test() {
142
        let mut handlebars = Registry::new();
143
        assert!(handlebars
144
            .register_template_string("t0", "{{> t1}}")
145
            .is_ok());
146
        assert!(handlebars
147
            .register_template_string("t1", "{{this}}")
148
            .is_ok());
149
        assert!(handlebars
150
            .register_template_string("t2", "{{#> t99}}not there{{/t99}}")
151
            .is_ok());
152
        assert!(handlebars
153
            .register_template_string("t3", "{{#*inline \"t31\"}}{{this}}{{/inline}}{{> t31}}")
154
            .is_ok());
155
        assert!(handlebars
156
            .register_template_string(
157
                "t4",
158
                "{{#> t5}}{{#*inline \"nav\"}}navbar{{/inline}}{{/t5}}"
159
            )
160
            .is_ok());
161
        assert!(handlebars
162
            .register_template_string("t5", "include {{> nav}}")
163
            .is_ok());
164
        assert!(handlebars
165
            .register_template_string("t6", "{{> t1 a}}")
166
            .is_ok());
167
        assert!(handlebars
168
            .register_template_string(
169
                "t7",
170
                "{{#*inline \"t71\"}}{{a}}{{/inline}}{{> t71 a=\"world\"}}"
171
            )
172
            .is_ok());
173
        assert!(handlebars.register_template_string("t8", "{{a}}").is_ok());
174
        assert!(handlebars
175
            .register_template_string("t9", "{{> t8 a=2}}")
176
            .is_ok());
177

178
        assert_eq!(handlebars.render("t0", &1).ok().unwrap(), "1".to_string());
179
        assert_eq!(
180
            handlebars.render("t2", &1).ok().unwrap(),
181
            "not there".to_string()
182
        );
183
        assert_eq!(handlebars.render("t3", &1).ok().unwrap(), "1".to_string());
184
        assert_eq!(
185
            handlebars.render("t4", &1).ok().unwrap(),
186
            "include navbar".to_string()
187
        );
188
        assert_eq!(
189
            handlebars.render("t6", &json!({"a": "2"})).ok().unwrap(),
190
            "2".to_string()
191
        );
192
        assert_eq!(
193
            handlebars.render("t7", &1).ok().unwrap(),
194
            "world".to_string()
195
        );
196
        assert_eq!(handlebars.render("t9", &1).ok().unwrap(), "2".to_string());
197
    }
198

199
    #[test]
200
    fn test_include_partial_block() {
201
        let t0 = "hello {{> @partial-block}}";
202
        let t1 = "{{#> t0}}inner {{this}}{{/t0}}";
203

204
        let mut handlebars = Registry::new();
205
        assert!(handlebars.register_template_string("t0", t0).is_ok());
206
        assert!(handlebars.register_template_string("t1", t1).is_ok());
207

208
        let r0 = handlebars.render("t1", &true);
209
        assert_eq!(r0.ok().unwrap(), "hello inner true".to_string());
210
    }
211

212
    #[test]
213
    fn test_self_inclusion() {
214
        let t0 = "hello {{> t1}} {{> t0}}";
215
        let t1 = "some template";
216
        let mut handlebars = Registry::new();
217
        assert!(handlebars.register_template_string("t0", t0).is_ok());
218
        assert!(handlebars.register_template_string("t1", t1).is_ok());
219

220
        let r0 = handlebars.render("t0", &true);
221
        assert!(r0.is_err());
222
    }
223

224
    #[test]
225
    fn test_issue_143() {
226
        let main_template = "one{{> two }}three{{> two }}";
227
        let two_partial = "--- two ---";
228

229
        let mut handlebars = Registry::new();
230
        assert!(handlebars
231
            .register_template_string("template", main_template)
232
            .is_ok());
233
        assert!(handlebars
234
            .register_template_string("two", two_partial)
235
            .is_ok());
236

237
        let r0 = handlebars.render("template", &true);
238
        assert_eq!(r0.ok().unwrap(), "one--- two ---three--- two ---");
239
    }
240

241
    #[test]
242
    fn test_hash_context_outscope() {
243
        let main_template = "In: {{> p a=2}} Out: {{a}}";
244
        let p_partial = "{{a}}";
245

246
        let mut handlebars = Registry::new();
247
        assert!(handlebars
248
            .register_template_string("template", main_template)
249
            .is_ok());
250
        assert!(handlebars.register_template_string("p", p_partial).is_ok());
251

252
        let r0 = handlebars.render("template", &true);
253
        assert_eq!(r0.ok().unwrap(), "In: 2 Out: ");
254
    }
255

256
    #[test]
257
    fn test_partial_context_hash() {
258
        let mut hbs = Registry::new();
259
        hbs.register_template_string("one", "This is a test. {{> two name=\"fred\" }}")
260
            .unwrap();
261
        hbs.register_template_string("two", "Lets test {{name}}")
262
            .unwrap();
263
        assert_eq!(
264
            "This is a test. Lets test fred",
265
            hbs.render("one", &0).unwrap()
266
        );
267
    }
268

269
    #[test]
270
    fn teset_partial_context_with_both_hash_and_param() {
271
        let mut hbs = Registry::new();
272
        hbs.register_template_string("one", "This is a test. {{> two this name=\"fred\" }}")
273
            .unwrap();
274
        hbs.register_template_string("two", "Lets test {{name}} and {{root_name}}")
275
            .unwrap();
276
        assert_eq!(
277
            "This is a test. Lets test fred and tom",
278
            hbs.render("one", &json!({"root_name": "tom"})).unwrap()
279
        );
280
    }
281

282
    #[test]
283
    fn test_partial_subexpression_context_hash() {
284
        let mut hbs = Registry::new();
285
        hbs.register_template_string("one", "This is a test. {{> (x @root) name=\"fred\" }}")
286
            .unwrap();
287
        hbs.register_template_string("two", "Lets test {{name}}")
288
            .unwrap();
289

290
        hbs.register_helper(
291
            "x",
292
            Box::new(
293
                |_: &Helper<'_>,
294
                 _: &Registry<'_>,
295
                 _: &Context,
296
                 _: &mut RenderContext<'_, '_>,
297
                 out: &mut dyn Output|
298
                 -> Result<(), RenderError> {
299
                    out.write("two")?;
300
                    Ok(())
301
                },
302
            ),
303
        );
304
        assert_eq!(
305
            "This is a test. Lets test fred",
306
            hbs.render("one", &0).unwrap()
307
        );
308
    }
309

310
    #[test]
311
    fn test_nested_partial_scope() {
312
        let t = "{{#*inline \"pp\"}}{{a}} {{b}}{{/inline}}{{#each c}}{{> pp a=2}}{{/each}}";
313
        let data = json!({"c": [{"b": true}, {"b": false}]});
314

315
        let mut handlebars = Registry::new();
316
        assert!(handlebars.register_template_string("t", t).is_ok());
317
        let r0 = handlebars.render("t", &data);
318
        assert_eq!(r0.ok().unwrap(), "2 true2 false");
319
    }
320

321
    #[test]
322
    fn test_nested_partial_block() {
323
        let mut handlebars = Registry::new();
324
        let template1 = "<outer>{{> @partial-block }}</outer>";
325
        let template2 = "{{#> t1 }}<inner>{{> @partial-block }}</inner>{{/ t1 }}";
326
        let template3 = "{{#> t2 }}Hello{{/ t2 }}";
327

328
        handlebars
329
            .register_template_string("t1", template1)
330
            .unwrap();
331
        handlebars
332
            .register_template_string("t2", template2)
333
            .unwrap();
334

335
        let page = handlebars.render_template(template3, &json!({})).unwrap();
336
        assert_eq!("<outer><inner>Hello</inner></outer>", page);
337
    }
338

339
    #[test]
340
    fn test_subexpression_partial_block() {
341
        let mut handlebars = Registry::new();
342
        let template1 = "<outer>{{> @partial-block }}</outer>";
343
        let template2 = "{{#> (x 'foo') }}<inner>{{> @partial-block }}</inner>{{/}}";
344
        let template3 = "{{#> (y this) }}Hello{{/}} World";
345

346
        handlebars.register_helper(
347
            "x",
348
            Box::new(
349
                |_: &Helper<'_>,
350
                 _: &Registry<'_>,
351
                 _: &Context,
352
                 _: &mut RenderContext<'_, '_>,
353
                 out: &mut dyn Output|
354
                 -> Result<(), RenderError> {
355
                    out.write("t1")?;
356
                    Ok(())
357
                },
358
            ),
359
        );
360
        handlebars.register_helper(
361
            "y",
362
            Box::new(
363
                |_: &Helper<'_>,
364
                 _: &Registry<'_>,
365
                 _: &Context,
366
                 _: &mut RenderContext<'_, '_>,
367
                 out: &mut dyn Output|
368
                 -> Result<(), RenderError> {
369
                    out.write("t2")?;
370
                    Ok(())
371
                },
372
            ),
373
        );
374
        handlebars
375
            .register_template_string("t1", template1)
376
            .unwrap();
377
        handlebars
378
            .register_template_string("t2", template2)
379
            .unwrap();
380

381
        let page = handlebars.render_template(template3, &json!({})).unwrap();
382
        assert_eq!("<outer><inner>Hello</inner></outer> World", page);
383
    }
384

385
    #[test]
386
    fn test_up_to_partial_level() {
387
        let outer = r#"{{>inner name="fruit:" vegetables=fruits}}"#;
388
        let inner = "{{#each vegetables}}{{../name}} {{this}},{{/each}}";
389

390
        let data = json!({ "fruits": ["carrot", "tomato"] });
391

392
        let mut handlebars = Registry::new();
393
        handlebars.register_template_string("outer", outer).unwrap();
394
        handlebars.register_template_string("inner", inner).unwrap();
395

396
        assert_eq!(
397
            handlebars.render("outer", &data).unwrap(),
398
            "fruit: carrot,fruit: tomato,"
399
        );
400
    }
401

402
    #[test]
403
    fn line_stripping_with_inline_and_partial() {
404
        let tpl0 = r#"{{#*inline "foo"}}foo
405
{{/inline}}
406
{{> foo}}
407
{{> foo}}
408
{{> foo}}"#;
409
        let tpl1 = r#"{{#*inline "foo"}}foo{{/inline}}
410
{{> foo}}
411
{{> foo}}
412
{{> foo}}"#;
413

414
        let hbs = Registry::new();
415
        assert_eq!(
416
            r"foo
417
foo
418
foo
419
",
420
            hbs.render_template(tpl0, &json!({})).unwrap()
421
        );
422
        assert_eq!(
423
            r"
424
foofoofoo",
425
            hbs.render_template(tpl1, &json!({})).unwrap()
426
        );
427
    }
428

429
    #[test]
430
    fn test_partial_indent() {
431
        let outer = r"                {{> inner inner_solo}}
432

433
{{#each inners}}
434
                {{> inner}}
435
{{/each}}
436

437
        {{#each inners}}
438
        {{> inner}}
439
        {{/each}}
440
";
441
        let inner = r"name: {{name}}
442
";
443

444
        let mut hbs = Registry::new();
445

446
        hbs.register_template_string("inner", inner).unwrap();
447
        hbs.register_template_string("outer", outer).unwrap();
448

449
        let result = hbs
450
            .render(
451
                "outer",
452
                &json!({
453
                    "inner_solo": {"name": "inner_solo"},
454
                    "inners": [
455
                        {"name": "hello"},
456
                        {"name": "there"}
457
                    ]
458
                }),
459
            )
460
            .unwrap();
461

462
        assert_eq!(
463
            result,
464
            r"                name: inner_solo
465

466
                name: hello
467
                name: there
468

469
        name: hello
470
        name: there
471
"
472
        );
473
    }
474
    // Rule::partial_expression should not trim leading indent  by default
475

476
    #[test]
477
    fn test_partial_prevent_indent() {
478
        let outer = r"                {{> inner inner_solo}}
479

480
{{#each inners}}
481
                {{> inner}}
482
{{/each}}
483

484
        {{#each inners}}
485
        {{> inner}}
486
        {{/each}}
487
";
488
        let inner = r"name: {{name}}
489
";
490

491
        let mut hbs = Registry::new();
492
        hbs.set_prevent_indent(true);
493

494
        hbs.register_template_string("inner", inner).unwrap();
495
        hbs.register_template_string("outer", outer).unwrap();
496

497
        let result = hbs
498
            .render(
499
                "outer",
500
                &json!({
501
                    "inner_solo": {"name": "inner_solo"},
502
                    "inners": [
503
                        {"name": "hello"},
504
                        {"name": "there"}
505
                    ]
506
                }),
507
            )
508
            .unwrap();
509

510
        assert_eq!(
511
            result,
512
            r"                name: inner_solo
513

514
                name: hello
515
                name: there
516

517
        name: hello
518
        name: there
519
"
520
        );
521
    }
522

523
    #[test]
524
    fn test_nested_partials() {
525
        let mut hb = Registry::new();
526
        hb.register_template_string("partial", "{{> @partial-block}}")
527
            .unwrap();
528
        hb.register_template_string(
529
            "index",
530
            r"{{#>partial}}
531
    Yo
532
    {{#>partial}}
533
    Yo 2
534
    {{/partial}}
535
{{/partial}}",
536
        )
537
        .unwrap();
538
        assert_eq!(
539
            r"    Yo
540
    Yo 2
541
",
542
            hb.render("index", &()).unwrap()
543
        );
544

545
        hb.register_template_string("partial2", "{{> @partial-block}}")
546
            .unwrap();
547
        let r2 = hb
548
            .render_template(
549
                r"{{#> partial}}
550
{{#> partial2}}
551
:(
552
{{/partial2}}
553
{{/partial}}",
554
                &(),
555
            )
556
            .unwrap();
557
        assert_eq!(":(\n", r2);
558
    }
559

560
    #[test]
561
    fn test_partial_context_issue_495() {
562
        let mut hb = Registry::new();
563
        hb.register_template_string(
564
            "t1",
565
            r#"{{~#*inline "displayName"~}}
566
Template:{{name}}
567
{{/inline}}
568
{{#each data as |name|}}
569
Name:{{name}}
570
{{>displayName name="aaaa"}}
571
{{/each}}"#,
572
        )
573
        .unwrap();
574

575
        hb.register_template_string(
576
            "t2",
577
            r#"{{~#*inline "displayName"~}}
578
Template:{{this}}
579
{{/inline}}
580
{{#each data as |name|}}
581
Name:{{name}}
582
{{>displayName}}
583
{{/each}}"#,
584
        )
585
        .unwrap();
586

587
        let data = json!({
588
            "data": ["hudel", "test"]
589
        });
590

591
        assert_eq!(
592
            r"Name:hudel
593
Template:aaaa
594
Name:test
595
Template:aaaa
596
",
597
            hb.render("t1", &data).unwrap()
598
        );
599
        assert_eq!(
600
            r"Name:hudel
601
Template:hudel
602
Name:test
603
Template:test
604
",
605
            hb.render("t2", &data).unwrap()
606
        );
607
    }
608

609
    #[test]
610
    fn test_multiline_partial_indent() {
611
        let mut hb = Registry::new();
612

613
        hb.register_template_string(
614
            "t1",
615
            r#"{{#*inline "thepartial"}}
616
  inner first line
617
  inner second line
618
{{/inline}}
619
  {{> thepartial}}
620
outer third line"#,
621
        )
622
        .unwrap();
623
        assert_eq!(
624
            r"    inner first line
625
    inner second line
626
outer third line",
627
            hb.render("t1", &()).unwrap()
628
        );
629

630
        hb.register_template_string(
631
            "t2",
632
            r#"{{#*inline "thepartial"}}inner first line
633
inner second line
634
{{/inline}}
635
  {{> thepartial}}
636
outer third line"#,
637
        )
638
        .unwrap();
639
        assert_eq!(
640
            r"  inner first line
641
  inner second line
642
outer third line",
643
            hb.render("t2", &()).unwrap()
644
        );
645

646
        hb.register_template_string(
647
            "t3",
648
            r#"{{#*inline "thepartial"}}{{a}}{{/inline}}
649
  {{> thepartial}}
650
outer third line"#,
651
        )
652
        .unwrap();
653
        assert_eq!(
654
            r"
655
  inner first line
656
  inner second lineouter third line",
657
            hb.render("t3", &json!({"a": "inner first line\ninner second line"}))
658
                .unwrap()
659
        );
660

661
        hb.register_template_string(
662
            "t4",
663
            r#"{{#*inline "thepartial"}}
664
  inner first line
665
  inner second line
666
{{/inline}}
667
  {{~> thepartial}}
668
outer third line"#,
669
        )
670
        .unwrap();
671
        assert_eq!(
672
            r"  inner first line
673
  inner second line
674
outer third line",
675
            hb.render("t4", &()).unwrap()
676
        );
677

678
        let mut hb2 = Registry::new();
679
        hb2.set_prevent_indent(true);
680

681
        hb2.register_template_string(
682
            "t1",
683
            r#"{{#*inline "thepartial"}}
684
  inner first line
685
  inner second line
686
{{/inline}}
687
  {{> thepartial}}
688
outer third line"#,
689
        )
690
        .unwrap();
691
        assert_eq!(
692
            r"    inner first line
693
  inner second line
694
outer third line",
695
            hb2.render("t1", &()).unwrap()
696
        );
697
    }
698

699
    #[test]
700
    fn test_indent_level_on_nested_partials() {
701
        let nested_partial = "
702
<div>
703
    content
704
</div>
705
";
706
        let partial = "
707
<div>
708
    {{>nested_partial}}
709
</div>
710
";
711

712
        let partial_indented = "
713
<div>
714
    {{>partial}}
715
</div>
716
";
717

718
        let result = "
719
<div>
720
    <div>
721
        <div>
722
            content
723
        </div>
724
    </div>
725
</div>
726
";
727

728
        let mut hb = Registry::new();
729
        hb.register_template_string("nested_partial", nested_partial.trim_start())
730
            .unwrap();
731
        hb.register_template_string("partial", partial.trim_start())
732
            .unwrap();
733
        hb.register_template_string("partial_indented", partial_indented.trim_start())
734
            .unwrap();
735

736
        let s = hb.render("partial_indented", &()).unwrap();
737

738
        assert_eq!(&s, result.trim_start());
739
    }
740

741
    #[test]
742
    fn test_issue_534() {
743
        let t1 = "{{title}}";
744
        let t2 = "{{#each modules}}{{> (lookup this \"module\") content name=0}}{{/each}}";
745

746
        let data = json!({
747
          "modules": [
748
            {"module": "t1", "content": {"title": "foo"}},
749
            {"module": "t1", "content": {"title": "bar"}},
750
          ]
751
        });
752

753
        let mut hbs = Registry::new();
754
        hbs.register_template_string("t1", t1).unwrap();
755
        hbs.register_template_string("t2", t2).unwrap();
756

757
        assert_eq!("foobar", hbs.render("t2", &data).unwrap());
758
    }
759

760
    #[test]
761
    fn test_partial_not_found() {
762
        let t1 = "{{> bar}}";
763
        let hbs = Registry::new();
764
        assert!(hbs.render_template(t1, &()).is_err());
765
    }
766

767
    #[test]
768
    fn test_issue_643_this_context() {
769
        let t1 = "{{this}}";
770
        let t2 = "{{> t1 \"hello world\"}}";
771

772
        let mut hbs = Registry::new();
773
        hbs.register_template_string("t1", t1).unwrap();
774
        hbs.register_template_string("t2", t2).unwrap();
775

776
        assert_eq!("hello world", hbs.render("t2", &()).unwrap());
777

778
        let t1 = "{{a}} {{[0]}} {{[1]}}";
779
        let t2 = "{{> t1 \"hello world\" a=1}}";
780

781
        let mut hbs = Registry::new();
782
        hbs.register_template_string("t1", t1).unwrap();
783
        hbs.register_template_string("t2", t2).unwrap();
784

785
        assert_eq!("1 h e", hbs.render("t2", &()).unwrap());
786

787
        let t1 = "{{#each this}}{{@key}}:{{this}},{{/each}}";
788
        let t2 = "{{> t1 a=1}}";
789

790
        let mut hbs = Registry::new();
791
        hbs.register_template_string("t1", t1).unwrap();
792
        hbs.register_template_string("t2", t2).unwrap();
793

794
        assert_eq!("a:1,", hbs.render("t2", &()).unwrap());
795

796
        let t1 = "{{#each this}}{{@key}}:{{this}},{{/each}}";
797
        let t2 = "{{> t1 a=1}}";
798

799
        let mut hbs = Registry::new();
800
        hbs.register_template_string("t1", t1).unwrap();
801
        hbs.register_template_string("t2", t2).unwrap();
802

803
        assert_eq!("a:1,b:2,", hbs.render("t2", &json!({"b": 2})).unwrap());
804

805
        let t1 = "{{#each this}}{{@key}}:{{this}},{{/each}}";
806
        let t2 = "{{> t1 b a=1}}";
807

808
        let mut hbs = Registry::new();
809
        hbs.register_template_string("t1", t1).unwrap();
810
        hbs.register_template_string("t2", t2).unwrap();
811

812
        assert_eq!("a:1,", hbs.render("t2", &json!({"b": 2})).unwrap());
813
    }
814
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc