test: exec
This commit is contained in:
343
package/c/hemar/test/test_render_exec.sql
Executable file
343
package/c/hemar/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 $$;
|
||||
Reference in New Issue
Block a user