refactor: hemar reboot
This commit is contained in:
38
package/c/hemar-legacy/test/mod.sql
Executable file
38
package/c/hemar-legacy/test/mod.sql
Executable file
@@ -0,0 +1,38 @@
|
||||
BEGIN;
|
||||
CREATE OR REPLACE FUNCTION pg_temp.diff(string1 text, string2 text) RETURNS TABLE("index" int, char1 text, char2 text) AS $$
|
||||
BEGIN
|
||||
RETURN QUERY WITH
|
||||
s1 AS (SELECT string1 AS str),
|
||||
s2 AS (SELECT string2 AS str)
|
||||
SELECT i,
|
||||
substring(s1.str FROM i FOR 1) AS char1,
|
||||
substring(s2.str FROM i FOR 1) AS char2
|
||||
FROM s1, s2,
|
||||
generate_series(1, GREATEST(length(s1.str), length(s2.str))) AS i
|
||||
WHERE substring(s1.str FROM i FOR 1) IS DISTINCT FROM substring(s2.str FROM i FOR 1);
|
||||
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
CREATE OR REPLACE FUNCTION pg_temp.test_regexp_replace(string text) RETURNS text AS $$
|
||||
BEGIN
|
||||
RETURN regexp_replace(
|
||||
regexp_replace(
|
||||
regexp_replace(
|
||||
regexp_replace(
|
||||
regexp_replace(string, E'\t', '\\t', 'g'),
|
||||
E'\n', '\\n', 'g'),
|
||||
E'\r', '\\r', 'g'),
|
||||
' ', '[S]', 'g'),
|
||||
'\s', '\\s', 'g');
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
\ir test_jsonb_path.sql
|
||||
--\ir test_template_parser.sql
|
||||
\ir test_render_exec.sql
|
||||
\ir test_render_interpolate.sql
|
||||
\ir test_render_section.sql
|
||||
\ir test_render_include.sql
|
||||
--\ir test_render_all.sql
|
||||
ROLLBACK;
|
||||
516
package/c/hemar-legacy/test/test_jsonb_path.sql
Executable file
516
package/c/hemar-legacy/test/test_jsonb_path.sql
Executable file
@@ -0,0 +1,516 @@
|
||||
-- Test file for hemar.jsonb_get_by_path function
|
||||
-- Run with: psql -f test_jsonb_path.sql
|
||||
|
||||
-- Load extension if not already loaded
|
||||
-- CREATE EXTENSION IF NOT EXISTS hemar;
|
||||
|
||||
-- Create sample test data
|
||||
DO $$
|
||||
DECLARE
|
||||
test_json jsonb;
|
||||
result jsonb;
|
||||
passed boolean;
|
||||
total_tests integer := 0;
|
||||
passed_tests integer := 0;
|
||||
current_path text;
|
||||
BEGIN
|
||||
test_json := jsonb_build_object(
|
||||
'name', 'John Doe',
|
||||
'age', 30,
|
||||
'is_active', true,
|
||||
'tags', jsonb_build_array('developer', 'postgresql', 'jsonb'),
|
||||
'address', jsonb_build_object(
|
||||
'street', '123 Main St',
|
||||
'city', 'New York',
|
||||
'zip', '10001'
|
||||
),
|
||||
'contacts', jsonb_build_array(
|
||||
jsonb_build_object(
|
||||
'type', 'email',
|
||||
'value', 'john@example.com'
|
||||
),
|
||||
jsonb_build_object(
|
||||
'type', 'phone',
|
||||
'value', '555-1234',
|
||||
'verified', true
|
||||
)
|
||||
),
|
||||
'skills', jsonb_build_array(
|
||||
jsonb_build_array('PostgreSQL', 5),
|
||||
jsonb_build_array('Python', 4),
|
||||
jsonb_build_array('JavaScript', 3)
|
||||
)
|
||||
);
|
||||
|
||||
-- Test basic field access
|
||||
total_tests := total_tests + 1;
|
||||
current_path := 'name';
|
||||
result := hemar.jsonb_get_by_path(test_json, current_path);
|
||||
passed := result = '"John Doe"'::jsonb;
|
||||
passed_tests := passed_tests + (CASE WHEN passed THEN 1 ELSE 0 END);
|
||||
IF passed THEN
|
||||
RAISE NOTICE 'Test %: Simple field access (path="%"): % | PASSED: %',
|
||||
total_tests, current_path, result, passed;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Simple field access (path="%"): % | PASSED: % (expected: "John Doe")',
|
||||
total_tests, current_path, result, passed;
|
||||
END IF;
|
||||
|
||||
total_tests := total_tests + 1;
|
||||
current_path := 'age';
|
||||
result := hemar.jsonb_get_by_path(test_json, current_path);
|
||||
passed := result = '30'::jsonb;
|
||||
passed_tests := passed_tests + (CASE WHEN passed THEN 1 ELSE 0 END);
|
||||
IF passed THEN
|
||||
RAISE NOTICE 'Test %: Numeric field access (path="%"): % | PASSED: %',
|
||||
total_tests, current_path, result, passed;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Numeric field access (path="%"): % | PASSED: % (expected: 30)',
|
||||
total_tests, current_path, result, passed;
|
||||
END IF;
|
||||
|
||||
total_tests := total_tests + 1;
|
||||
current_path := 'is_active';
|
||||
result := hemar.jsonb_get_by_path(test_json, current_path);
|
||||
passed := result = 'true'::jsonb;
|
||||
passed_tests := passed_tests + (CASE WHEN passed THEN 1 ELSE 0 END);
|
||||
IF passed THEN
|
||||
RAISE NOTICE 'Test %: Boolean field access (path="%"): % | PASSED: %',
|
||||
total_tests, current_path, result, passed;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Boolean field access (path="%"): % | PASSED: % (expected: true)',
|
||||
total_tests, current_path, result, passed;
|
||||
END IF;
|
||||
|
||||
-- Test nested field access
|
||||
total_tests := total_tests + 1;
|
||||
current_path := 'address.city';
|
||||
result := hemar.jsonb_get_by_path(test_json, current_path);
|
||||
passed := result = '"New York"'::jsonb;
|
||||
passed_tests := passed_tests + (CASE WHEN passed THEN 1 ELSE 0 END);
|
||||
IF passed THEN
|
||||
RAISE NOTICE 'Test %: Nested object field access (path="%"): % | PASSED: %',
|
||||
total_tests, current_path, result, passed;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Nested object field access (path="%"): % | PASSED: % (expected: "New York")',
|
||||
total_tests, current_path, result, passed;
|
||||
END IF;
|
||||
|
||||
-- Test array access
|
||||
total_tests := total_tests + 1;
|
||||
current_path := 'tags[1]';
|
||||
result := hemar.jsonb_get_by_path(test_json, current_path);
|
||||
passed := result = '"postgresql"'::jsonb;
|
||||
passed_tests := passed_tests + (CASE WHEN passed THEN 1 ELSE 0 END);
|
||||
IF passed THEN
|
||||
RAISE NOTICE 'Test %: Simple array access (path="%"): % | PASSED: %',
|
||||
total_tests, current_path, result, passed;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Simple array access (path="%"): % | PASSED: % (expected: "postgresql")',
|
||||
total_tests, current_path, result, passed;
|
||||
END IF;
|
||||
|
||||
total_tests := total_tests + 1;
|
||||
current_path := 'contacts[0].type';
|
||||
result := hemar.jsonb_get_by_path(test_json, current_path);
|
||||
passed := result = '"email"'::jsonb;
|
||||
passed_tests := passed_tests + (CASE WHEN passed THEN 1 ELSE 0 END);
|
||||
IF passed THEN
|
||||
RAISE NOTICE 'Test %: Object in array access (path="%"): % | PASSED: %',
|
||||
total_tests, current_path, result, passed;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Object in array access (path="%"): % | PASSED: % (expected: "email")',
|
||||
total_tests, current_path, result, passed;
|
||||
END IF;
|
||||
|
||||
total_tests := total_tests + 1;
|
||||
current_path := 'skills[1][0]';
|
||||
result := hemar.jsonb_get_by_path(test_json, current_path);
|
||||
passed := result = '"Python"'::jsonb;
|
||||
passed_tests := passed_tests + (CASE WHEN passed THEN 1 ELSE 0 END);
|
||||
IF passed THEN
|
||||
RAISE NOTICE 'Test %: Nested array access (path="%"): % | PASSED: %',
|
||||
total_tests, current_path, result, passed;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Nested array access (path="%"): % | PASSED: % (expected: "Python")',
|
||||
total_tests, current_path, result, passed;
|
||||
END IF;
|
||||
|
||||
total_tests := total_tests + 1;
|
||||
current_path := 'contacts[1].value';
|
||||
result := hemar.jsonb_get_by_path(test_json, current_path);
|
||||
passed := result = '"555-1234"'::jsonb;
|
||||
passed_tests := passed_tests + (CASE WHEN passed THEN 1 ELSE 0 END);
|
||||
IF passed THEN
|
||||
RAISE NOTICE 'Test %: Complex path with multiple array indices (path="%"): % | PASSED: %',
|
||||
total_tests, current_path, result, passed;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Complex path with multiple array indices (path="%"): % | PASSED: % (expected: "555-1234")',
|
||||
total_tests, current_path, result, passed;
|
||||
END IF;
|
||||
|
||||
-- Test object and array returns
|
||||
total_tests := total_tests + 1;
|
||||
current_path := 'address';
|
||||
result := hemar.jsonb_get_by_path(test_json, current_path);
|
||||
passed := jsonb_typeof(result) = 'object';
|
||||
passed_tests := passed_tests + (CASE WHEN passed THEN 1 ELSE 0 END);
|
||||
IF passed THEN
|
||||
RAISE NOTICE 'Test %: Path to object (path="%"): % | PASSED: %',
|
||||
total_tests, current_path, result, passed;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Path to object (path="%"): % | PASSED: % (expected type: object, got: %)',
|
||||
total_tests, current_path, result, passed, jsonb_typeof(result);
|
||||
END IF;
|
||||
|
||||
total_tests := total_tests + 1;
|
||||
current_path := 'contacts';
|
||||
result := hemar.jsonb_get_by_path(test_json, current_path);
|
||||
passed := jsonb_typeof(result) = 'array';
|
||||
passed_tests := passed_tests + (CASE WHEN passed THEN 1 ELSE 0 END);
|
||||
IF passed THEN
|
||||
RAISE NOTICE 'Test %: Path to array (path="%"): % | PASSED: %',
|
||||
total_tests, current_path, result, passed;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Path to array (path="%"): % | PASSED: % (expected type: array, got: %)',
|
||||
total_tests, current_path, result, passed, jsonb_typeof(result);
|
||||
END IF;
|
||||
|
||||
-- Test error cases
|
||||
total_tests := total_tests + 1;
|
||||
current_path := 'unknown_field';
|
||||
result := hemar.jsonb_get_by_path(test_json, current_path);
|
||||
passed := result IS NULL;
|
||||
passed_tests := passed_tests + (CASE WHEN passed THEN 1 ELSE 0 END);
|
||||
IF passed THEN
|
||||
RAISE NOTICE 'Test %: Non-existent field (path="%"): % | PASSED: %',
|
||||
total_tests, current_path, result, passed;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Non-existent field (path="%"): % | PASSED: % (expected: NULL)',
|
||||
total_tests, current_path, result, passed;
|
||||
END IF;
|
||||
|
||||
total_tests := total_tests + 1;
|
||||
current_path := 'address.country';
|
||||
result := hemar.jsonb_get_by_path(test_json, current_path);
|
||||
passed := result IS NULL;
|
||||
passed_tests := passed_tests + (CASE WHEN passed THEN 1 ELSE 0 END);
|
||||
|
||||
IF passed THEN
|
||||
RAISE NOTICE 'Test %: Non-existent nested field (path="%"): % | PASSED: %',
|
||||
total_tests, current_path, result, passed;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Non-existent nested field (path="%"): % | PASSED: % (expected: NULL)',
|
||||
total_tests, current_path, result, passed;
|
||||
END IF;
|
||||
|
||||
total_tests := total_tests + 1;
|
||||
current_path := 'tags[10]';
|
||||
result := hemar.jsonb_get_by_path(test_json, current_path);
|
||||
passed := result IS NULL;
|
||||
passed_tests := passed_tests + (CASE WHEN passed THEN 1 ELSE 0 END);
|
||||
IF passed THEN
|
||||
RAISE NOTICE 'Test %: Array index out of bounds (path="%"): % | PASSED: %',
|
||||
total_tests, current_path, result, passed;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Array index out of bounds (path="%"): % | PASSED: % (expected: NULL)',
|
||||
total_tests, current_path, result, passed;
|
||||
END IF;
|
||||
|
||||
-- Test edge cases
|
||||
total_tests := total_tests + 1;
|
||||
current_path := '';
|
||||
result := hemar.jsonb_get_by_path(test_json, current_path);
|
||||
passed := result IS NULL;
|
||||
passed_tests := passed_tests + (CASE WHEN passed THEN 1 ELSE 0 END);
|
||||
IF passed THEN
|
||||
RAISE NOTICE 'Test %: Empty path (path="%"): % | PASSED: %',
|
||||
total_tests, current_path, result, passed;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Empty path (path="%"): % | PASSED: % (expected: NULL)',
|
||||
total_tests, current_path, result, passed;
|
||||
END IF;
|
||||
|
||||
total_tests := total_tests + 1;
|
||||
current_path := 'skills[0][1]';
|
||||
result := hemar.jsonb_get_by_path(test_json, current_path);
|
||||
passed := result = '5'::jsonb;
|
||||
passed_tests := passed_tests + (CASE WHEN passed THEN 1 ELSE 0 END);
|
||||
IF passed THEN
|
||||
RAISE NOTICE 'Test %: Multiple array indices (path="%"): % | PASSED: %',
|
||||
total_tests, current_path, result, passed;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Multiple array indices (path="%"): % | PASSED: % (expected: 5)',
|
||||
total_tests, current_path, result, passed;
|
||||
END IF;
|
||||
|
||||
-- Additional complex test cases
|
||||
|
||||
-- Test 16: Deep nested object access
|
||||
total_tests := total_tests + 1;
|
||||
test_json := jsonb_build_object(
|
||||
'level1', jsonb_build_object(
|
||||
'level2', jsonb_build_object(
|
||||
'level3', jsonb_build_object(
|
||||
'level4', jsonb_build_object(
|
||||
'value', 'deep nested value'
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
current_path := 'level1.level2.level3.level4.value';
|
||||
result := hemar.jsonb_get_by_path(test_json, current_path);
|
||||
passed := result = '"deep nested value"'::jsonb;
|
||||
passed_tests := passed_tests + (CASE WHEN passed THEN 1 ELSE 0 END);
|
||||
IF passed THEN
|
||||
RAISE NOTICE 'Test %: Deep nested object access (path="%"): % | PASSED: %',
|
||||
total_tests, current_path, result, passed;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Deep nested object access (path="%"): % | PASSED: % (expected: "deep nested value")',
|
||||
total_tests, current_path, result, passed;
|
||||
END IF;
|
||||
|
||||
-- Test 17: Deep nested array access
|
||||
total_tests := total_tests + 1;
|
||||
test_json := jsonb_build_array(
|
||||
jsonb_build_array(
|
||||
jsonb_build_array(
|
||||
jsonb_build_array(
|
||||
'nested array value'
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
current_path := '[0][0][0][0]';
|
||||
result := hemar.jsonb_get_by_path(test_json, current_path);
|
||||
passed := result = '"nested array value"'::jsonb;
|
||||
passed_tests := passed_tests + (CASE WHEN passed THEN 1 ELSE 0 END);
|
||||
IF passed THEN
|
||||
RAISE NOTICE 'Test %: Deep nested array access (path="%"): % | PASSED: %',
|
||||
total_tests, current_path, result, passed;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Deep nested array access (path="%"): % | PASSED: % (expected: "nested array value")',
|
||||
total_tests, current_path, result, passed;
|
||||
END IF;
|
||||
|
||||
-- Test 18: Complex mixed nesting (object -> array -> object -> array)
|
||||
total_tests := total_tests + 1;
|
||||
test_json := jsonb_build_object(
|
||||
'users', jsonb_build_array(
|
||||
jsonb_build_object(
|
||||
'name', 'Alice',
|
||||
'permissions', jsonb_build_array('read', 'write', 'admin')
|
||||
),
|
||||
jsonb_build_object(
|
||||
'name', 'Bob',
|
||||
'permissions', jsonb_build_array('read', 'write')
|
||||
)
|
||||
)
|
||||
);
|
||||
current_path := 'users[1].permissions[0]';
|
||||
result := hemar.jsonb_get_by_path(test_json, current_path);
|
||||
passed := result = '"read"'::jsonb;
|
||||
passed_tests := passed_tests + (CASE WHEN passed THEN 1 ELSE 0 END);
|
||||
IF passed THEN
|
||||
RAISE NOTICE 'Test %: Complex mixed nesting (path="%"): % | PASSED: %',
|
||||
total_tests, current_path, result, passed;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Complex mixed nesting (path="%"): % | PASSED: % (expected: "read")',
|
||||
total_tests, current_path, result, passed;
|
||||
END IF;
|
||||
|
||||
-- Test 19: Array with mixed types
|
||||
total_tests := total_tests + 1;
|
||||
test_json := jsonb_build_array(
|
||||
'string',
|
||||
42,
|
||||
true,
|
||||
jsonb_build_object('key', 'value'),
|
||||
jsonb_build_array(1, 2, 3)
|
||||
);
|
||||
current_path := '[3].key';
|
||||
result := hemar.jsonb_get_by_path(test_json, current_path);
|
||||
passed := result = '"value"'::jsonb;
|
||||
passed_tests := passed_tests + (CASE WHEN passed THEN 1 ELSE 0 END);
|
||||
IF passed THEN
|
||||
RAISE NOTICE 'Test %: Array with mixed types (path="%"): % | PASSED: %',
|
||||
total_tests, current_path, result, passed;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Array with mixed types (path="%"): % | PASSED: % (expected: "value")',
|
||||
total_tests, current_path, result, passed;
|
||||
END IF;
|
||||
|
||||
-- Test 20: Path with array at the end
|
||||
total_tests := total_tests + 1;
|
||||
test_json := jsonb_build_object(
|
||||
'data', jsonb_build_object(
|
||||
'items', jsonb_build_array(10, 20, 30, 40)
|
||||
)
|
||||
);
|
||||
current_path := 'data.items[2]';
|
||||
result := hemar.jsonb_get_by_path(test_json, current_path);
|
||||
passed := result = '30'::jsonb;
|
||||
passed_tests := passed_tests + (CASE WHEN passed THEN 1 ELSE 0 END);
|
||||
IF passed THEN
|
||||
RAISE NOTICE 'Test %: Path with array at the end (path="%"): % | PASSED: %',
|
||||
total_tests, current_path, result, passed;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Path with array at the end (path="%"): % | PASSED: % (expected: 30)',
|
||||
total_tests, current_path, result, passed;
|
||||
END IF;
|
||||
|
||||
-- Test 21: Numeric field names
|
||||
total_tests := total_tests + 1;
|
||||
test_json := jsonb_build_object(
|
||||
'123', 'numeric key',
|
||||
'456', jsonb_build_object(
|
||||
'789', 'nested numeric key'
|
||||
)
|
||||
);
|
||||
current_path := '456.789';
|
||||
result := hemar.jsonb_get_by_path(test_json, current_path);
|
||||
passed := result = '"nested numeric key"'::jsonb;
|
||||
passed_tests := passed_tests + (CASE WHEN passed THEN 1 ELSE 0 END);
|
||||
IF passed THEN
|
||||
RAISE NOTICE 'Test %: Numeric field names (path="%"): % | PASSED: %',
|
||||
total_tests, current_path, result, passed;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Numeric field names (path="%"): % | PASSED: % (expected: "nested numeric key")',
|
||||
total_tests, current_path, result, passed;
|
||||
END IF;
|
||||
|
||||
-- Test 22: Special characters in field names
|
||||
total_tests := total_tests + 1;
|
||||
test_json := jsonb_build_object(
|
||||
'special@field', 'special value',
|
||||
'nested', jsonb_build_object(
|
||||
'field-with-hyphens', 'hyphenated value'
|
||||
)
|
||||
);
|
||||
current_path := 'nested.field-with-hyphens';
|
||||
result := hemar.jsonb_get_by_path(test_json, current_path);
|
||||
passed := result = '"hyphenated value"'::jsonb;
|
||||
passed_tests := passed_tests + (CASE WHEN passed THEN 1 ELSE 0 END);
|
||||
IF passed THEN
|
||||
RAISE NOTICE 'Test %: Special characters in field names (path="%"): % | PASSED: %',
|
||||
total_tests, current_path, result, passed;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Special characters in field names (path="%"): % | PASSED: % (expected: "hyphenated value")',
|
||||
total_tests, current_path, result, passed;
|
||||
END IF;
|
||||
|
||||
-- Test 23: Array of arrays of arrays
|
||||
total_tests := total_tests + 1;
|
||||
test_json := jsonb_build_array(
|
||||
jsonb_build_array(
|
||||
jsonb_build_array(1, 2),
|
||||
jsonb_build_array(3, 4)
|
||||
),
|
||||
jsonb_build_array(
|
||||
jsonb_build_array(5, 6),
|
||||
jsonb_build_array(7, 8)
|
||||
)
|
||||
);
|
||||
current_path := '[1][0][1]';
|
||||
result := hemar.jsonb_get_by_path(test_json, current_path);
|
||||
passed := result = '6'::jsonb;
|
||||
passed_tests := passed_tests + (CASE WHEN passed THEN 1 ELSE 0 END);
|
||||
IF passed THEN
|
||||
RAISE NOTICE 'Test %: Array of arrays of arrays (path="%"): % | PASSED: %',
|
||||
total_tests, current_path, result, passed;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Array of arrays of arrays (path="%"): % | PASSED: % (expected: 6)',
|
||||
total_tests, current_path, result, passed;
|
||||
END IF;
|
||||
|
||||
-- Test 24: Complex path with multiple array indices and object fields
|
||||
total_tests := total_tests + 1;
|
||||
test_json := jsonb_build_object(
|
||||
'companies', jsonb_build_array(
|
||||
jsonb_build_object(
|
||||
'name', 'Company A',
|
||||
'departments', jsonb_build_array(
|
||||
jsonb_build_object(
|
||||
'name', 'Engineering',
|
||||
'teams', jsonb_build_array(
|
||||
jsonb_build_object(
|
||||
'name', 'Backend',
|
||||
'members', jsonb_build_array(
|
||||
jsonb_build_object('name', 'John', 'role', 'Developer'),
|
||||
jsonb_build_object('name', 'Jane', 'role', 'Lead')
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
current_path := 'companies[0].departments[0].teams[0].members[1].role';
|
||||
result := hemar.jsonb_get_by_path(test_json, current_path);
|
||||
passed := result = '"Lead"'::jsonb;
|
||||
passed_tests := passed_tests + (CASE WHEN passed THEN 1 ELSE 0 END);
|
||||
IF passed THEN
|
||||
RAISE NOTICE 'Test %: Very complex path (path="%"): % | PASSED: %',
|
||||
total_tests, current_path, result, passed;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Very complex path (path="%"): % | PASSED: % (expected: "Lead")',
|
||||
total_tests, current_path, result, passed;
|
||||
END IF;
|
||||
|
||||
-- Test 25: Empty array and object edge cases
|
||||
total_tests := total_tests + 1;
|
||||
test_json := jsonb_build_object(
|
||||
'emptyArray', jsonb_build_array(),
|
||||
'emptyObject', jsonb_build_object(),
|
||||
'arrayWithEmptyObject', jsonb_build_array(jsonb_build_object()),
|
||||
'objectWithEmptyArray', jsonb_build_object('empty', jsonb_build_array())
|
||||
);
|
||||
current_path := 'objectWithEmptyArray.empty';
|
||||
result := hemar.jsonb_get_by_path(test_json, current_path);
|
||||
passed := jsonb_typeof(result) = 'array' AND jsonb_array_length(result) = 0;
|
||||
passed_tests := passed_tests + (CASE WHEN passed THEN 1 ELSE 0 END);
|
||||
IF passed THEN
|
||||
RAISE NOTICE 'Test %: Empty array/object edge cases (path="%"): % | PASSED: %',
|
||||
total_tests, current_path, result, passed;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Empty array/object edge cases (path="%"): % | PASSED: % (expected: empty array)',
|
||||
total_tests, current_path, result, passed;
|
||||
END IF;
|
||||
|
||||
-- Test nested object path parsing
|
||||
total_tests := total_tests + 1;
|
||||
result := hemar.jsonb_get_by_path(
|
||||
'{"user": {"profile": {"name": "John", "age": 30}}}'::jsonb,
|
||||
'user.profile.name'
|
||||
);
|
||||
passed := result = '"John"'::jsonb;
|
||||
passed_tests := passed_tests + (CASE WHEN passed THEN 1 ELSE 0 END);
|
||||
IF passed THEN
|
||||
RAISE NOTICE 'Test %: Nested object path parsing (path="%"): % | PASSED: %',
|
||||
total_tests, current_path, result, passed;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Nested object path parsing (path="%"): % | PASSED: % (expected: "John")',
|
||||
total_tests, current_path, result, passed;
|
||||
END IF;
|
||||
|
||||
-- Print summary
|
||||
IF passed_tests = total_tests THEN
|
||||
RAISE NOTICE '------------------------------------';
|
||||
RAISE NOTICE 'SUMMARY: % of % jsonb_get_by_path tests passed (100%%)',
|
||||
passed_tests, total_tests;
|
||||
RAISE NOTICE '------------------------------------';
|
||||
ELSE
|
||||
RAISE WARNING '------------------------------------';
|
||||
RAISE WARNING 'SUMMARY: % of % jsonb_get_by_path 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 % jsonb_get_by_path tests did not pass', (total_tests - passed_tests), total_tests;
|
||||
END IF;
|
||||
END $$;
|
||||
261
package/c/hemar-legacy/test/test_render_all.sql
Executable file
261
package/c/hemar-legacy/test/test_render_all.sql
Executable file
@@ -0,0 +1,261 @@
|
||||
-- Test all template tags together
|
||||
CREATE OR REPLACE FUNCTION pg_temp.diff(string1 text, string2 text) RETURNS TABLE("index" int, char1 text, char2 text) AS $$
|
||||
BEGIN
|
||||
RETURN QUERY WITH
|
||||
s1 AS (SELECT string1 AS str),
|
||||
s2 AS (SELECT string2 AS str)
|
||||
SELECT i,
|
||||
substring(s1.str FROM i FOR 1) AS char1,
|
||||
substring(s2.str FROM i FOR 1) AS char2
|
||||
FROM s1, s2,
|
||||
generate_series(1, GREATEST(length(s1.str), length(s2.str))) AS i
|
||||
WHERE substring(s1.str FROM i FOR 1) IS DISTINCT FROM substring(s2.str FROM i FOR 1);
|
||||
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
CREATE OR REPLACE FUNCTION pg_temp.test_regexp_replace(string text) RETURNS text AS $$
|
||||
BEGIN
|
||||
RETURN regexp_replace(
|
||||
regexp_replace(
|
||||
regexp_replace(
|
||||
regexp_replace(
|
||||
regexp_replace(string, E'\t', '[TAB]', 'g'),
|
||||
E'\n', '[LF]', 'g'),
|
||||
E'\r', '[CR]', 'g'),
|
||||
' ', '[SPACE]', 'g'),
|
||||
'\s', '[WHITESPACE]', 'g');
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
DO $$
|
||||
DECLARE
|
||||
total_tests INT := 0;
|
||||
passed_tests INT := 0;
|
||||
test_result TEXT;
|
||||
expected TEXT;
|
||||
passed BOOLEAN;
|
||||
item INT;
|
||||
c1 TEXT;
|
||||
c2 TEXT;
|
||||
BEGIN
|
||||
-- Test 1: Template with execute tag using context from section
|
||||
total_tests := total_tests + 1;
|
||||
BEGIN
|
||||
test_result := hemar.render(
|
||||
'{
|
||||
"items": [
|
||||
{"id": 1, "value": 100},
|
||||
{"id": 2, "value": 200},
|
||||
{"id": 3, "value": 300}
|
||||
]
|
||||
}'::jsonb,
|
||||
$template$Items:
|
||||
{{ for item in items }}
|
||||
Item {{ item.id }}: {{ exec RETURN (context->'item'->>'value')::int * 2; }}
|
||||
{{ end }}$template$
|
||||
);
|
||||
|
||||
expected:='Items:
|
||||
Item 1: 200
|
||||
Item 2: 400
|
||||
Item 3: 600
|
||||
';
|
||||
|
||||
passed := test_result = expected;
|
||||
passed_tests := passed_tests + (CASE WHEN passed THEN 1 ELSE 0 END);
|
||||
IF passed THEN
|
||||
RAISE NOTICE 'Test %: Template with execute tag using context from section: PASSED', total_tests;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Template with execute tag using context from section: FAILED. Expected "%", got "%"',
|
||||
total_tests, pg_temp.test_regexp_replace(expected), pg_temp.test_regexp_replace(test_result);
|
||||
FOR item, c1, c2 IN
|
||||
SELECT * FROM pg_temp.diff(expected, test_result)
|
||||
LOOP
|
||||
RAISE NOTICE ' % | % | %', item, c1, c2;
|
||||
END LOOP;
|
||||
END IF;
|
||||
EXCEPTION WHEN OTHERS THEN
|
||||
RAISE WARNING 'Test % failed: Error: %', total_tests, SQLERRM;
|
||||
END;
|
||||
|
||||
-- Test 2: Complex template with all tag types
|
||||
total_tests := total_tests + 1;
|
||||
BEGIN
|
||||
test_result := hemar.render(
|
||||
'{
|
||||
"page": {
|
||||
"title": "My Page",
|
||||
"sections": [
|
||||
{
|
||||
"id": "section1",
|
||||
"title": "Section 1",
|
||||
"items": [
|
||||
{
|
||||
"id": "item1",
|
||||
"status": "active",
|
||||
"content": "Item 1 Content",
|
||||
"template": "item_template"
|
||||
},
|
||||
{
|
||||
"id": "item2",
|
||||
"status": "inactive",
|
||||
"content": "Item 2 Content",
|
||||
"template": "item_template"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"include": {
|
||||
"meta_tags": {
|
||||
"content": "<meta name=\"description\" content=\"Test Page\">"
|
||||
},
|
||||
"header": {
|
||||
"template": "Welcome to {{ page.title }}!",
|
||||
"context": {
|
||||
"page": {
|
||||
"title": "My Page"
|
||||
}
|
||||
}
|
||||
},
|
||||
"item_template": {
|
||||
"template": "Status: {{ status }}, Content: {{ content }}"
|
||||
},
|
||||
"footer": {
|
||||
"content": "<footer>Copyright 2024</footer>"
|
||||
}
|
||||
}
|
||||
}'::jsonb,
|
||||
$template$<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>{{ page.title }}</title>
|
||||
{{ include meta_tags }}
|
||||
</head>
|
||||
<body>
|
||||
<header>{{ include header }}</header>
|
||||
<main>
|
||||
{{ for section in page.sections }}
|
||||
<section id="{{ section.id }}">
|
||||
<h2>{{ section.title }}</h2>
|
||||
{{ for item in section.items }}
|
||||
<div class="item {{ item.status }}">
|
||||
{{ include item.template }}
|
||||
{{ exec
|
||||
DECLARE
|
||||
v_status TEXT;
|
||||
BEGIN
|
||||
v_status := context->'item'->>'status';
|
||||
RETURN CASE
|
||||
WHEN v_status = 'active' THEN ' (Active Item)'
|
||||
ELSE ' (Inactive Item)'
|
||||
END;
|
||||
END;
|
||||
}}
|
||||
</div>
|
||||
{{ end }}
|
||||
</section>
|
||||
{{ end }}
|
||||
</main>
|
||||
<footer>{{ include footer }}</footer>
|
||||
</body>
|
||||
</html>$template$
|
||||
);
|
||||
|
||||
expected := '<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>My Page</title>
|
||||
<meta name="description" content="Test Page">
|
||||
</head>
|
||||
<body>
|
||||
<header>Welcome to My Page!</header>
|
||||
<main>
|
||||
<section id="section1">
|
||||
<h2>Section 1</h2>
|
||||
<div class="item active">
|
||||
Status: active, Content: Item 1 Content (Active Item)
|
||||
</div>
|
||||
<div class="item inactive">
|
||||
Status: inactive, Content: Item 2 Content (Inactive Item)
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
<footer><footer>Copyright 2024</footer></footer>
|
||||
</body>
|
||||
</html>';
|
||||
|
||||
passed := test_result = expected;
|
||||
passed_tests := passed_tests + (CASE WHEN passed THEN 1 ELSE 0 END);
|
||||
IF passed THEN
|
||||
RAISE NOTICE 'Test %: Complex template with all tag types: PASSED', total_tests;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Complex template with all tag types: FAILED. Expected "%", got "%"',
|
||||
total_tests, pg_temp.test_regexp_replace(expected), pg_temp.test_regexp_replace(test_result);
|
||||
END IF;
|
||||
EXCEPTION WHEN OTHERS THEN
|
||||
RAISE WARNING 'Test % failed: Error: %', total_tests, SQLERRM;
|
||||
END;
|
||||
|
||||
-- Test 3: Template with nested includes and shared context
|
||||
total_tests := total_tests + 1;
|
||||
BEGIN
|
||||
test_result := hemar.render(
|
||||
'{
|
||||
"user": {
|
||||
"name": "John",
|
||||
"role": "admin"
|
||||
},
|
||||
"include": {
|
||||
"user_info": {
|
||||
"template": "User: {{ user.name }} ({{ user.role }})"
|
||||
},
|
||||
"permissions": {
|
||||
"template": "{{ include user_info }} - Permissions: {{ for perm in user.permissions }}{{ perm }} {{ end }}",
|
||||
"context": {
|
||||
"user": {
|
||||
"name": "John",
|
||||
"role": "admin",
|
||||
"permissions": ["read", "write", "delete"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}'::jsonb,
|
||||
$template${{ include permissions }}$template$
|
||||
);
|
||||
|
||||
expected := 'User: John (admin) - Permissions: read write delete ';
|
||||
|
||||
passed := test_result = expected;
|
||||
passed_tests := passed_tests + (CASE WHEN passed THEN 1 ELSE 0 END);
|
||||
IF passed THEN
|
||||
RAISE NOTICE 'Test %: Template with nested includes and shared context: PASSED', total_tests;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Template with nested includes and shared context: FAILED. Expected "%", got "%"',
|
||||
total_tests, expected, test_result;
|
||||
END IF;
|
||||
EXCEPTION WHEN OTHERS THEN
|
||||
RAISE WARNING 'Test % failed: Error: %', total_tests, SQLERRM;
|
||||
END;
|
||||
|
||||
-- Print summary
|
||||
IF passed_tests = total_tests THEN
|
||||
RAISE NOTICE '------------------------------------';
|
||||
RAISE NOTICE 'SUMMARY: % of % combined template tests passed (100%%)',
|
||||
passed_tests, total_tests;
|
||||
RAISE NOTICE '------------------------------------';
|
||||
ELSE
|
||||
RAISE WARNING '------------------------------------';
|
||||
RAISE WARNING 'SUMMARY: % of % combined template 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 % combined template tests did not pass', (total_tests - passed_tests), total_tests;
|
||||
END IF;
|
||||
END $$;
|
||||
343
package/c/hemar-legacy/test/test_render_exec.sql
Executable file
343
package/c/hemar-legacy/test/test_render_exec.sql
Executable file
@@ -0,0 +1,343 @@
|
||||
-- Test the render function with execute tags
|
||||
CREATE EXTENSION IF NOT EXISTS hemar;
|
||||
|
||||
DO $$
|
||||
DECLARE
|
||||
total_tests INT := 0;
|
||||
passed_tests INT := 0;
|
||||
test_result TEXT;
|
||||
expected TEXT;
|
||||
passed BOOLEAN;
|
||||
BEGIN
|
||||
-- Test 1: Simple execute tag that sets a variable
|
||||
total_tests := total_tests + 1;
|
||||
test_result := hemar.render(
|
||||
'{"name": "John", "age": 30}'::jsonb,
|
||||
'Hello {{ exec PERFORM 1; }}'
|
||||
);
|
||||
expected := 'Hello ';
|
||||
passed := test_result = expected;
|
||||
passed_tests := passed_tests + (CASE WHEN passed THEN 1 ELSE 0 END);
|
||||
IF passed THEN
|
||||
RAISE NOTICE 'Test %: Simple execute tag: PASSED', total_tests;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Simple execute tag: FAILED. Expected "%", got "%"',
|
||||
total_tests, expected, test_result;
|
||||
END IF;
|
||||
|
||||
-- Test 2: Execute tag with context access
|
||||
total_tests := total_tests + 1;
|
||||
DROP TABLE IF EXISTS test_output;
|
||||
CREATE TEMP TABLE test_output (value TEXT);
|
||||
|
||||
test_result := hemar.render(
|
||||
'{"name": "John", "age": 30}'::jsonb,
|
||||
$expected$Hello {{ exec INSERT INTO test_output VALUES (context->'name'); }}$expected$
|
||||
);
|
||||
|
||||
SELECT value INTO expected FROM test_output;
|
||||
passed := expected = '"John"';
|
||||
passed_tests := passed_tests + (CASE WHEN passed THEN 1 ELSE 0 END);
|
||||
IF passed THEN
|
||||
RAISE NOTICE 'Test %: Execute tag with context access: PASSED', total_tests;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Execute tag with context access: FAILED. Expected "John", got "%"',
|
||||
total_tests, expected;
|
||||
END IF;
|
||||
|
||||
-- Test 3: Execute tag with quotes and complex SQL
|
||||
total_tests := total_tests + 1;
|
||||
DROP TABLE IF EXISTS test_output;
|
||||
CREATE TEMP TABLE test_output (value TEXT);
|
||||
|
||||
test_result := hemar.render(
|
||||
'{"items": [{"id": 1, "name": "Item 1"}, {"id": 2, "name": "Item 2"}]}'::jsonb,
|
||||
$expected$Items: {{ exec
|
||||
INSERT INTO test_output
|
||||
SELECT jsonb_array_elements(context->'items')->>'name';
|
||||
}}$expected$
|
||||
);
|
||||
|
||||
SELECT string_agg(value, ', ' ORDER BY value) INTO expected FROM test_output;
|
||||
passed := expected = 'Item 1, Item 2';
|
||||
passed_tests := passed_tests + (CASE WHEN passed THEN 1 ELSE 0 END);
|
||||
IF passed THEN
|
||||
RAISE NOTICE 'Test %: Execute tag with complex SQL: PASSED', total_tests;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Execute tag with complex SQL: FAILED. Expected "Item 1, Item 2", got "%"',
|
||||
total_tests, expected;
|
||||
END IF;
|
||||
|
||||
-- Test 4: Execute tag with output capture
|
||||
total_tests := total_tests + 1;
|
||||
test_result := hemar.render(
|
||||
'{"name": "John", "age": 30}'::jsonb,
|
||||
$expected$Hello {{ exec RETURN context->>'name'; }}$expected$
|
||||
);
|
||||
expected := 'Hello John';
|
||||
passed := test_result = expected;
|
||||
passed_tests := passed_tests + (CASE WHEN passed THEN 1 ELSE 0 END);
|
||||
IF passed THEN
|
||||
RAISE NOTICE 'Test %: Execute tag with output capture: PASSED', total_tests;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Execute tag with output capture: FAILED. Expected "%", got "%"',
|
||||
total_tests, expected, test_result;
|
||||
END IF;
|
||||
|
||||
-- Test 5: Execute tag with complex output
|
||||
total_tests := total_tests + 1;
|
||||
test_result := hemar.render(
|
||||
'{"items": [{"id": 1, "name": "Item 1"}, {"id": 2, "name": "Item 2"}]}'::jsonb,
|
||||
$expected$Items: {{ exec
|
||||
RETURN (SELECT string_agg(value, ', ')
|
||||
FROM (
|
||||
SELECT jsonb_array_elements(context->'items')->>'name' as value
|
||||
) t);
|
||||
}}$expected$
|
||||
);
|
||||
expected := 'Items: Item 1, Item 2';
|
||||
passed := test_result = expected;
|
||||
passed_tests := passed_tests + (CASE WHEN passed THEN 1 ELSE 0 END);
|
||||
IF passed THEN
|
||||
RAISE NOTICE 'Test %: Execute tag with complex output: PASSED', total_tests;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Execute tag with complex output: FAILED. Expected "%", got "%"',
|
||||
total_tests, expected, test_result;
|
||||
END IF;
|
||||
|
||||
-- Test 6: Execute tag with multiple statements
|
||||
total_tests := total_tests + 1;
|
||||
test_result := hemar.render(
|
||||
'{"name": "John", "age": 30}'::jsonb,
|
||||
$expected$Hello {{ exec
|
||||
DECLARE
|
||||
v_name TEXT;
|
||||
BEGIN
|
||||
v_name := context->>'name';
|
||||
RETURN v_name;
|
||||
END;
|
||||
}}$expected$
|
||||
);
|
||||
expected := 'Hello John';
|
||||
passed := test_result = expected;
|
||||
passed_tests := passed_tests + (CASE WHEN passed THEN 1 ELSE 0 END);
|
||||
IF passed THEN
|
||||
RAISE NOTICE 'Test %: Execute tag with multiple statements: PASSED', total_tests;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Execute tag with multiple statements: FAILED. Expected "%", got "%"',
|
||||
total_tests, expected, test_result;
|
||||
END IF;
|
||||
|
||||
-- Test 7: Execute tag with array operations
|
||||
total_tests := total_tests + 1;
|
||||
test_result := hemar.render(
|
||||
'{"numbers": [1, 2, 3, 4, 5]}'::jsonb,
|
||||
$expected$Sum: {{ exec
|
||||
RETURN (SELECT sum(value::int)
|
||||
FROM jsonb_array_elements_text(context->'numbers') as value);
|
||||
}}$expected$
|
||||
);
|
||||
expected := 'Sum: 15';
|
||||
passed := test_result = expected;
|
||||
passed_tests := passed_tests + (CASE WHEN passed THEN 1 ELSE 0 END);
|
||||
IF passed THEN
|
||||
RAISE NOTICE 'Test %: Execute tag with array operations: PASSED', total_tests;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Execute tag with array operations: FAILED. Expected "%", got "%"',
|
||||
total_tests, expected, test_result;
|
||||
END IF;
|
||||
|
||||
-- Test 8: Execute tag with nested JSON operations
|
||||
total_tests := total_tests + 1;
|
||||
test_result := hemar.render(
|
||||
'{"user": {"profile": {"settings": {"theme": "dark", "notifications": true}}}}'::jsonb,
|
||||
$expected$Settings: {{ exec
|
||||
RETURN context->'user'->'profile'->'settings'->>'theme';
|
||||
}}$expected$
|
||||
);
|
||||
expected := 'Settings: dark';
|
||||
passed := test_result = expected;
|
||||
passed_tests := passed_tests + (CASE WHEN passed THEN 1 ELSE 0 END);
|
||||
IF passed THEN
|
||||
RAISE NOTICE 'Test %: Execute tag with nested JSON operations: PASSED', total_tests;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Execute tag with nested JSON operations: FAILED. Expected "%", got "%"',
|
||||
total_tests, expected, test_result;
|
||||
END IF;
|
||||
|
||||
-- Test 9: Execute tag with conditional logic
|
||||
total_tests := total_tests + 1;
|
||||
test_result := hemar.render(
|
||||
'{"age": 25, "country": "US"}'::jsonb,
|
||||
$expected$Status: {{ exec
|
||||
DECLARE
|
||||
v_status TEXT;
|
||||
BEGIN
|
||||
IF (context->>'age')::int >= 21 AND context->>'country' = 'US' THEN
|
||||
v_status := 'Adult in US';
|
||||
ELSE
|
||||
v_status := 'Other';
|
||||
END IF;
|
||||
RETURN v_status;
|
||||
END;
|
||||
}}$expected$
|
||||
);
|
||||
expected := 'Status: Adult in US';
|
||||
passed := test_result = expected;
|
||||
passed_tests := passed_tests + (CASE WHEN passed THEN 1 ELSE 0 END);
|
||||
IF passed THEN
|
||||
RAISE NOTICE 'Test %: Execute tag with conditional logic: PASSED', total_tests;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Execute tag with conditional logic: FAILED. Expected "%", got "%"',
|
||||
total_tests, expected, test_result;
|
||||
END IF;
|
||||
|
||||
-- Test 10: Execute tag with string manipulation
|
||||
total_tests := total_tests + 1;
|
||||
test_result := hemar.render(
|
||||
'{"text": "hello world"}'::jsonb,
|
||||
$expected$Text: {{ exec
|
||||
RETURN upper(context->>'text');
|
||||
}}$expected$
|
||||
);
|
||||
expected := 'Text: HELLO WORLD';
|
||||
passed := test_result = expected;
|
||||
passed_tests := passed_tests + (CASE WHEN passed THEN 1 ELSE 0 END);
|
||||
IF passed THEN
|
||||
RAISE NOTICE 'Test %: Execute tag with string manipulation: PASSED', total_tests;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Execute tag with string manipulation: FAILED. Expected "%", got "%"',
|
||||
total_tests, expected, test_result;
|
||||
END IF;
|
||||
|
||||
-- Test 11: Execute tag with date operations
|
||||
total_tests := total_tests + 1;
|
||||
test_result := hemar.render(
|
||||
'{"date": "2024-03-15"}'::jsonb,
|
||||
$expected$Date: {{ exec
|
||||
RETURN to_char((context->>'date')::date, 'Month DD, YYYY');
|
||||
}}$expected$
|
||||
);
|
||||
expected := 'Date: March 15, 2024';
|
||||
passed := test_result = expected;
|
||||
passed_tests := passed_tests + (CASE WHEN passed THEN 1 ELSE 0 END);
|
||||
IF passed THEN
|
||||
RAISE NOTICE 'Test %: Execute tag with date operations: PASSED', total_tests;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Execute tag with date operations: FAILED. Expected "%", got "%"',
|
||||
total_tests, expected, test_result;
|
||||
END IF;
|
||||
|
||||
-- Test 12: Execute tag with aggregation
|
||||
total_tests := total_tests + 1;
|
||||
test_result := hemar.render(
|
||||
'{"scores": [85, 92, 78, 95, 88]}'::jsonb,
|
||||
$expected$Stats: {{ exec
|
||||
RETURN (SELECT format('Avg: %s, Max: %s',
|
||||
round(avg(value::float)::numeric, 1),
|
||||
max(value::int))
|
||||
FROM jsonb_array_elements_text(context->'scores') as value);
|
||||
}}$expected$
|
||||
);
|
||||
expected := 'Stats: Avg: 87.6, Max: 95';
|
||||
passed := test_result = expected;
|
||||
passed_tests := passed_tests + (CASE WHEN passed THEN 1 ELSE 0 END);
|
||||
IF passed THEN
|
||||
RAISE NOTICE 'Test %: Execute tag with aggregation: PASSED', total_tests;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Execute tag with aggregation: FAILED. Expected "%", got "%"',
|
||||
total_tests, expected, test_result;
|
||||
END IF;
|
||||
|
||||
-- Test 13: Execute tag with error handling
|
||||
total_tests := total_tests + 1;
|
||||
test_result := hemar.render(
|
||||
'{"value": "not_a_number"}'::jsonb,
|
||||
$expected$Result: {{ exec
|
||||
BEGIN
|
||||
RETURN (context->>'value')::int::text;
|
||||
EXCEPTION WHEN OTHERS THEN
|
||||
RETURN 'Error: Invalid number';
|
||||
END;
|
||||
}}$expected$
|
||||
);
|
||||
expected := 'Result: Error: Invalid number';
|
||||
passed := test_result = expected;
|
||||
passed_tests := passed_tests + (CASE WHEN passed THEN 1 ELSE 0 END);
|
||||
IF passed THEN
|
||||
RAISE NOTICE 'Test %: Execute tag with error handling: PASSED', total_tests;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Execute tag with error handling: FAILED. Expected "%", got "%"',
|
||||
total_tests, expected, test_result;
|
||||
END IF;
|
||||
|
||||
-- Test 14: Execute tag with complex JSON transformation
|
||||
total_tests := total_tests + 1;
|
||||
test_result := hemar.render(
|
||||
'{"users": [{"name": "Alice", "roles": ["admin", "user"]}, {"name": "Bob", "roles": ["user"]}]}'::jsonb,
|
||||
$expected$Users: {{ exec
|
||||
RETURN (SELECT string_agg(
|
||||
format('%s (%s)',
|
||||
user_data->>'name',
|
||||
(SELECT string_agg(role, ', ')
|
||||
FROM jsonb_array_elements_text(user_data->'roles') as role)
|
||||
),
|
||||
'; '
|
||||
)
|
||||
FROM jsonb_array_elements(context->'users') as user_data);
|
||||
}}$expected$
|
||||
);
|
||||
expected := 'Users: Alice (admin, user); Bob (user)';
|
||||
passed := test_result = expected;
|
||||
passed_tests := passed_tests + (CASE WHEN passed THEN 1 ELSE 0 END);
|
||||
IF passed THEN
|
||||
RAISE NOTICE 'Test %: Execute tag with complex JSON transformation: PASSED', total_tests;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Execute tag with complex JSON transformation: FAILED. Expected "%", got "%"',
|
||||
total_tests, expected, test_result;
|
||||
END IF;
|
||||
|
||||
-- Test 15: Execute tag with empty/null handling
|
||||
total_tests := total_tests + 1;
|
||||
test_result := hemar.render(
|
||||
'{"name": null, "items": []}'::jsonb,
|
||||
$expected$Result: {{ exec
|
||||
DECLARE
|
||||
v_name TEXT;
|
||||
v_count INT;
|
||||
BEGIN
|
||||
v_name := COALESCE(context->>'name', 'Unknown');
|
||||
v_count := jsonb_array_length(context->'items');
|
||||
RETURN format('Name: %s, Items: %s', v_name, v_count);
|
||||
END;
|
||||
}}$expected$
|
||||
);
|
||||
expected := 'Result: Name: Unknown, Items: 0';
|
||||
passed := test_result = expected;
|
||||
passed_tests := passed_tests + (CASE WHEN passed THEN 1 ELSE 0 END);
|
||||
IF passed THEN
|
||||
RAISE NOTICE 'Test %: Execute tag with empty/null handling: PASSED', total_tests;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Execute tag with empty/null handling: FAILED. Expected "%", got "%"',
|
||||
total_tests, expected, test_result;
|
||||
END IF;
|
||||
|
||||
-- Print summary
|
||||
IF passed_tests = total_tests THEN
|
||||
RAISE NOTICE '------------------------------------';
|
||||
RAISE NOTICE 'SUMMARY: % of % render exec tests passed (100%%)',
|
||||
passed_tests, total_tests;
|
||||
RAISE NOTICE '------------------------------------';
|
||||
ELSE
|
||||
RAISE WARNING '------------------------------------';
|
||||
RAISE WARNING 'SUMMARY: % of % render exec 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 % render exec tests did not pass', (total_tests - passed_tests), total_tests;
|
||||
END IF;
|
||||
END $$;
|
||||
235
package/c/hemar-legacy/test/test_render_include.sql
Executable file
235
package/c/hemar-legacy/test/test_render_include.sql
Executable file
@@ -0,0 +1,235 @@
|
||||
-- Test include tag functionality
|
||||
DO $$
|
||||
DECLARE
|
||||
result text;
|
||||
total_tests integer := 0;
|
||||
passed_tests integer := 0;
|
||||
BEGIN
|
||||
-- Test 1: Plain text inclusion
|
||||
total_tests := total_tests + 1;
|
||||
BEGIN
|
||||
result := hemar.render(
|
||||
'{
|
||||
"include": {
|
||||
"inner_template": {
|
||||
"content": "<p>Hello World</p>"
|
||||
}
|
||||
}
|
||||
}'::jsonb,
|
||||
$hemar${{ include inner_template }}$hemar$
|
||||
);
|
||||
|
||||
IF result = '<p>Hello World</p>' THEN
|
||||
RAISE NOTICE 'Test %: Plain text inclusion works correctly', total_tests;
|
||||
passed_tests := passed_tests + 1;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: failed, Expected "<p>Hello World</p>", got "%"', total_tests, result;
|
||||
END IF;
|
||||
EXCEPTION WHEN OTHERS THEN
|
||||
RAISE WARNING 'Test %: Plain text inclusion: FAILED with error: %', total_tests, SQLERRM;
|
||||
END;
|
||||
|
||||
-- Test 2: Template with separate context
|
||||
total_tests := total_tests + 1;
|
||||
result := hemar.render(
|
||||
'{
|
||||
"include": {
|
||||
"inner_template": {
|
||||
"template": "Hello {{ name }}!",
|
||||
"context": {
|
||||
"name": "John"
|
||||
}
|
||||
}
|
||||
}
|
||||
}'::jsonb,
|
||||
$hemar${{ include inner_template }}$hemar$
|
||||
);
|
||||
|
||||
IF result = 'Hello John!' THEN
|
||||
RAISE NOTICE 'Test %: Template with separate context works correctly', total_tests;
|
||||
passed_tests := passed_tests + 1;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: failed, Expected "Hello John!", got "%"', total_tests, result;
|
||||
END IF;
|
||||
|
||||
-- Test 3: Template with shared context
|
||||
total_tests := total_tests + 1;
|
||||
result := hemar.render(
|
||||
'{
|
||||
"name": "John",
|
||||
"include": {
|
||||
"inner_template": {
|
||||
"template": "Hello {{ name }}!"
|
||||
}
|
||||
}
|
||||
}'::jsonb,
|
||||
$hemar${{ include inner_template }}$hemar$
|
||||
);
|
||||
|
||||
IF result = 'Hello John!' THEN
|
||||
RAISE NOTICE 'Test % passed: Template with shared context works correctly', total_tests;
|
||||
passed_tests := passed_tests + 1;
|
||||
ELSE
|
||||
RAISE WARNING 'Test % failed: Expected "Hello John!", got "%"', total_tests, result;
|
||||
END IF;
|
||||
|
||||
-- Test 4: Nested includes
|
||||
total_tests := total_tests + 1;
|
||||
result := hemar.render(
|
||||
'{
|
||||
"include": {
|
||||
"outer_template": {
|
||||
"template": "Outer: {{ include inner_template }}",
|
||||
"context": {
|
||||
"include": {
|
||||
"inner_template": {
|
||||
"template": "Inner: {{ name }}",
|
||||
"context": {
|
||||
"name": "John"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}'::jsonb,
|
||||
$hemar${{ include outer_template }}$hemar$
|
||||
);
|
||||
|
||||
IF result = 'Outer: Inner: John' THEN
|
||||
RAISE NOTICE 'Test % passed: Nested includes work correctly', total_tests;
|
||||
passed_tests := passed_tests + 1;
|
||||
ELSE
|
||||
RAISE WARNING 'Test % failed: Expected "Outer: Inner: John", got "%"', total_tests, result;
|
||||
END IF;
|
||||
|
||||
-- Test 5: Complex template with multiple includes
|
||||
total_tests := total_tests + 1;
|
||||
result := hemar.render(
|
||||
'{
|
||||
"include": {
|
||||
"header": {
|
||||
"content": "<header>Welcome</header>"
|
||||
},
|
||||
"content": {
|
||||
"template": "Hello {{ user.name }}!",
|
||||
"context": {
|
||||
"user": {
|
||||
"name": "John"
|
||||
}
|
||||
}
|
||||
},
|
||||
"footer": {
|
||||
"template": "Copyright {{ year }}",
|
||||
"context": {
|
||||
"year": "2024"
|
||||
}
|
||||
}
|
||||
}
|
||||
}'::jsonb,
|
||||
$hemar$Header: {{ include header }}
|
||||
Content: {{ include content }}
|
||||
Footer: {{ include footer }}$hemar$
|
||||
);
|
||||
|
||||
IF result = 'Header: <header>Welcome</header>
|
||||
Content: Hello John!
|
||||
Footer: Copyright 2024' THEN
|
||||
RAISE NOTICE 'Test % passed: Complex template with multiple includes works correctly', total_tests;
|
||||
passed_tests := passed_tests + 1;
|
||||
ELSE
|
||||
RAISE WARNING 'Test % failed: Expected , got "%"', total_tests, result;
|
||||
END IF;
|
||||
|
||||
-- Test 6: Error handling - missing include data
|
||||
total_tests := total_tests + 1;
|
||||
BEGIN
|
||||
result := hemar.render(
|
||||
'{{ include missing_template }}',
|
||||
'{}'::jsonb
|
||||
);
|
||||
RAISE WARNING 'Test % failed: Should have raised an error for missing include data', total_tests;
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
RAISE NOTICE 'Test % passed: Error handling for missing include data works correctly', total_tests;
|
||||
passed_tests := passed_tests + 1;
|
||||
END;
|
||||
|
||||
-- Test 7: Error handling - invalid include data
|
||||
total_tests := total_tests + 1;
|
||||
BEGIN
|
||||
result := hemar.render(
|
||||
'{
|
||||
"include": {
|
||||
"invalid_template": "not an object"
|
||||
}
|
||||
}'::jsonb,
|
||||
'{{ include invalid_template }}'
|
||||
);
|
||||
|
||||
IF result = '' THEN
|
||||
RAISE NOTICE 'Test % passed: Error handling for invalid include data works correctly', total_tests;
|
||||
passed_tests := passed_tests + 1;
|
||||
ELSE
|
||||
RAISE WARNING 'Test % failed: Expected "", got "%"', total_tests, result;
|
||||
END IF;
|
||||
EXCEPTION WHEN OTHERS THEN
|
||||
RAISE WARNING 'Test % failed: Should have raised an error for invalid include data', total_tests;
|
||||
END;
|
||||
|
||||
-- Test 8: Error handling - unexisting include object
|
||||
total_tests := total_tests + 1;
|
||||
BEGIN
|
||||
result := hemar.render(
|
||||
'{}'::jsonb,
|
||||
'{{ include invalid_template }}'
|
||||
);
|
||||
|
||||
IF result = '' THEN
|
||||
RAISE NOTICE 'Test % passed: Error handling for unexisting include object works correctly', total_tests;
|
||||
passed_tests := passed_tests + 1;
|
||||
ELSE
|
||||
RAISE WARNING 'Test % failed: Expected "", got "%"', total_tests, result;
|
||||
END IF;
|
||||
EXCEPTION WHEN OTHERS THEN
|
||||
RAISE WARNING 'Test % failed: Should have raised an error for unexisting include object', total_tests;
|
||||
END;
|
||||
|
||||
-- Test 9: Error handling - unexisting include data
|
||||
total_tests := total_tests + 1;
|
||||
BEGIN
|
||||
result := hemar.render(
|
||||
'{
|
||||
"include": { }
|
||||
}'::jsonb,
|
||||
'{{ include invalid_template }}'
|
||||
);
|
||||
|
||||
IF result = '' THEN
|
||||
RAISE NOTICE 'Test % passed: Error handling for unexisting include data works correctly', total_tests;
|
||||
passed_tests := passed_tests + 1;
|
||||
ELSE
|
||||
RAISE WARNING 'Test % failed: Expected "", got "%"', total_tests, result;
|
||||
END IF;
|
||||
EXCEPTION WHEN OTHERS THEN
|
||||
RAISE WARNING 'Test % failed: Should have raised an error for unexisting include data', total_tests;
|
||||
END;
|
||||
|
||||
IF passed_tests = total_tests THEN
|
||||
RAISE NOTICE '------------------------------------';
|
||||
RAISE NOTICE 'SUMMARY: % of % template include tests passed (100%%)',
|
||||
passed_tests, total_tests;
|
||||
RAISE NOTICE '------------------------------------';
|
||||
ELSE
|
||||
RAISE WARNING '------------------------------------';
|
||||
RAISE WARNING 'SUMMARY: % of % template include 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 % template include tests did not pass', (total_tests - passed_tests), total_tests;
|
||||
END IF;
|
||||
END $$;
|
||||
190
package/c/hemar-legacy/test/test_render_interpolate.sql
Executable file
190
package/c/hemar-legacy/test/test_render_interpolate.sql
Executable file
@@ -0,0 +1,190 @@
|
||||
-- Test the render function with interpolation tags
|
||||
CREATE EXTENSION IF NOT EXISTS hemar;
|
||||
|
||||
DO $$
|
||||
DECLARE
|
||||
total_tests INT := 0;
|
||||
passed_tests INT := 0;
|
||||
test_result TEXT;
|
||||
expected TEXT;
|
||||
passed BOOLEAN;
|
||||
BEGIN
|
||||
-- Test 1: Simple string interpolation
|
||||
total_tests := total_tests + 1;
|
||||
test_result := hemar.render(
|
||||
'{"name": "John"}'::jsonb,
|
||||
'Hello {{ name }}!'
|
||||
);
|
||||
expected := 'Hello John!';
|
||||
passed := test_result = expected;
|
||||
passed_tests := passed_tests + (CASE WHEN passed THEN 1 ELSE 0 END);
|
||||
IF passed THEN
|
||||
RAISE NOTICE 'Test %: Simple string interpolation: PASSED', total_tests;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Simple string interpolation: FAILED. Expected "%", got "%"',
|
||||
total_tests, expected, test_result;
|
||||
END IF;
|
||||
|
||||
-- Test 2: Numeric interpolation
|
||||
total_tests := total_tests + 1;
|
||||
test_result := hemar.render(
|
||||
'{"age": 30, "price": 19.99}'::jsonb,
|
||||
'Age: {{ age }}, Price: {{ price }}'
|
||||
);
|
||||
expected := 'Age: 30, Price: 19.99';
|
||||
passed := test_result = expected;
|
||||
passed_tests := passed_tests + (CASE WHEN passed THEN 1 ELSE 0 END);
|
||||
IF passed THEN
|
||||
RAISE NOTICE 'Test %: Numeric interpolation: PASSED', total_tests;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Numeric interpolation: FAILED. Expected "%", got "%"',
|
||||
total_tests, expected, test_result;
|
||||
END IF;
|
||||
|
||||
-- Test 3: Boolean interpolation
|
||||
total_tests := total_tests + 1;
|
||||
test_result := hemar.render(
|
||||
'{"is_active": true, "is_deleted": false}'::jsonb,
|
||||
'Status: {{ is_active }}, Deleted: {{ is_deleted }}'
|
||||
);
|
||||
expected := 'Status: true, Deleted: false';
|
||||
passed := test_result = expected;
|
||||
passed_tests := passed_tests + (CASE WHEN passed THEN 1 ELSE 0 END);
|
||||
IF passed THEN
|
||||
RAISE NOTICE 'Test %: Boolean interpolation: PASSED', total_tests;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Boolean interpolation: FAILED. Expected "%", got "%"',
|
||||
total_tests, expected, test_result;
|
||||
END IF;
|
||||
|
||||
-- Test 4: Null value interpolation
|
||||
total_tests := total_tests + 1;
|
||||
test_result := hemar.render(
|
||||
'{"name": null}'::jsonb,
|
||||
'Name: {{ name }}'
|
||||
);
|
||||
expected := 'Name: ';
|
||||
passed := test_result = expected;
|
||||
passed_tests := passed_tests + (CASE WHEN passed THEN 1 ELSE 0 END);
|
||||
IF passed THEN
|
||||
RAISE NOTICE 'Test %: Null value interpolation: PASSED', total_tests;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Null value interpolation: FAILED. Expected "%", got "%"',
|
||||
total_tests, expected, test_result;
|
||||
END IF;
|
||||
|
||||
-- Test 5: Nested object interpolation
|
||||
total_tests := total_tests + 1;
|
||||
test_result := hemar.render(
|
||||
'{"user": {"profile": {"name": "John", "age": 30}}}'::jsonb,
|
||||
'User: {{ user.profile.name }}, Age: {{ user.profile.age }}'
|
||||
);
|
||||
expected := 'User: John, Age: 30';
|
||||
passed := test_result = expected;
|
||||
passed_tests := passed_tests + (CASE WHEN passed THEN 1 ELSE 0 END);
|
||||
IF passed THEN
|
||||
RAISE NOTICE 'Test %: Nested object interpolation: PASSED', total_tests;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Nested object interpolation: FAILED. Expected "%", got "%"',
|
||||
total_tests, expected, test_result;
|
||||
END IF;
|
||||
|
||||
-- Test 6: Array interpolation
|
||||
total_tests := total_tests + 1;
|
||||
test_result := hemar.render(
|
||||
'{"numbers": [1, 2, 3], "names": ["John", "Jane"]}'::jsonb,
|
||||
'Numbers: {{ numbers }}, Names: {{ names }}'
|
||||
);
|
||||
expected := 'Numbers: [1, 2, 3], Names: ["John", "Jane"]';
|
||||
passed := test_result = expected;
|
||||
passed_tests := passed_tests + (CASE WHEN passed THEN 1 ELSE 0 END);
|
||||
IF passed THEN
|
||||
RAISE NOTICE 'Test %: Array interpolation: PASSED', total_tests;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Array interpolation: FAILED. Expected "%", got "%"',
|
||||
total_tests, expected, test_result;
|
||||
END IF;
|
||||
|
||||
-- Test 7: Array index interpolation
|
||||
total_tests := total_tests + 1;
|
||||
test_result := hemar.render(
|
||||
'{"items": [{"id": 1, "name": "Item 1"}, {"id": 2, "name": "Item 2"}]}'::jsonb,
|
||||
'First item: {{ items[0].name }}, Second item: {{ items[1].name }}'
|
||||
);
|
||||
expected := 'First item: Item 1, Second item: Item 2';
|
||||
passed := test_result = expected;
|
||||
passed_tests := passed_tests + (CASE WHEN passed THEN 1 ELSE 0 END);
|
||||
IF passed THEN
|
||||
RAISE NOTICE 'Test %: Array index interpolation: PASSED', total_tests;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Array index interpolation: FAILED. Expected "%", got "%"',
|
||||
total_tests, expected, test_result;
|
||||
END IF;
|
||||
|
||||
-- Test 8: Complex nested structure interpolation
|
||||
total_tests := total_tests + 1;
|
||||
test_result := hemar.render(
|
||||
'{"company": {"name": "Tech Corp", "employees": [{"name": "John", "role": "Developer"}, {"name": "Jane", "role": "Manager"}]}}'::jsonb,
|
||||
'Company: {{ company.name }}, First employee: {{ company.employees[0].name }} ({{ company.employees[0].role }})'
|
||||
);
|
||||
expected := 'Company: Tech Corp, First employee: John (Developer)';
|
||||
passed := test_result = expected;
|
||||
passed_tests := passed_tests + (CASE WHEN passed THEN 1 ELSE 0 END);
|
||||
IF passed THEN
|
||||
RAISE NOTICE 'Test %: Complex nested structure interpolation: PASSED', total_tests;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Complex nested structure interpolation: FAILED. Expected "%", got "%"',
|
||||
total_tests, expected, test_result;
|
||||
END IF;
|
||||
|
||||
-- Test 9: Multiple interpolations in text
|
||||
total_tests := total_tests + 1;
|
||||
test_result := hemar.render(
|
||||
'{"greeting": "Hello", "name": "John", "punctuation": "!"}'::jsonb,
|
||||
'{{ greeting }} {{ name }}{{ punctuation }} How are you {{ name }}?'
|
||||
);
|
||||
expected := 'Hello John! How are you John?';
|
||||
passed := test_result = expected;
|
||||
passed_tests := passed_tests + (CASE WHEN passed THEN 1 ELSE 0 END);
|
||||
IF passed THEN
|
||||
RAISE NOTICE 'Test %: Multiple interpolations in text: PASSED', total_tests;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Multiple interpolations in text: FAILED. Expected "%", got "%"',
|
||||
total_tests, expected, test_result;
|
||||
END IF;
|
||||
|
||||
-- Test 10: Invalid path handling
|
||||
total_tests := total_tests + 1;
|
||||
test_result := hemar.render(
|
||||
'{"name": "John"}'::jsonb,
|
||||
'Name: {{ name }}, Age: {{ age }}, Address: {{ address.street }}'
|
||||
);
|
||||
expected := 'Name: John, Age: , Address: ';
|
||||
passed := test_result = expected;
|
||||
passed_tests := passed_tests + (CASE WHEN passed THEN 1 ELSE 0 END);
|
||||
IF passed THEN
|
||||
RAISE NOTICE 'Test %: Invalid path handling: PASSED', total_tests;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Invalid path handling: FAILED. Expected "%", got "%"',
|
||||
total_tests, expected, test_result;
|
||||
END IF;
|
||||
|
||||
-- Print summary
|
||||
IF passed_tests = total_tests THEN
|
||||
RAISE NOTICE '------------------------------------';
|
||||
RAISE NOTICE 'SUMMARY: % of % interpolation render tests passed (100%%)',
|
||||
passed_tests, total_tests;
|
||||
RAISE NOTICE '------------------------------------';
|
||||
ELSE
|
||||
RAISE WARNING '------------------------------------';
|
||||
RAISE WARNING 'SUMMARY: % of % interpolation render 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 % interpolation render tests did not pass', (total_tests - passed_tests), total_tests;
|
||||
END IF;
|
||||
END $$;
|
||||
401
package/c/hemar-legacy/test/test_render_section.sql
Executable file
401
package/c/hemar-legacy/test/test_render_section.sql
Executable file
@@ -0,0 +1,401 @@
|
||||
-- Test section rendering
|
||||
DO $$
|
||||
DECLARE
|
||||
test_result text;
|
||||
expected text;
|
||||
total_tests integer := 0;
|
||||
passed_tests integer := 0;
|
||||
BEGIN
|
||||
-- Test 1: String iteration
|
||||
total_tests := total_tests + 1;
|
||||
BEGIN
|
||||
test_result := hemar.render(
|
||||
'{"text": "Hello"}'::jsonb,
|
||||
'{{for char in text}}{{char}}{{end}}'
|
||||
);
|
||||
expected := 'Hello';
|
||||
IF test_result = expected THEN
|
||||
RAISE NOTICE 'Test %: String iteration: PASSED', total_tests;
|
||||
passed_tests := passed_tests + 1;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: String iteration: FAILED. Expected "%", got "%"', total_tests, expected, test_result;
|
||||
END IF;
|
||||
EXCEPTION WHEN OTHERS THEN
|
||||
RAISE WARNING 'Test %: String iteration: FAILED with error: %', total_tests, SQLERRM;
|
||||
END;
|
||||
|
||||
-- Test 2: Array iteration
|
||||
total_tests := total_tests + 1;
|
||||
BEGIN
|
||||
test_result := hemar.render(
|
||||
'{"numbers": [1, 2, 3]}'::jsonb,
|
||||
'{{for num in numbers}}{{num}}{{end}}'
|
||||
);
|
||||
expected := '123';
|
||||
IF test_result = expected THEN
|
||||
RAISE NOTICE 'Test %: Array iteration: PASSED', total_tests;
|
||||
passed_tests := passed_tests + 1;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Array iteration: FAILED. Expected "%", got "%"', total_tests, expected, test_result;
|
||||
END IF;
|
||||
EXCEPTION WHEN OTHERS THEN
|
||||
RAISE WARNING 'Test %: Array iteration: FAILED with error: %', total_tests, SQLERRM;
|
||||
END;
|
||||
|
||||
-- Test 3: Object iteration
|
||||
total_tests := total_tests + 1;
|
||||
BEGIN
|
||||
test_result := hemar.render(
|
||||
'{"user": {"name": "John", "age": 30}}'::jsonb,
|
||||
'{{for item in user}}{{item.key}}: {{item.value}}{{end}}'
|
||||
);
|
||||
expected := 'age: 30name: John';
|
||||
IF test_result = expected THEN
|
||||
RAISE NOTICE 'Test %: Object iteration: PASSED', total_tests;
|
||||
passed_tests := passed_tests + 1;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Object iteration: FAILED. Expected "%", got "%"', total_tests, expected, test_result;
|
||||
END IF;
|
||||
EXCEPTION WHEN OTHERS THEN
|
||||
RAISE WARNING 'Test %: Object iteration: FAILED with error: %', total_tests, SQLERRM;
|
||||
END;
|
||||
|
||||
-- Test 4: Boolean condition (true)
|
||||
total_tests := total_tests + 1;
|
||||
BEGIN
|
||||
test_result := hemar.render(
|
||||
'{"show": true}'::jsonb,
|
||||
'{{for show in show}}Content{{end}}'
|
||||
);
|
||||
expected := 'Content';
|
||||
IF test_result = expected THEN
|
||||
RAISE NOTICE 'Test %: Boolean condition (true): PASSED', total_tests;
|
||||
passed_tests := passed_tests + 1;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Boolean condition (true): FAILED. Expected "%", got "%"', total_tests, expected, test_result;
|
||||
END IF;
|
||||
EXCEPTION WHEN OTHERS THEN
|
||||
RAISE WARNING 'Test %: Boolean condition (true): FAILED with error: %', total_tests, SQLERRM;
|
||||
END;
|
||||
|
||||
-- Test 5: Boolean condition (false)
|
||||
total_tests := total_tests + 1;
|
||||
BEGIN
|
||||
test_result := hemar.render(
|
||||
'{"show": false}'::jsonb,
|
||||
'{{for show in show}}Content{{end}}'
|
||||
);
|
||||
expected := '';
|
||||
IF test_result = expected THEN
|
||||
RAISE NOTICE 'Test %: Boolean condition (false): PASSED', total_tests;
|
||||
passed_tests := passed_tests + 1;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Boolean condition (false): FAILED. Expected "%", got "%"', total_tests, expected, test_result;
|
||||
END IF;
|
||||
EXCEPTION WHEN OTHERS THEN
|
||||
RAISE WARNING 'Test %: Boolean condition (false): FAILED with error: %', total_tests, SQLERRM;
|
||||
END;
|
||||
|
||||
|
||||
-- Test 6: Nested sections
|
||||
total_tests := total_tests + 1;
|
||||
BEGIN
|
||||
test_result := hemar.render(
|
||||
'{"items": [{"name": "Item 1", "tags": ["tag1", "tag2"]}, {"name": "Item 2", "tags": ["tag3"]}]}'::jsonb,
|
||||
'{{for item in items}}{{item.name}}: {{for tag in item.tags}}{{tag}} {{end}}{{end}}'
|
||||
);
|
||||
expected := 'Item 1: tag1 tag2 Item 2: tag3 ';
|
||||
IF test_result = expected THEN
|
||||
RAISE NOTICE 'Test %: Nested sections: PASSED', total_tests;
|
||||
passed_tests := passed_tests + 1;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Nested sections: FAILED. Expected "%", got "%"', total_tests, expected, test_result;
|
||||
END IF;
|
||||
EXCEPTION WHEN OTHERS THEN
|
||||
RAISE WARNING 'Test %: Nested sections: FAILED with error: %', total_tests, SQLERRM;
|
||||
END;
|
||||
|
||||
-- Test 7: Section with context
|
||||
total_tests := total_tests + 1;
|
||||
BEGIN
|
||||
test_result := hemar.render(
|
||||
'{"items": ["a", "b"], "prefix": "Item: "}'::jsonb,
|
||||
'{{for item in items}}{{prefix}}{{item}}{{end}}'
|
||||
);
|
||||
expected := 'Item: aItem: b';
|
||||
IF test_result = expected THEN
|
||||
RAISE NOTICE 'Test %: Section with context: PASSED', total_tests;
|
||||
passed_tests := passed_tests + 1;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Section with context: FAILED. Expected "%", got "%"', total_tests, expected, test_result;
|
||||
END IF;
|
||||
EXCEPTION WHEN OTHERS THEN
|
||||
RAISE WARNING 'Test %: Section with context: FAILED with error: %', total_tests, SQLERRM;
|
||||
END;
|
||||
|
||||
-- Test 8: Empty array
|
||||
total_tests := total_tests + 1;
|
||||
BEGIN
|
||||
test_result := hemar.render(
|
||||
'{"items": []}'::jsonb,
|
||||
'{{for item in items}}{{item}}{{end}}'
|
||||
);
|
||||
expected := '';
|
||||
IF test_result = expected THEN
|
||||
RAISE NOTICE 'Test %: Empty array: PASSED', total_tests;
|
||||
passed_tests := passed_tests + 1;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Empty array: FAILED. Expected "%", got "%"', total_tests, expected, test_result;
|
||||
END IF;
|
||||
EXCEPTION WHEN OTHERS THEN
|
||||
RAISE WARNING 'Test %: Empty array: FAILED with error: %', total_tests, SQLERRM;
|
||||
END;
|
||||
|
||||
-- Test 9: Empty object
|
||||
total_tests := total_tests + 1;
|
||||
BEGIN
|
||||
test_result := hemar.render(
|
||||
'{"user": {}}'::jsonb,
|
||||
'{{for key in user}}{{key}}{{end}}'
|
||||
);
|
||||
expected := '';
|
||||
IF test_result = expected THEN
|
||||
RAISE NOTICE 'Test %: Empty object: PASSED', total_tests;
|
||||
passed_tests := passed_tests + 1;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Empty object: FAILED. Expected "%", got "%"', total_tests, expected, test_result;
|
||||
END IF;
|
||||
EXCEPTION WHEN OTHERS THEN
|
||||
RAISE WARNING 'Test %: Empty object: FAILED with error: %', total_tests, SQLERRM;
|
||||
END;
|
||||
|
||||
-- Test 10: Invalid collection type (number)
|
||||
total_tests := total_tests + 1;
|
||||
BEGIN
|
||||
test_result := hemar.render(
|
||||
'{"number": 42}'::jsonb,
|
||||
'{{for item in number}}{{item}}{{end}}'
|
||||
);
|
||||
expected := '';
|
||||
IF test_result = expected THEN
|
||||
RAISE NOTICE 'Test %: Invalid collection type: PASSED (error raised as expected)', total_tests;
|
||||
passed_tests := passed_tests + 1;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Invalid collection type: FAILED. Expected "%", got "%"', total_tests, expected, test_result;
|
||||
END IF;
|
||||
EXCEPTION WHEN OTHERS THEN
|
||||
RAISE WARNING 'Test %: Invalid collection type: FAILED with error: %', total_tests, SQLERRM;
|
||||
END;
|
||||
|
||||
|
||||
-- Test 11: Section whitespaces
|
||||
total_tests := total_tests + 1;
|
||||
BEGIN
|
||||
test_result := hemar.render(
|
||||
'{"array": [1, 2, 3]}'::jsonb,
|
||||
'{{for item in array}}item{{end}}'
|
||||
);
|
||||
expected := 'itemitemitem';
|
||||
IF test_result = expected THEN
|
||||
RAISE NOTICE 'Test %: Section whitespaces: PASSED', total_tests;
|
||||
passed_tests := passed_tests + 1;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Section whitespaces: FAILED. Expected "%", got "%"', total_tests, expected, test_result;
|
||||
END IF;
|
||||
EXCEPTION WHEN OTHERS THEN
|
||||
RAISE WARNING 'Test %: Section whitespaces: FAILED with error: %', total_tests, SQLERRM;
|
||||
END;
|
||||
|
||||
-- Test 12: Section whitespaces 2
|
||||
total_tests := total_tests + 1;
|
||||
BEGIN
|
||||
test_result := hemar.render(
|
||||
'{"array": [1, 2, 3]}'::jsonb,
|
||||
'{{for item in array}}
|
||||
item
|
||||
{{end}}'
|
||||
);
|
||||
expected := ' item
|
||||
item
|
||||
item
|
||||
';
|
||||
IF test_result = expected THEN
|
||||
RAISE NOTICE 'Test %: Section whitespaces 2: PASSED', total_tests;
|
||||
passed_tests := passed_tests + 1;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Section whitespaces 2: FAILED. Expected "%", got "%"', total_tests, expected, test_result;
|
||||
END IF;
|
||||
EXCEPTION WHEN OTHERS THEN
|
||||
RAISE WARNING 'Test %: Section whitespaces 2: FAILED with error: %', total_tests, SQLERRM;
|
||||
END;
|
||||
|
||||
-- Test 13: Section whitespaces 3
|
||||
total_tests := total_tests + 1;
|
||||
BEGIN
|
||||
test_result := hemar.render(
|
||||
'{"array": [1, 2, 3]}'::jsonb,
|
||||
'{{for item in array}} item
|
||||
{{end}}'
|
||||
);
|
||||
expected := ' item
|
||||
item
|
||||
item
|
||||
';
|
||||
IF test_result = expected THEN
|
||||
RAISE NOTICE 'Test %: Section whitespaces 3: PASSED', total_tests;
|
||||
passed_tests := passed_tests + 1;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Section whitespaces 3: FAILED. Expected "%", got "%"', total_tests, expected, test_result;
|
||||
END IF;
|
||||
EXCEPTION WHEN OTHERS THEN
|
||||
RAISE WARNING 'Test %: Section whitespaces 3: FAILED with error: %', total_tests, SQLERRM;
|
||||
END;
|
||||
|
||||
-- Test 14: Section whitespaces 4
|
||||
total_tests := total_tests + 1;
|
||||
BEGIN
|
||||
test_result := hemar.render(
|
||||
'{"array": [1, 2, 3]}'::jsonb,
|
||||
'{{for item in array}}
|
||||
item {{end}}'
|
||||
);
|
||||
expected := ' item item item ';
|
||||
IF test_result = expected THEN
|
||||
RAISE NOTICE 'Test %: Section whitespaces 4: PASSED', total_tests;
|
||||
passed_tests := passed_tests + 1;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Section whitespaces 4: FAILED. Expected "%", got "%"', total_tests, expected, test_result;
|
||||
END IF;
|
||||
EXCEPTION WHEN OTHERS THEN
|
||||
RAISE WARNING 'Test %: Section whitespaces 4: FAILED with error: %', total_tests, SQLERRM;
|
||||
END;
|
||||
|
||||
-- Test 15: Section whitespaces 5
|
||||
total_tests := total_tests + 1;
|
||||
BEGIN
|
||||
test_result := hemar.render(
|
||||
'{"array": [1, 2, 3]}'::jsonb,
|
||||
'{{for item in array}}
|
||||
item
|
||||
{{end}}
|
||||
'
|
||||
);
|
||||
expected := ' item
|
||||
item
|
||||
item
|
||||
';
|
||||
IF test_result = expected THEN
|
||||
RAISE NOTICE 'Test %: Section whitespaces 5: PASSED', total_tests;
|
||||
passed_tests := passed_tests + 1;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Section whitespaces 5: FAILED. Expected "%", got "%"', total_tests, pg_temp.test_regexp_replace(expected), pg_temp.test_regexp_replace(test_result);
|
||||
END IF;
|
||||
EXCEPTION WHEN OTHERS THEN
|
||||
RAISE WARNING 'Test %: Section whitespaces 5: FAILED with error: %', total_tests, SQLERRM;
|
||||
END;
|
||||
|
||||
-- Test 16: Tabs
|
||||
total_tests := total_tests + 1;
|
||||
BEGIN
|
||||
test_result := hemar.render(
|
||||
'{"array": [1, 2, 3]}'::jsonb,
|
||||
'
|
||||
identation1
|
||||
{{for item in array}}
|
||||
identation2
|
||||
{{end}}
|
||||
identation1
|
||||
'
|
||||
);
|
||||
expected := '
|
||||
identation1
|
||||
identation2
|
||||
identation2
|
||||
identation2
|
||||
identation1
|
||||
';
|
||||
|
||||
IF test_result = expected THEN
|
||||
RAISE NOTICE 'Test %: Tabs: PASSED', total_tests;
|
||||
passed_tests := passed_tests + 1;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Tabs: FAILED. Expected "%", got "%"', total_tests, pg_temp.test_regexp_replace(expected), pg_temp.test_regexp_replace(test_result);
|
||||
END IF;
|
||||
EXCEPTION WHEN OTHERS THEN
|
||||
RAISE WARNING 'Test %: Tabs: FAILED with error: %', total_tests, SQLERRM;
|
||||
END;
|
||||
|
||||
-- Test 17: Tabs 2
|
||||
total_tests := total_tests + 1;
|
||||
BEGIN
|
||||
test_result := hemar.render(
|
||||
'{"array": [1, 2, 3]}'::jsonb,
|
||||
'
|
||||
identation1
|
||||
{{for item in array}}
|
||||
identation2
|
||||
{{end}}
|
||||
identation1
|
||||
'
|
||||
);
|
||||
expected := '
|
||||
identation1
|
||||
identation2
|
||||
identation2
|
||||
identation2
|
||||
identation1
|
||||
';
|
||||
|
||||
IF test_result = expected THEN
|
||||
RAISE NOTICE 'Test %: Tabs: PASSED', total_tests;
|
||||
passed_tests := passed_tests + 1;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Tabs: FAILED. Expected "%", got "%"', total_tests, pg_temp.test_regexp_replace(expected), pg_temp.test_regexp_replace(test_result);
|
||||
END IF;
|
||||
EXCEPTION WHEN OTHERS THEN
|
||||
RAISE WARNING 'Test %: Tabs: FAILED with error: %', total_tests, SQLERRM;
|
||||
END;
|
||||
|
||||
-- Test 18: Context
|
||||
total_tests := total_tests + 1;
|
||||
BEGIN
|
||||
test_result := hemar.render(
|
||||
'{"value": 12, "array": [1, 2, 3]}'::jsonb,
|
||||
'
|
||||
{{for item in array}}
|
||||
{{exec RETURN context::TEXT}}
|
||||
{{end}}
|
||||
'
|
||||
);
|
||||
expected := '
|
||||
';
|
||||
|
||||
IF test_result = expected THEN
|
||||
RAISE NOTICE 'Test %: Context: PASSED', total_tests;
|
||||
passed_tests := passed_tests + 1;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Context: FAILED. Expected "%", got "%"', total_tests, expected, test_result;
|
||||
END IF;
|
||||
EXCEPTION WHEN OTHERS THEN
|
||||
RAISE WARNING 'Test %: Context: FAILED with error: %', total_tests, SQLERRM;
|
||||
END;
|
||||
|
||||
-- Print summary
|
||||
IF passed_tests = total_tests THEN
|
||||
RAISE NOTICE '------------------------------------';
|
||||
RAISE NOTICE 'SUMMARY: % of % template section tests passed (100%%)',
|
||||
passed_tests, total_tests;
|
||||
RAISE NOTICE '------------------------------------';
|
||||
ELSE
|
||||
RAISE WARNING '------------------------------------';
|
||||
RAISE WARNING 'SUMMARY: % of % template section 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 % template section tests did not pass', (total_tests - passed_tests), total_tests;
|
||||
END IF;
|
||||
END $$;
|
||||
1134
package/c/hemar-legacy/test/test_template_parser.sql
Executable file
1134
package/c/hemar-legacy/test/test_template_parser.sql
Executable file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user