mirror of
https://github.com/sbrow/thor.git
synced 2026-08-26 19:33:32 -04:00
199 lines
5.0 KiB
Odin
199 lines
5.0 KiB
Odin
#+test
|
|
#+feature dynamic-literals
|
|
package mustache
|
|
|
|
import "core:fmt"
|
|
import "core:testing"
|
|
|
|
Inner :: struct {
|
|
foo: string,
|
|
bar: int,
|
|
}
|
|
|
|
Page :: struct {
|
|
title: string,
|
|
}
|
|
|
|
Outer :: struct {
|
|
title: string,
|
|
page: Page,
|
|
inner: Inner,
|
|
numbers: [3]int,
|
|
}
|
|
|
|
@(test)
|
|
test_validate_simple_found :: proc(t: ^testing.T) {
|
|
data := Outer {
|
|
title = "hi",
|
|
}
|
|
ctx := make([dynamic]any, 0, 1, context.temp_allocator)
|
|
append(&ctx, data)
|
|
|
|
ok, missing, _ := validate_key_path(ctx[:], "title")
|
|
testing.expect_value(t, ok, true)
|
|
testing.expect(t, missing == "", fmt.tprintf("expected empty missing, got %q", missing))
|
|
}
|
|
|
|
@(test)
|
|
test_validate_simple_missing :: proc(t: ^testing.T) {
|
|
data := Outer {
|
|
title = "hi",
|
|
}
|
|
ctx := make([dynamic]any, 0, 1, context.temp_allocator)
|
|
append(&ctx, data)
|
|
|
|
ok, missing, available := validate_key_path(ctx[:], "page_titel")
|
|
testing.expect_value(t, ok, false)
|
|
testing.expect_value(t, missing, "page_titel")
|
|
testing.expect(t, len(available) > 0, "should have suggestions")
|
|
}
|
|
|
|
@(test)
|
|
test_validate_dotted_found :: proc(t: ^testing.T) {
|
|
data := Outer {
|
|
inner = Inner{foo = "x"},
|
|
}
|
|
ctx := make([dynamic]any, 0, 1, context.temp_allocator)
|
|
append(&ctx, data)
|
|
|
|
ok, missing, _ := validate_key_path(ctx[:], "inner.foo")
|
|
testing.expect_value(t, ok, true)
|
|
testing.expect_value(t, missing, "")
|
|
}
|
|
|
|
@(test)
|
|
test_validate_dotted_missing :: proc(t: ^testing.T) {
|
|
data := Outer {
|
|
inner = Inner{foo = "x"},
|
|
}
|
|
ctx := make([dynamic]any, 0, 1, context.temp_allocator)
|
|
append(&ctx, data)
|
|
|
|
ok, missing, available := validate_key_path(ctx[:], "inner.fooo")
|
|
testing.expect_value(t, ok, false)
|
|
testing.expect_value(t, missing, "fooo")
|
|
testing.expect(t, len(available) > 0, "should have inner field suggestions")
|
|
}
|
|
|
|
Params_Data :: struct {
|
|
params: map[string]string,
|
|
}
|
|
|
|
Maybe_Bool_Data :: struct {
|
|
flag: Maybe(bool),
|
|
name: string,
|
|
}
|
|
|
|
Inner_For_Using :: struct {
|
|
flag: Maybe(bool),
|
|
label: string,
|
|
}
|
|
|
|
Outer_With_Using :: struct {
|
|
using inner: Inner_For_Using,
|
|
other: int,
|
|
}
|
|
|
|
@(test)
|
|
test_validate_path_through_using_to_maybe_bool :: proc(t: ^testing.T) {
|
|
data := Outer_With_Using {
|
|
inner = Inner_For_Using{label = "hi"},
|
|
other = 42,
|
|
}
|
|
ctx := make([dynamic]any, 0, 1, context.temp_allocator)
|
|
append(&ctx, data)
|
|
|
|
// `flag` is promoted via using; field exists even when Maybe is nil.
|
|
ok, missing, _ := validate_key_path(ctx[:], "flag")
|
|
testing.expect_value(t, ok, true)
|
|
testing.expect_value(t, missing, "")
|
|
|
|
// `label` is also promoted via using.
|
|
ok2, missing2, _ := validate_key_path(ctx[:], "label")
|
|
testing.expect_value(t, ok2, true)
|
|
testing.expect_value(t, missing2, "")
|
|
}
|
|
|
|
@(test)
|
|
test_struct_has_field_with_maybe_bool :: proc(t: ^testing.T) {
|
|
data := Maybe_Bool_Data {
|
|
name = "hi",
|
|
} // flag is nil Maybe
|
|
testing.expect_value(t, struct_has_field(data, "flag"), true)
|
|
testing.expect_value(t, struct_has_field(data, "name"), true)
|
|
testing.expect_value(t, struct_has_field(data, "missing"), false)
|
|
}
|
|
|
|
@(test)
|
|
test_validate_path_through_maybe_bool :: proc(t: ^testing.T) {
|
|
data := Maybe_Bool_Data {
|
|
name = "hi",
|
|
}
|
|
ctx := make([dynamic]any, 0, 1, context.temp_allocator)
|
|
append(&ctx, data)
|
|
|
|
// `flag` exists as a field even when its Maybe value is nil — should NOT warn.
|
|
ok, missing, _ := validate_key_path(ctx[:], "flag")
|
|
testing.expect_value(t, ok, true)
|
|
testing.expect_value(t, missing, "")
|
|
}
|
|
|
|
@(test)
|
|
test_validate_map_path_silent :: proc(t: ^testing.T) {
|
|
data := Params_Data {
|
|
params = {"social" = "x"},
|
|
}
|
|
defer delete(data.params)
|
|
ctx := make([dynamic]any, 0, 1, context.temp_allocator)
|
|
append(&ctx, data)
|
|
|
|
// `params` exists and is a map — subsequent segments are user-defined.
|
|
ok, _, _ := validate_key_path(ctx[:], "params.anything_here")
|
|
testing.expect_value(t, ok, true)
|
|
}
|
|
|
|
@(test)
|
|
test_suggest_correction_exact :: proc(t: ^testing.T) {
|
|
available := []string{"title", "page.title", "body"}
|
|
testing.expect_value(t, suggest_correction(available, "page_titel"), "page.title")
|
|
}
|
|
|
|
@(test)
|
|
test_suggest_correction_close :: proc(t: ^testing.T) {
|
|
available := []string{"title", "body", "now"}
|
|
testing.expect_value(t, suggest_correction(available, "titel"), "title")
|
|
}
|
|
|
|
@(test)
|
|
test_suggest_correction_no_match :: proc(t: ^testing.T) {
|
|
available := []string{"completely_different", "unrelated"}
|
|
testing.expect_value(t, suggest_correction(available, "page_titel"), "")
|
|
}
|
|
|
|
@(test)
|
|
test_suggest_correction_empty :: proc(t: ^testing.T) {
|
|
testing.expect_value(t, suggest_correction([]string{}, "anything"), "")
|
|
testing.expect_value(t, suggest_correction([]string{"a"}, ""), "")
|
|
}
|
|
|
|
@(test)
|
|
test_warn_no_false_positive_for_valid_keys :: proc(t: ^testing.T) {
|
|
Data :: struct {
|
|
name: string,
|
|
}
|
|
src := "Hello {{name}}"
|
|
tmpl, err := parse(src, "<test>", context.temp_allocator)
|
|
testing.expect(t, err == nil, "should parse")
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
// We can't easily capture log output in tests, but we can verify the
|
|
// validation procs agree the key exists.
|
|
ctx := make([dynamic]any, 0, 1, context.temp_allocator)
|
|
append(&ctx, Data{name = "World"})
|
|
|
|
ok, missing, _ := validate_key_path(ctx[:], "name")
|
|
testing.expect_value(t, ok, true)
|
|
}
|