renderLayout('cooperation-contract'); $seals = array_values(array_filter($frames, fn ($frame) => $frame['class'] === 'contract-signatures__blank')); $handwriting = array_values(array_filter($frames, fn ($frame) => $frame['class'] === 'contract-signatures__handwriting')); $this->assertCount(2, $seals); $this->assertCount(2, $handwriting); $this->assertGreaterThan(1, $pageCount); foreach ($seals as $index => $seal) { $this->assertGreaterThanOrEqual(159, $seal['width']); $this->assertGreaterThanOrEqual(159, $seal['height']); $this->assertSame($pageCount, $seal['page']); $this->assertGreaterThanOrEqual(75, $handwriting[$index]['height']); $this->assertGreaterThanOrEqual($seal['y'] + $seal['height'], $handwriting[$index]['y']); } $this->assertLessThanOrEqual($seals[1]['x'], $seals[0]['x'] + $seals[0]['width']); foreach ($frames as $frame) { $this->assertSame($pageCount, $frame['page'], 'Both parties and their dates must stay on the signature page.'); $this->assertLessThan(806, $frame['y'] + $frame['height']); } } public function test_other_agreements_keep_full_size_seal_spaces_and_dates_together(): void { foreach (['account-proof', 'account-change', 'entity-change', 'shared-contract', 'authorization'] as $type) { [$frames, $pageCount] = $this->renderLayout($type); $seals = array_values(array_filter($frames, fn ($frame) => $frame['class'] === 'sign-grid__blank')); $this->assertCount(in_array($type, ['entity-change', 'authorization'], true) ? 2 : 1, $seals); foreach ($seals as $seal) { $this->assertGreaterThanOrEqual(159, $seal['width'], $type); $this->assertGreaterThanOrEqual(159, $seal['height'], $type); } foreach ($frames as $frame) { $this->assertSame($pageCount, $frame['page'], "$type signature spaces and dates must stay together."); $this->assertLessThan(806, $frame['y'] + $frame['height'], $type); } } } private function renderLayout(string $type): array { $payload = [ 'company_full_name' => '示例甲方公司', 'signature_date' => '2026-10-11', 'account_proof_effective_date' => '2026-10-11', 'account_proof_account_name' => '示例合作公司', 'account_proof_bank_name' => '示例银行', 'account_proof_bank_account' => '0000000000000000', 'account_change_date' => '2026-10-11', 'old_account_name' => '原收款人', 'old_account_number' => '0000000000000000', 'old_account_stop_date' => '2026-10-11', 'new_account_effective_date' => '2026-10-11', 'new_account_name' => '新收款人', 'new_bank_name' => '示例银行', 'new_bank_account' => '0000000000000000', 'former_company_name' => '示例原公司', 'former_legal_representative' => '原法人', 'entity_change_date' => '2026-10-11', 'changed_company_name' => '示例新公司', 'changed_company_start_date' => '2026-10-11', 'secondary_operator_name' => '新法人', 'contract_partner_name' => '示例合作公司', 'shared_courier_names' => ['示例快递'], 'cooperation_party_a_name' => '示例甲方公司', 'cooperation_party_a_phone' => '00000000000', 'cooperation_party_b_name' => '示例乙方公司', 'cooperation_party_b_phone' => '00000000000', 'cooperation_start_date' => '2026-10-11', 'cooperation_end_date' => '2027-10-10', 'principal_name' => '示例委托方', 'principal_id_number' => 'EXAMPLE-ID', 'trustee_name' => '示例受托方', 'trustee_id_number' => 'EXAMPLE-ID', 'authorization_items' => ['1', '2', '3', '4'], 'bill_counterparty' => '示例对账方', 'loan_counterparty' => '示例借支方', 'payment_counterparty' => '示例付款方', 'authorization_start_date' => '2026-10-11', 'authorization_end_date' => '2027-10-10', ]; $signature = new CourierAgreementSignature([ 'business_no' => 'AGR-LAYOUT-TEST', 'template_code' => CourierAgreementSignature::DOCUMENTS[$type]['code'], 'document_type' => $type, 'payload' => $payload, ]); $frames = []; $pdf = app('dompdf.wrapper'); $this->app->instance('dompdf.wrapper', $pdf); $pdf->getDomPDF()->setCallbacks([[ 'event' => 'end_frame', 'f' => function ($frame) use (&$frames, $pdf): void { $node = $frame->get_node(); if (! $node instanceof DOMElement || ! preg_match('/(?:blank|handwriting|sign-grid__line|contract-signatures__title|contract-signatures__line)/', $node->getAttribute('class'))) { return; } $position = $frame->get_position(); $frames[] = [ 'class' => $node->getAttribute('class'), 'page' => $pdf->getDomPDF()->getCanvas()->get_page_number(), 'x' => $position['x'], 'y' => $position['y'], 'width' => $frame->get_margin_width(), 'height' => $frame->get_margin_height(), ]; }, ]]); app(CourierAgreementPdf::class)->render($signature); $this->app->forgetInstance('dompdf.wrapper'); return [$frames, $pdf->getDomPDF()->getCanvas()->get_page_count()]; } }