test: hemar: +20 tests for parsing

This commit is contained in:
2025-05-15 18:54:56 +00:00
parent 653330dd48
commit 421cc6e870
2 changed files with 407 additions and 2 deletions

View File

@@ -0,0 +1,405 @@
-- Test file for hemar template parser
-- Run with: psql -f test_template_parser.sql
-- Load extension if not already loaded
-- CREATE EXTENSION IF NOT EXISTS hemar;
-- Create test function to validate template parsing
CREATE OR REPLACE FUNCTION test_template_parse(template_text text, expected_structure text) RETURNS boolean AS $$
DECLARE
parsed_result text;
passed boolean;
BEGIN
BEGIN
parsed_result := hemar.parse(template_text);
passed := position(expected_structure in parsed_result) > 0;
EXCEPTION
WHEN OTHERS THEN
passed := false;
END;
IF NOT passed THEN
RAISE WARNING 'Template parsing test failed!';
RAISE WARNING 'Template: %', template_text;
RAISE WARNING 'Expected to find: %', expected_structure;
RAISE WARNING 'Actual result: %', parsed_result;
END IF;
RETURN passed;
END;
$$ LANGUAGE plpgsql;
-- Run the tests
DO $$
DECLARE
total_tests integer := 0;
passed_tests integer := 0;
result boolean;
BEGIN
RAISE NOTICE 'Starting template parser tests...';
-- Test 1: Simple interpolation
total_tests := total_tests + 1;
result := test_template_parse(
'{{ simple_var }}',
'INTERPOLATE: "simple_var"'
);
IF result THEN
passed_tests := passed_tests + 1;
RAISE NOTICE 'Test %: Simple interpolation - PASSED', total_tests;
ELSE
RAISE WARNING 'Test %: Simple interpolation - FAILED', total_tests;
END IF;
-- Test 2: Interpolation with surrounding text
total_tests := total_tests + 1;
result := test_template_parse(
'Hello, {{ name }}!',
'TEXT: "Hello, "
INTERPOLATE: "name"
TEXT: "!"'
);
IF result THEN
passed_tests := passed_tests + 1;
RAISE NOTICE 'Test %: Interpolation with surrounding text - PASSED', total_tests;
ELSE
RAISE WARNING 'Test %: Interpolation with surrounding text - FAILED', total_tests;
END IF;
-- Test 3: Simple section (for loop)
total_tests := total_tests + 1;
result := test_template_parse(
'{{ for item in items do }}{{ item }}{{ end }}',
'SECTION: iterator="item", collection="items"'
);
IF result THEN
passed_tests := passed_tests + 1;
RAISE NOTICE 'Test %: Simple section (for loop) - PASSED', total_tests;
ELSE
RAISE WARNING 'Test %: Simple section (for loop) - FAILED', total_tests;
END IF;
-- Test 4: Section with nested interpolation
total_tests := total_tests + 1;
result := test_template_parse(
'{{ for item in items do }}Name: {{ item.name }}{{ end }}',
'SECTION: iterator="item", collection="items"
TEXT: "Name: "
INTERPOLATE: "item.name"'
);
IF result THEN
passed_tests := passed_tests + 1;
RAISE NOTICE 'Test %: Section with nested interpolation - PASSED', total_tests;
ELSE
RAISE WARNING 'Test %: Section with nested interpolation - FAILED', total_tests;
END IF;
-- Test 5: Nested sections
total_tests := total_tests + 1;
result := test_template_parse(
'{{ for item in items do }}{{ for subitem in item.subitems do }}{{ subitem }}{{ end }}{{ end }}',
'SECTION: iterator="item", collection="items"
SECTION: iterator="subitem", collection="item.subitems"
INTERPOLATE: "subitem"'
);
IF result THEN
passed_tests := passed_tests + 1;
RAISE NOTICE 'Test %: Nested sections - PASSED', total_tests;
ELSE
RAISE WARNING 'Test %: Nested sections - FAILED', total_tests;
END IF;
-- Test 6: Include tag
total_tests := total_tests + 1;
result := test_template_parse(
'{{ include template_name }}',
'INCLUDE: "template_name"'
);
IF result THEN
passed_tests := passed_tests + 1;
RAISE NOTICE 'Test %: Include tag - PASSED', total_tests;
ELSE
RAISE WARNING 'Test %: Include tag - FAILED', total_tests;
END IF;
-- Test 7: Execute tag
total_tests := total_tests + 1;
result := test_template_parse(
'{{ exec RETURN my_function(arg1, arg2) }}',
'EXECUTE: "RETURN my_function(arg1, arg2)"'
);
IF result THEN
passed_tests := passed_tests + 1;
RAISE NOTICE 'Test %: Execute tag - PASSED', total_tests;
ELSE
RAISE WARNING 'Test %: Execute tag - FAILED', total_tests;
END IF;
-- Test 8: Complex mixed template
total_tests := total_tests + 1;
result := test_template_parse(
'<div>{{ for item in items do }}<p>{{ item.name }}</p>{{ include item.template }}{{ end }}</div>',
'TEXT: "<div>"
SECTION: iterator="item", collection="items"
TEXT: "<p>"
INTERPOLATE: "item.name"
TEXT: "</p>"
INCLUDE: "item.template"
TEXT: "</div>"'
);
IF result THEN
passed_tests := passed_tests + 1;
RAISE NOTICE 'Test %: Complex mixed template - PASSED', total_tests;
ELSE
RAISE WARNING 'Test %: Complex mixed template - FAILED', total_tests;
END IF;
-- Test 9: Execute tag with complex SQL
total_tests := total_tests + 1;
result := test_template_parse(
'{{ exec
IF condition THEN
RETURN ''value1'';
ELSE
RETURN ''value2'';
END IF;
}}',
'EXECUTE: "IF condition THEN'
);
IF result THEN
passed_tests := passed_tests + 1;
RAISE NOTICE 'Test %: Execute tag with complex SQL - PASSED', total_tests;
ELSE
RAISE WARNING 'Test %: Execute tag with complex SQL - FAILED', total_tests;
END IF;
-- Test 10: Whitespace handling
total_tests := total_tests + 1;
result := test_template_parse(
'{{ spaced_var }}',
'INTERPOLATE: "spaced_var"'
);
IF result THEN
passed_tests := passed_tests + 1;
RAISE NOTICE 'Test %: Whitespace handling - PASSED', total_tests;
ELSE
RAISE WARNING 'Test %: Whitespace handling - FAILED', total_tests;
END IF;
-- Test 11: Multiple consecutive tags
total_tests := total_tests + 1;
result := test_template_parse(
'{{ var1 }}{{ var2 }}{{ var3 }}',
'INTERPOLATE: "var1"
INTERPOLATE: "var2"
INTERPOLATE: "var3"'
);
IF result THEN
passed_tests := passed_tests + 1;
RAISE NOTICE 'Test %: Multiple consecutive tags - PASSED', total_tests;
ELSE
RAISE WARNING 'Test %: Multiple consecutive tags - FAILED', total_tests;
END IF;
-- Test 12: Section with multiple nested elements
total_tests := total_tests + 1;
result := test_template_parse(
'{{ for item in items do }}
<h2>{{ item.title }}</h2>
<p>{{ item.description }}</p>
{{ include item.footer }}
{{ end }}',
'SECTION: iterator="item", collection="items"
TEXT: "
<h2>"
INTERPOLATE: "item.title"
TEXT: "</h2>
<p>"
INTERPOLATE: "item.description"
TEXT: "</p>
"
INCLUDE: "item.footer"
TEXT: "
"'
);
IF result THEN
passed_tests := passed_tests + 1;
RAISE NOTICE 'Test %: Section with multiple nested elements - PASSED', total_tests;
ELSE
RAISE WARNING 'Test %: Section with multiple nested elements - FAILED', total_tests;
END IF;
-- Test 13: Empty template
total_tests := total_tests + 1;
result := test_template_parse(
'',
'TEXT: ""'
);
IF result THEN
passed_tests := passed_tests + 1;
RAISE NOTICE 'Test %: Empty template - PASSED', total_tests;
ELSE
RAISE WARNING 'Test %: Empty template - FAILED', total_tests;
END IF;
-- Test 14: Just text, no tags
total_tests := total_tests + 1;
result := test_template_parse(
'Just plain text, no tags here.',
'TEXT: "Just plain text, no tags here."'
);
IF result THEN
passed_tests := passed_tests + 1;
RAISE NOTICE 'Test %: Just text, no tags - PASSED', total_tests;
ELSE
RAISE WARNING 'Test %: Just text, no tags - FAILED', total_tests;
END IF;
-- Test 15: Complex example from documentation
total_tests := total_tests + 1;
result := test_template_parse(
'<div>text before<div>
{{ include inner_template }}
{{ name }}
{{ for item in array do }}
some text: {{ name2 }}
{{ item.name }}
{{ end }}
<div>code insertion:</div>
{{ exec
context + ''{"name3": "zalupa"}'';
IF context->condition THEN
RAISE INFO ''some log'';
RETURN ''some text'';
END
RETURN ''some other text'';
}}
<div id="footer">...</div>',
'TEXT: "<div>text before<div>
"
INCLUDE: "inner_template"
TEXT: "
"
INTERPOLATE: "name"
TEXT: "
"
SECTION: iterator="item", collection="array"'
);
IF result THEN
passed_tests := passed_tests + 1;
RAISE NOTICE 'Test %: Complex example from documentation - PASSED', total_tests;
ELSE
RAISE WARNING 'Test %: Complex example from documentation - FAILED', total_tests;
END IF;
-- Test 16: Multiple nested sections
total_tests := total_tests + 1;
result := test_template_parse(
'{{ for a in items do }}
{{ for b in a.items do }}
{{ for c in b.items do }}
{{ c.name }}
{{ end }}
{{ end }}
{{ end }}',
'SECTION: iterator="a", collection="items"
TEXT: "
"
SECTION: iterator="b", collection="a.items"
TEXT: "
"
SECTION: iterator="c", collection="b.items"
TEXT: "
"
INTERPOLATE: "c.name"
TEXT: "
"'
);
IF result THEN
passed_tests := passed_tests + 1;
RAISE NOTICE 'Test %: Multiple nested sections - PASSED', total_tests;
ELSE
RAISE WARNING 'Test %: Multiple nested sections - FAILED', total_tests;
END IF;
-- Test 17: Interpolation with special characters
total_tests := total_tests + 1;
result := test_template_parse(
'{{ special@field }}',
'INTERPOLATE: "special@field"'
);
IF result THEN
passed_tests := passed_tests + 1;
RAISE NOTICE 'Test %: Interpolation with special characters - PASSED', total_tests;
ELSE
RAISE WARNING 'Test %: Interpolation with special characters - FAILED', total_tests;
END IF;
-- Test 18: Section with complex iterator and collection names
total_tests := total_tests + 1;
result := test_template_parse(
'{{ for complex_item.with.dots in complex_collection[0].items do }}{{ end }}',
'SECTION: iterator="complex_item.with.dots", collection="complex_collection[0].items"'
);
IF result THEN
passed_tests := passed_tests + 1;
RAISE NOTICE 'Test %: Section with complex iterator and collection names - PASSED', total_tests;
ELSE
RAISE WARNING 'Test %: Section with complex iterator and collection names - FAILED', total_tests;
END IF;
-- Test 19: Include with complex path
total_tests := total_tests + 1;
result := test_template_parse(
'{{ include templates[0].nested.path }}',
'INCLUDE: "templates[0].nested.path"'
);
IF result THEN
passed_tests := passed_tests + 1;
RAISE NOTICE 'Test %: Include with complex path - PASSED', total_tests;
ELSE
RAISE WARNING 'Test %: Include with complex path - FAILED', total_tests;
END IF;
-- Test 20: Execute with complex SQL and quotes
total_tests := total_tests + 1;
result := test_template_parse(
'{{ exec SELECT ''text with "double" quotes'' AS result; }}',
'EXECUTE: "SELECT ''text with "double" quotes'' AS result;"'
);
IF result THEN
passed_tests := passed_tests + 1;
RAISE NOTICE 'Test %: Execute with complex SQL and quotes - PASSED', total_tests;
ELSE
RAISE WARNING 'Test %: Execute with complex SQL and quotes - FAILED', total_tests;
END IF;
-- Print summary
IF passed_tests = total_tests THEN
RAISE NOTICE '------------------------------------';
RAISE NOTICE 'SUMMARY: % of % tests passed (100%%)',
passed_tests, total_tests;
RAISE NOTICE '------------------------------------';
ELSE
RAISE WARNING '------------------------------------';
RAISE WARNING 'SUMMARY: % of % tests passed (%)',
passed_tests,
total_tests,
round((passed_tests::numeric / total_tests::numeric) * 100, 2) || '%';
RAISE WARNING '------------------------------------';
END IF;
IF passed_tests != total_tests THEN
RAISE EXCEPTION 'Tests failed: % of % tests did not pass', (total_tests - passed_tests), total_tests;
END IF;
END $$;