Files
erv-clientright/hotels/qa-report-erv-hotels-form-2026-03-13.md

366 lines
9.1 KiB
Markdown
Raw Normal View History

2026-03-13 10:42:01 +03:00
# QA report: ERV Hotels claim form
Date: 2026-03-13
URL: https://erv.clientright.ru/hotels/
Scope: manual code-assisted QA review of masks, validation, policy check flow, SMS flow, step logic, and submission flow.
## Executive summary
The form is generally wired up and backend endpoints respond, but there are several important frontend issues.
Most important findings:
1. **Critical:** form submission appears to bypass real SMS-confirmation gating.
2. **High:** `Tab` is blocked on the first input field.
3. **Medium:** jQuery is loaded twice.
4. **Medium:** policy-number normalization is incomplete and fragile.
5. **Medium:** phone validation logic is strict and should be regression-tested with paste scenarios.
---
## Confirmed observations
### Backend policy check responds correctly
Endpoint: `database.php`
Tested cases:
- empty payload → returns `{"success":"false","message":"Номер полиса не указан"}`
- invalid policy number → returns `{"success":"false","message":"Полис не найден"}`
This part looks alive and generally sane.
---
## Findings
## 1) CRITICAL — submit flow appears to bypass actual SMS confirmation
### Why this is critical
In the submit handler, the code opens the SMS modal but still proceeds directly to `submit.php` because the condition is hardcoded as `if(1)`.
### Relevant code pattern
```js
$('.form.active form').submit(function(e){
if(!validate_step(index)){ e.preventDefault(); } else {
e.preventDefault();
$('button[type="submit"]').attr("disabled", true);
if(1) {
$.fancybox.open({ src: '#confirm_sms', type: 'inline' });
...
$.ajax({
url: 'submit.php',
method: 'post',
...
});
```
### Risk
The form may be submitted even if SMS code was not actually confirmed.
### Expected behavior
Submission to `submit.php` should only happen after successful SMS verification.
### Recommended fix
Replace the hardcoded `if(1)` with a real condition based on verified phone state, for example:
- a dedicated boolean like `smsVerified === true`
- or a validated marker on the phone field after successful verification
- and prevent submit entirely until SMS verification succeeds
### Suggested implementation direction
- set explicit state after successful `sms-verify.php?action=verify`
- on form submit, check that state
- only then build `FormData` and call `submit.php`
---
## 2) HIGH — Tab key is blocked on the first input
### Relevant code
```js
document.querySelector('input').addEventListener('keydown', function (e) {
if (e.which == 9) {
e.preventDefault();
}
});
```
### Problem
This blocks `Tab` on the first input field.
### User impact
- keyboard navigation is broken
- accessibility is degraded
- desktop UX becomes weird and frustrating
### Expected behavior
`Tab` should move focus to the next field normally.
### Recommended fix
Remove this listener entirely unless there is a very specific documented reason.
---
## 3) MEDIUM — jQuery is included twice
### Current page includes
```html
<script src="https://code.jquery.com/jquery-3.6.3.min.js"></script>
<script src="libs/jquery/jquery-3.4.1.min.js"></script>
```
### Risk
- plugin conflicts
- unexpected behavior depending on initialization order
- harder debugging
### Expected behavior
Only one jQuery version should be loaded.
### Recommended fix
Keep a single version and verify plugins against it.
---
## 4) MEDIUM — policy number normalization is incomplete / fragile
### Current behavior
The code only explicitly normalizes Cyrillic:
- `Е``E`
- `А``A`
### Relevant logic
```js
if(police_number.slice(0,1)=="Е"){
police_number=police_number.replace(/Е/g, 'E');
}
if(police_number.slice(0,1)=="А"){
police_number=police_number.replace(/А/g, 'A');
}
```
### Risk
User input may still fail in edge cases:
- pasted values with spaces
- other Cyrillic lookalikes
- lowercase input
- mixed formatting
### Expected behavior
Policy number should be normalized consistently before validation / sending.
### Recommended fix
Before submit/check:
- `trim()`
- uppercase
- replace common Cyrillic lookalikes with Latin equivalents
- normalize spaces
- possibly normalize dash types
---
## 5) MEDIUM — applicant phone validation needs regression testing for paste/input scenarios
### Current logic
Applicant phone (`.js-phone-mask`) is normalized to Russian 10-digit local format and validated strictly.
### Relevant behavior
- strips `+7` / `8`
- keeps only 10 digits
- formats as `999 999-99-99`
### Potential issue areas
- paste of `+7 912 345-67-89`
- paste of `8 (912) 345-67-89`
- typing starting with `8` or `7`
- editing in the middle of the string
- overlong paste values
### Expected behavior
All common Russian user inputs should normalize cleanly and predictably.
### Recommended regression tests
- `9123456789`
- `8 912 345-67-89`
- `+7 912 345-67-89`
- `89123456789`
- `79123456789`
- paste with brackets/spaces/dashes
---
## 6) MEDIUM — hotel phone field uses separate validation logic and should be tested independently
### Current logic
Hotel phone (`.js-place-phone`) allows 10 to 15 digits.
### Risk
International phone scenarios may behave inconsistently:
- with `+`
- with spaces
- with brackets
- with short local numbers
### Expected behavior
Visible, predictable validation for international hotel contact numbers.
### Recommended regression tests
- `+49 30 12345678`
- `+1 (555) 123-4567`
- `0049...`
- short invalid numbers
- numbers over 15 digits
---
## 7) MEDIUM — description field has hard limits; UX should be checked
### Current logic
Description requires:
- minimum 50 characters
- maximum 2000 characters
### Risk
Users may be blocked without clear enough guidance.
### Expected behavior
- clear live or submit-time feedback
- understandable character requirement
### Recommended improvement
Consider a live character counter or helper text.
---
## 8) MEDIUM — file requirements for selected hotel risks should be regression-tested in browser
### Current logic
On `hotel-2`:
- at least one risk checkbox must be selected
- if a risk is selected, a supporting file is required
- unchecking should clear file state
### Why this matters
This logic is easy to break in real browser interaction.
### Recommended tests
- select risk without file → should block next/submit
- add file → should pass
- uncheck risk after upload → file state should reset cleanly
- re-check and re-upload → should still work
---
## 9) LOW — duplicated / potentially confusing SMS UI flow
### Observed behavior in code
The SMS modal and button state handling are fairly complex:
- cooldown timer
- resend behavior
- modal warnings
- direct phone field locking after success
This may be fine, but it is sensitive to regressions.
### Recommendation
Simplify state handling where possible and ensure there is a single source of truth:
- not verified
- sending
- code sent
- verified
---
## Suggested fixes by priority
## Priority P1
1. Fix submit flow so `submit.php` is called only after successful SMS verification.
2. Remove the `Tab` blocker on the first input.
## Priority P2
3. Remove duplicate jQuery include.
4. Harden policy number normalization.
## Priority P3
5. Regression-test applicant phone paste/typing behavior.
6. Regression-test hotel phone international input behavior.
7. Regression-test file upload behavior on `hotel-2`.
8. Improve UX around description-length validation.
---
## Suggested manual QA checklist for Cursor / further automation
### Policy check
- empty policy number
- invalid policy number
- valid-format policy number with slash
- Cyrillic first letter (`А`, `Е`)
- paste with spaces
### Date of birth / representative block
- adult DOB
- minor DOB
- representative block shown only for minors
- representative fields disabled/hidden correctly otherwise
### Applicant phone
- direct typing: `9123456789`
- paste: `+7 912 345-67-89`
- paste: `8 (912) 345-67-89`
- reject incomplete values
- reject non-digit garbage cleanly
### Hotel phone
- accept international-looking values
- reject too short values
- reject too long values
### Email
- valid email
- invalid email without domain
- invalid email without `@`
- trim spaces around value
### Files
- required file missing for selected risk
- file upload passes when attached
- file reset after uncheck
- re-upload after returning back in steps
### Description
- under 50 chars → error
- exactly 50 chars → pass
- over 2000 chars → error
### Final submit
- no agreement checkbox → block
- with agreement → allow
- ensure SMS verified state is mandatory before actual submit
---
## Important note
This report is based on:
- live endpoint checks
- frontend source review
- flow analysis of production JS
A full browser-driven E2E pass is still recommended after fixes, especially for:
- file uploads
- modal transitions
- SMS flow
- step navigation
---
## Best next step for Cursor
Ask Cursor to:
1. inspect `common.js`
2. fix the submit/SMS gating bug first
3. remove the `Tab` blocker
4. remove duplicate jQuery include
5. add robust input normalization for policy/phone
6. produce a small browser regression checklist after patching