selected = true; return $this; } public function getCustomerName(int $customer_number): ?string { if (!$this->selected) { throw new \RuntimeException('Customer name requested before local customer selection.'); } self::$calls[] = 'name:' . $customer_number; return 'KING FOOD DANMARK A/S'; } public function getCustomerEcocomicData(?int $customer_number = null): self { if (!$this->selected) { throw new \RuntimeException('Economic customer requested before local customer selection.'); } self::$calls[] = 'economic:' . (int)$customer_number; $this->economic_customer = (object)[ 'corporateIdentificationNumber' => '12345678', ]; return $this; } } } namespace { require_once WD . '/modules/email/helpers/email_template.php'; require_once WD . '/modules/email/templates/email_template_new_customer.php'; function assert_true(bool $condition, string $message): void { if (!$condition) { throw new \RuntimeException($message); } } function cleanup_buffers_to(int $base_level): string { $output = ''; while (ob_get_level() > $base_level) { $output .= (string)ob_get_clean(); } return $output; } $base_level = ob_get_level(); ob_start(); try { $html = (new \email\templates\email_template_new_customer( 12345678, 'https://truckwash.io/auth/password-reset/mock-token', ))->generate_html(); $leaked_output = cleanup_buffers_to($base_level); assert_true($leaked_output === '', 'Template generation must not leak buffered HTML output.'); assert_true( str_contains($html, 'Tak for din registrering af KING FOOD DANMARK A/S (12345678) som kunde hos Truck Wash.'), 'Template must render the selected customer name and CVR in the welcome intro.' ); assert_true( \objects\users_o::$calls === ['select:12345678', 'name:12345678', 'economic:12345678'], 'Template must select the local customer before reading customer details.' ); } catch (\Throwable $exception) { $leaked_output = cleanup_buffers_to($base_level); fwrite(STDERR, $leaked_output); fwrite(STDERR, $exception->getMessage() . PHP_EOL); exit(1); } echo "\033[32m[PASS]\033[0m New customer email template renders without leaked output.\n"; exit(0); }