Video Club Rental
Level: Advanced 60–90 minConcepts: Business LogicStateValidationMockingEdge Cases
Solutions: C# | TypeScript | Python
Build the backend for a video rental club. This kata has a rich domain with users, rentals, wishlists, pricing tiers, and loyalty mechanics. Based on Jason Gorman’s classic workshop exercise.
Requirements
Users
- Users have a name, email, and age
- Users must be 18 or older to register
- A welcome email is sent upon successful registration
- Admin users can create and delete other users
Rentals
- Base rental charge: £2.50 per title for 15 days
- Tiered pricing for simultaneous rentals:
| Simultaneous Rentals | Price per Title |
|---|---|
| 1st title | £2.50 |
| 2nd title | £2.25 |
| 3rd title | £1.75 |
- On-time return (within 15 days): user earns 2 priority points
- Late return (after 15 days): user loses 2 priority points, receives a late alert, and cannot rent until the overdue title is returned
Priority Access
- Users with 5+ priority points get priority access to new releases
- Priority points cannot go below 0
Wishlists
- Users can add titles to a wishlist (case-insensitive matching)
- When a wished title becomes available, the user is notified
- A waiting list determines notification order
Donations
- Users can donate videos to the library
- Donors receive 10 loyalty points per donated title
- If the title already exists, the copy count increases
- If the title is new, a library entry is created
- Users on the wishlist for a donated title are notified
Library Catalog
Each title tracks:
- Title name, director, release year
- Total copies and available copies
Admin Features
- Admins can create and send newsletters to all users
Test Cases
| Scenario | Expected |
|---|---|
| Register user aged 18 | Success, welcome email sent |
| Register user aged 17 | Error: too young |
| Rent 1 title | Charged £2.50 |
| Rent 2 titles | Charged £2.50 + £2.25 = £4.75 |
| Rent 3 titles | Charged £2.50 + £2.25 + £1.75 = £6.50 |
| Return on time | +2 priority points |
| Return late | -2 priority points, late alert, rental blocked |
| Rent while overdue | Error: has overdue rental |
| Priority access, 4 points | Denied |
| Priority access, 5 points | Granted |
| Wishlist notification | User notified when title available |
| Donate new title | Library entry created, +10 loyalty |
| Donate existing title | Copy count +1, +10 loyalty |
| Donate wishlisted title | Wishlist users notified |
| Admin creates user | Success |
| Non-admin creates user | Error: unauthorized |
Bonus
- Add a wrong return detection — user returns a title they didn’t rent. Send a warning email.
- Add rental history — users can view their past rentals
- Add recommendations — suggest titles based on rental history and genre matching
- Add membership tiers — Bronze, Silver, Gold based on loyalty points, with increasing discounts
Hint
Use test doubles for email sending and notifications — define interfaces and mock them. Start with user registration and age validation. Then basic rental pricing. Layer on priority points, then wishlists. Each concern is testable independently before composing them together.
Reference Walkthrough
Full C#, TypeScript, and Python implementations live at tddbuddy-reference-katas/video-club-rental. Twenty-four scenarios across registration, pricing, returns, priority access, donations, and wishlist — shared across all three languages — with a VideoClub aggregate, Money and Age value types, Clock and Notifier as injected collaborators, and three fluent builders (UserBuilder, TitleBuilder, VideoClubBuilder) in the test projects.
- C# (.NET 8, xUnit, FluentAssertions) — walkthrough
- TypeScript (Node 20, Vitest, strict types) — walkthrough
- Python (3.11, pytest, dataclasses, Decimal) — walkthrough
This kata ships in Agent Full-Bake mode: one commit per language with the full domain design landing together. The walkthroughs read as design rationale — why Money is a type, why Clock is injected, why the builder returns a tuple — not a step-by-step commit tour. See the repo’s Gears section for when middle gear is the right call.