Atul1997's picture
Upload 7 files
dbede45 verified

A newer version of the Gradio SDK is available: 6.11.0

Upgrade

Hotel Search App β€” QA Report

Scope of Testing

This QA report validates the Hotel Search App against the Architect's plan (plan.md) and the Builder's summary (build.md). Testing covers schema adherence, input validation, edge cases, adversarial inputs, security, and interface contract enforcement.


1. Plan vs. Build Compliance

Plan Requirement Implemented? Notes
Free-form natural language input Yes Single Gradio Textbox, 5-line height
SerpApi google_hotels engine Yes Correct engine parameter in API call
Date extraction (5+ formats) Yes MM/DD/YYYY, YYYY-MM-DD, Month Day Year, Month D-D Year, single dates
Price range extraction Yes Range, upper-bound, lower-bound patterns
Travel-agency link exclusion Yes 20+ agency domains in blocklist
Top 15 results Yes properties[:15] enforced
Direct hotel website links Yes get_hotel_link with fallback to Google search
Hugging Face deployment ready Yes Single app.py, requirements.txt, README metadata
API key via env variable or UI Yes Checks UI field first, then SERPAPI_KEY / SERPAPI_API_KEY
Graceful error handling Yes Try/except wraps full pipeline; friendly HTML messages

Verdict: All plan elements are implemented. No missing features.


2. Input Validation Tests

2.1 Empty Input

Test Input Expected Result
Blank string "" Error prompt PASS β€” "Please enter a hotel description to search."
Whitespace only " " Error prompt PASS β€” Same message

2.2 Missing API Key

Test Input Key Expected Result
No key anywhere Any text "" (no env var) Key prompt PASS β€” "SerpApi key required"

2.3 Adversarial / Gibberish Input

Test Input Expected Result
Random characters "asdfghjkl 12345" No crash; search attempt or no-results PASS β€” Falls back to raw text as query
SQL injection attempt "'; DROP TABLE hotels; --" No crash; input treated as text PASS β€” Regex simply won't match; text sent to SerpApi as query
XSS attempt "<script>alert('xss')</script>" No script execution PASS β€” Gradio HTML component sanitizes output
Extremely long input 5000-character string No crash PASS β€” First 120 chars used as query if no location found

3. Date Parsing Edge Cases

Input Fragment Extracted Check-in Extracted Check-out Result
"March 15 to March 18, 2026" 2026-03-15 2026-03-18 PASS
"3/15/2026 - 3/18/2026" 2026-03-15 2026-03-18 PASS
"2026-03-15 to 2026-03-18" 2026-03-15 2026-03-18 PASS
"March 15, 2026" (single date) 2026-03-15 2026-03-16 PASS β€” defaults to 1 night
No dates provided Tomorrow Tomorrow + 1 PASS β€” sensible defaults
Past date "Jan 1, 2020" Adjusted to tomorrow Tomorrow + 1 PASS β€” past-date guard works
"March 15-18, 2026" (range) 2026-03-15 2026-03-18 PASS β€” compact range regex

4. Price Parsing Edge Cases

Input Fragment min_price max_price Result
"$100 to $200" 100 200 PASS
"under $200" None 200 PASS
"budget of $150" None 150 PASS
"above $100" 100 None PASS
"at least $50" 50 None PASS
No price mentioned None None PASS β€” no price filter applied

5. Location Extraction Tests

Input Fragment Extracted Location Result
"hotel in Austin, TX" Austin, TX PASS
"near Times Square" Times Square PASS
"hotels in San Francisco" San Francisco PASS
"close to downtown Nashville" downtown Nashville PASS
No location keyword Falls back to first sentence PASS β€” graceful fallback

6. Travel-Agency Link Filtering

Verified that the blocklist covers: Expedia, Booking.com, Hotels.com, Trivago, Kayak, Priceline, Orbitz, Travelocity, Agoda, Trip.com, Hotwire, CheapTickets, LastMinute, eDreams, Opodo, Wotif, Zuji, MakeMyTrip, Goibibo, Yatra.

  • If all results happen to be travel-agency links, the filter relaxes (threshold < 3) to avoid showing zero results. This is a pragmatic trade-off documented in build.md.

7. Security Review

Check Status Notes
No hard-coded API keys PASS Key from UI (masked) or env var only
No eval() or exec() on user input PASS Input only used in regex and as SerpApi query param
No shell command execution PASS No subprocess or os.system calls
External links use rel='noopener noreferrer' PASS Prevents reverse tabnapping
Stack traces hidden from user PASS Generic error message with exception text only
Gradio type="password" for API key PASS Input is masked in UI

8. Interface Contract Verification

  • Parser output dict matches the JSON schema defined in plan.md.
  • SerpApi response is consumed via results.get("properties", []) with safe .get() access throughout.
  • HTML output is well-formed; tested with missing fields (no image, no rating, no amenities).

9. Findings & Recommendations

Issues Found (non-blocking)

  1. Relative date phrases like "next weekend" or "this Friday" are not parsed. The app defaults to tomorrow, which is acceptable but could be improved.
  2. Feature matching against results is not performed post-search. The required/desired/avoid features are extracted but only influence the search query indirectly. SerpApi handles the location and price filtering, but amenity-based re-ranking is not implemented.
  3. No automated test suite. Manual tests pass but a pytest suite would strengthen CI/CD.

Recommendations

  • Add a lightweight NLP layer (or LLM call) for better feature classification and relative date parsing in a future version.
  • Add unit tests for parse_user_input covering the edge cases above.
  • Consider rate-limiting or caching SerpApi calls to avoid quota exhaustion during heavy use.