2026-01-17 18:32:29 +05:30
|
|
|
//! Test helper for Pugz engine
|
|
|
|
|
//! Provides common utilities for template testing
|
|
|
|
|
|
|
|
|
|
const std = @import("std");
|
|
|
|
|
const pugz = @import("pugz");
|
|
|
|
|
|
2026-01-24 23:53:19 +05:30
|
|
|
/// Normalizes HTML by removing indentation/formatting whitespace.
|
|
|
|
|
/// This allows comparing pretty vs non-pretty output.
|
|
|
|
|
fn normalizeHtml(allocator: std.mem.Allocator, html: []const u8) ![]const u8 {
|
|
|
|
|
var result = std.ArrayListUnmanaged(u8){};
|
|
|
|
|
var i: usize = 0;
|
|
|
|
|
var in_tag = false;
|
|
|
|
|
var last_was_space = false;
|
|
|
|
|
|
|
|
|
|
while (i < html.len) {
|
|
|
|
|
const c = html[i];
|
|
|
|
|
|
|
|
|
|
if (c == '<') {
|
2026-01-25 00:06:55 +05:30
|
|
|
// Strip trailing whitespace before tags
|
|
|
|
|
while (result.items.len > 0 and (result.items[result.items.len - 1] == ' ' or result.items[result.items.len - 1] == '\t')) {
|
|
|
|
|
_ = result.pop();
|
|
|
|
|
}
|
2026-01-24 23:53:19 +05:30
|
|
|
in_tag = true;
|
|
|
|
|
last_was_space = false;
|
|
|
|
|
try result.append(allocator, c);
|
|
|
|
|
} else if (c == '>') {
|
|
|
|
|
in_tag = false;
|
|
|
|
|
last_was_space = false;
|
|
|
|
|
try result.append(allocator, c);
|
2026-01-25 00:06:55 +05:30
|
|
|
} else if (c == '\n' or c == '\r' or c == ' ' or c == '\t') {
|
|
|
|
|
// Treat all whitespace (including newlines) uniformly
|
2026-01-24 23:53:19 +05:30
|
|
|
if (in_tag) {
|
|
|
|
|
// Preserve single space in tags for attribute separation
|
|
|
|
|
if (!last_was_space) {
|
|
|
|
|
try result.append(allocator, ' ');
|
|
|
|
|
last_was_space = true;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// Outside tags: skip leading whitespace after >
|
|
|
|
|
if (result.items.len > 0 and result.items[result.items.len - 1] != '>') {
|
|
|
|
|
if (!last_was_space) {
|
|
|
|
|
try result.append(allocator, ' ');
|
|
|
|
|
last_was_space = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
i += 1;
|
|
|
|
|
continue;
|
|
|
|
|
} else {
|
|
|
|
|
last_was_space = false;
|
|
|
|
|
try result.append(allocator, c);
|
|
|
|
|
}
|
|
|
|
|
i += 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result.toOwnedSlice(allocator);
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-17 18:32:29 +05:30
|
|
|
/// Expects the template to produce the expected output when rendered with the given data.
|
|
|
|
|
/// Uses arena allocator for automatic cleanup.
|
2026-01-24 23:53:19 +05:30
|
|
|
/// Normalizes whitespace/formatting so pretty-print differences don't cause failures.
|
2026-01-17 18:32:29 +05:30
|
|
|
pub fn expectOutput(template: []const u8, data: anytype, expected: []const u8) !void {
|
|
|
|
|
var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
|
|
|
|
|
defer arena.deinit();
|
|
|
|
|
const allocator = arena.allocator();
|
|
|
|
|
|
2026-01-24 23:53:19 +05:30
|
|
|
const raw_result = try pugz.renderTemplate(allocator, template, data);
|
2026-01-17 18:32:29 +05:30
|
|
|
const result = std.mem.trimRight(u8, raw_result, "\n");
|
2026-01-24 23:53:19 +05:30
|
|
|
const expected_trimmed = std.mem.trimRight(u8, expected, "\n");
|
|
|
|
|
|
|
|
|
|
// Normalize both for comparison (ignores pretty-print differences)
|
|
|
|
|
const norm_result = try normalizeHtml(allocator, result);
|
|
|
|
|
const norm_expected = try normalizeHtml(allocator, expected_trimmed);
|
2026-01-17 18:32:29 +05:30
|
|
|
|
2026-01-24 23:53:19 +05:30
|
|
|
try std.testing.expectEqualStrings(norm_expected, norm_result);
|
2026-01-17 18:32:29 +05:30
|
|
|
}
|