# HK Logistics — QA report

Last run: 2026-10-07 · Node.js v24.16.0 · Windows 10 (local, `NODE_ENV=development`, `MAIL_TRANSPORT=json`)

Only tests that were actually executed are marked PASS. Anything not run is listed under "Not tested".

## 1. Summary

| Area | How it was tested | Result |
|---|---|---|
| Automated suite (`npm test`) | 33 node:test cases: pages, SEO, schema, sitemap/robots, redirects, 404, security headers, CSP, sensitive files, HTTP methods, XSS, CSRF, validation, header injection, SQL/NoSQL/command injection strings, honeypot, timing trap, rate limiting + XFF spoofing, real SMTP delivery (local test SMTP server with AUTH + TLS), SMTP failure handling, production mode | **33/33 PASS** |
| Dependency audit (`npm audit --omit=dev`) | npm registry advisories | **0 vulnerabilities** |
| Route smoke test | `curl` against the running server: 15 pages + sitemap + robots → 200; unknown page and `/.env` → 404 | **PASS** |
| Security headers (live) | `curl -I /`: CSP, X-Frame-Options DENY, nosniff, Referrer-Policy, Permissions-Policy, no X-Powered-By. HSTS checked in the production-mode test | **PASS** |
| Customer journey (`node scripts/qa-journey.js`) | Real Chrome: first impression, CTA above the fold, keyboard menu, route card → quote pre-fill, empty/invalid email/invalid phone, valid submission → thank-you with reference, service CTA pre-selects vehicle, mobile sticky bar, mobile menu, no horizontal scroll, 16px inputs | **22/22 PASS** |
| Browser + responsive (`npm run qa:browser`) | Every page at 1920×1080, 1440×900, 1366×768, 1024×768, 768×1024, 430×932, 390×844, 375×812; console errors, CSP violations, failed requests, overflow, broken images, missing alt, heading order | See section 3 |
| BigTrans / Bhavin cleanup | `grep -ri "bigtrans\|bhavin\|mukesoft"` over the project (excluding `node_modules`), plus the rendered-output test | **PASS**: the only match is the banned-words regex in `tests/app.test.js` |
| Visual review | Screenshots at 1440×900 and 390×844 (home, quote) | 1 defect found and fixed (section 2) |

## 2. Bugs found and fixed in this pass

| # | Issue | Root cause | Fix | Retest |
|---|---|---|---|---|
| 1 | Browser QA reported a console error on `/missing-page` at every viewport | The page is intentionally a 404. The script already ignored the 404 *response* but not the browser's matching "Failed to load resource" console message | `scripts/qa-browser.js` now ignores that one message on `/missing-page` only | Chrome: 0 issues at all 8 viewports |
| 2 | Home hero "Need a truck?" card: the dashed route line ran through the "Delivery location" label text | `.route-card__line` spans the whole fields block and painted over the (unpositioned) labels | Labels inside `.route-card` are now positioned above the line with a white background (`public/css/main.css`) | Screenshot verified; `npm test` re-run |
| 3 | Firefox, 390 and 375 px: `/services` scrolled horizontally (page width 394 px) | `.btn` is `white-space: nowrap` and `.split` used an implicit `auto` grid column, so the long button "See the equipment behind these services" made the column wider than the screen. Firefox's text measured slightly wider than Chrome's | `.split` columns now use `minmax(0, 1fr)`; buttons are capped at `max-width: 100%` and can wrap below 600 px | Firefox + Chrome, all pages × 8 viewports: 0 issues; `npm test` 33/33; journey 22/22 |
| 4 | Client feedback: banner photos barely visible | Hero/page-hero overlays were 85–97% opaque navy | Overlays lightened (desktop and mobile); soft text-shadow keeps white text readable | Screenshots at 1290 and 390 px; Chrome + Firefox all pages × 8 viewports: 0 issues |
| 5 | Client feedback: CTA band and footer looked the same colour | Both used `--navy-950` | CTA band now uses the logo blue gradient (`#005f97` → `#0072b5` → `#2e3192`); eyebrow lightened for contrast | Screenshot verified |
| 6 | Desktop: floating WhatsApp button (shown once a number was added) covered the footer "Sitemap" link | Fixed button at bottom right, no reserved space | Footer bottom row gets extra bottom padding at ≥760 px | Screenshot verified |
| 7 | Browser QA flagged aborted Google Fonts requests after leaving `/contact` | The Google Maps iframe loads Roboto; the harness navigated away before it finished (not a site bug) | `qa-browser.js` ignores aborted third-party requests and the matching font message | Firefox `/contact` → `/privacy-policy`: 0 issues |
| 8 | Two tests failed after real NAP was added | Tests asserted that phone/LocalBusiness were absent while unconfirmed | Tests now assert the confirmed phone, postcode and LocalBusiness, and that legal name/GSTIN stay unpublished | `npm test` 33/33 |

## 3. Browser results

| Browser | Viewports | Result |
|---|---|---|
| Chrome (installed) | 8/8 | **0 issues** (re-run after fix #3) |
| Edge (installed) | 8/8 | **0 issues** (run before fix #3; Edge uses the same engine as Chrome, which was re-run after the fix) |
| Firefox (installed) | 8/8 | **0 issues** after fix #3 (first run: 2 overflow issues on `/services` at 390 and 375 px) |
| Safari | — | Not tested (no macOS/iOS device available) |

## 4. Not tested / blocked on client information

These can't be completed without real data from HK Logistics. Fill them in `src/config/site.js`. Until then, development mode shows yellow "to be confirmed" placeholders and production mode hides those elements.

1. Registered legal name
2. GSTIN
3. Working days for office hours (times are confirmed)

Confirmed by HK Logistics on 2026-10-07 and now live in the header, footer, contact page, Mumbai/Network pages, map and LocalBusiness schema:

- Phone: +91 98925 59097. WhatsApp uses the same number; change `contact.whatsapp` if WhatsApp runs on a different number.
- Email: sales@hklogistics.co.in
- Office hours: 10:00 am – 7:00 pm (days not yet specified)
- Address: B-408, Kamala Ashish No. 3, Mahavir Nagar, Kandivali West, Mumbai 400067

Also pending:

- **Real email delivery:** configured on 2026-10-12 with Gmail SMTP (prerana.mukesoft@gmail.com, App Password, port 465 TLS). Enquiries go to prerana@mukesoft.in, and the visitor gets an automatic thank-you. A live test (reference HK261012LKFR) was accepted by Gmail for both messages. Confirm arrival in both inboxes, and switch `CONTACT_EMAIL` to the HK Logistics mailbox before launch.
- **Production domain**: probably `https://www.hklogistics.co.in`, going by the email domain (not yet confirmed). Set `APP_URL`, then run `npm run build:seo` to regenerate `sitemap.xml`/`robots.txt`.
- **Core Web Vitals on the live host**: run PageSpeed Insights after deployment. Locally, images are AVIF/WebP/JPEG with `srcset`, lazy loading below the fold, a self-hosted font, minified CSS/JS and compression.
- **PTL, location pages and blog**: not built on purpose (see `docs/SEO-KEYWORD-MAP.md`) until HK Logistics confirms those services or locations.

## 5. Client-perspective review (2026-10-07)

Reviewed as a Mumbai business owner looking for a transporter: home, services, quote, thank-you, Mumbai and contact pages on desktop (1290 px) and mobile (375 px).

| Question | Finding | Change |
|---|---|---|
| What does HK Logistics do, and where? | Clear: the H1, intro and service cards answer this above the fold | None |
| Can I reach a person quickly? | On desktop the phone number was only in the small top bar | Hero now says "Prefer to talk? Call +91 98925 59097 or WhatsApp us" |
| Is the language easy to follow? | Industry and internal terms: "focal point" (10 places), "Vehicle Engagement & Information Checklist", "SOP", "lane" | Rewritten as "single point of contact", "we check every vehicle: papers, condition and driver", "documented safety procedures" and "route". "Lane" is kept only for dedicated-contract routes, where buyers use the word themselves |
| Does the hero repeat itself? | The trust point "A single point of contact" repeated the intro sentence | Trust points are now: branches & agents across India · vehicles checked before loading · documented safety procedures |
| After submitting, what next? | The thank-you page offered only the phone | Adds WhatsApp and asks the visitor to keep their reference number |
| Is the quote form easy? | 5 required fields; everything else optional; call/WhatsApp beside it; "What happens next" shown | None |
| Do images load? | Yes. Two images looked blank in a fast full-page screenshot; this was lazy-load timing, confirmed by a slower scroll | None |

Suggestions that need HK Logistics input (not invented):

- **Response time:** for example "we reply within 2 working hours". This is the strongest trust signal for a quote form, but only HK Logistics can commit to it.
- **Client logos or testimonials,** with permission from the clients concerned.
- **Real photographs** of HK Logistics vehicles, the office or the team. Current photos are licensed stock (see `/image-credits`).
- **Working days** for office hours.

## 6. Mail delivery fix (2026-10-12)

| Issue | Root cause | Fix | Retest |
|---|---|---|---|
| Real contact-form submissions sent no email (log: `enquiry.spam_blocked`, reason `honeypot`) | The hidden spam-trap field was named `website`. Browser autofill and password managers fill fields with that name, so real visitors looked like bots and were discarded silently | Trap renamed to `hk_trap_x7` with password-manager ignore attributes. A filled trap no longer discards the enquiry: it is delivered with a `[Possible spam]` subject, and the visitor still gets the thank-you. The "too fast" timing trap is unchanged | Real Chrome submission of `/quote`, reference HK2610123TT6: `enquiry.sent` (from prerana.mukesoft@gmail.com to prerana@mukesoft.in) and `enquiry.acknowledged` (thank-you to the customer). `npm test` 33/33 |
