Testing Strategy
Relevant source files
The following files were used as context for generating this wiki page:
- app/Services/TemplateService.php
- phpunit.xml
- resources/views/dashboard/templates.blade.php
- resources/views/welcome.blade.php
- test_services.php
- tests/Unit/Config/PolarConfigTest.php
- tests/Unit/Services/CategoryServiceTest.php
- tests/Unit/Services/EmbeddedSignupServicePropertyTest.php
- tests/Unit/Services/OrderServicePropertyTest.php
- tests/Unit/Services/PaymentServicePropertyTest.php
- tests/Unit/Services/PlanConfigPropertyTest.php
- tests/Unit/Services/PolarServicePropertyTest.php
- tests/Unit/Services/ReportServicePropertyTest.php
- tests/Unit/Services/StoreServicePropertyTest.php
- tests/Unit/Services/TemplateServicePropertyTest.php
The project employs a multi-layered testing strategy leveraging the PHPUnit framework. The approach combines traditional unit and feature tests with a strong emphasis on property-based testing to ensure the correctness and robustness of core business logic. Client-side functionality, primarily built with Alpine.js, is managed and validated within the view layer.
The strategy is configured in phpunit.xml and is designed to run in a controlled, isolated environment. Key aspects include a clear separation of test suites, a consistent in-memory database setup for test execution, and the use of specialized testing libraries like Eris for property-based testing. This ensures that application services, data invariants, and critical integrations are thoroughly verified.
Test Environment Configuration
All tests are executed in a dedicated testing environment. The phpunit.xml file configures environment variables to ensure tests run in isolation without affecting development or production data. This includes using an in-memory SQLite database and array-based drivers for cache, session, and mail.
| Variable | Value | Purpose |
|---|---|---|
APP_ENV | testing | Sets the application environment to testing mode. |
DB_CONNECTION | sqlite | Uses the SQLite database driver. |
DB_DATABASE | :memory: | Uses an in-memory database for speed and isolation. |
CACHE_STORE | array | Uses a non-persistent array driver for caching. |
SESSION_DRIVER | array | Uses a non-persistent array driver for sessions. |
QUEUE_CONNECTION | sync | Executes queued jobs synchronously during tests. |
MAIL_MAILER | array | Prevents emails from being sent, storing them in an array instead. |
PULSE_ENABLED | false | Disables Laravel Pulse during tests. |
TELESCOPE_ENABLED | false | Disables Laravel Telescope during tests. |
Sources: phpunit.xml:18-28
Test Suites
The project organizes tests into two primary suites defined in phpunit.xml.
This diagram shows the two test suites configured in the project.
Sources: phpunit.xml:7-13
- Unit Test Suite: Contains tests for individual classes and methods in isolation. These tests are located in the
tests/Unitdirectory and focus on verifying the logic of specific components like services and configuration handlers. - Feature Test Suite: Contains tests that verify features from a higher level, potentially involving multiple interacting components. These tests are located in the
tests/Featuredirectory.
Unit Testing
Unit tests form the foundation of the testing strategy, focusing on individual service methods and class logic.
Standard Unit Tests
Standard unit tests verify specific outcomes for given inputs. The project uses the RefreshDatabase trait to ensure a clean database state for each test, preventing interference between test cases.
An example is the CategoryServiceTest, which verifies that the service can create categories, generate unique slugs, and handle deletion constraints correctly.
Sources: tests/Unit/Services/CategoryServiceTest.php
Property-Based Testing (PBT)
A significant portion of the unit tests are property-based, using the Eris testing library. Instead of testing with fixed examples, PBT defines general properties that must hold true for a wide range of auto-generated inputs. This approach is particularly effective at finding edge cases in business logic. PBT is implemented using the Eris\TestTrait and Eris\Generators.
Sources: tests/Unit/Services/TemplateServicePropertyTest.php:15, tests/Unit/Services/PolarServicePropertyTest.php:15
Template Management Properties
The TemplateServicePropertyTest ensures the robustness of the template validation and serialization logic.
| Property | Description | Validation Method |
|---|---|---|
| Template Name Validation | The name must only contain lowercase letters, digits, and underscores. | validateTemplateName |
| Footer Length Validation | Footer text must be 60 characters or fewer. | validateFooter |
| Body Length Validation | Body text must be between 1 and 1024 characters. | validateBody |
| Button Limit Validation | A template can have up to 10 quick-reply buttons OR up to 2 call-to-action buttons, but not a mix. | validateButtons |
| Required Field Validation | name, category, language, and body are mandatory fields. | validateRequiredFields |
| Data Round-Trip | Serializing template data to JSON and deserializing it back must result in the original data structure. | serializeTemplate, deserializeTemplate |
| Preview Variable Rendering | Placeholders like {{1}} in the body are correctly rendered as [Variable 1] in the preview. | renderPreviewBody |
Sources: tests/Unit/Services/TemplateServicePropertyTest.php, app/Services/TemplateService.php
The button validation logic is a good example of complex rules checked by PBT.
This flowchart illustrates the button validation logic in TemplateService.
Sources: app/Services/TemplateService.php:110-150
Polar Subscription Properties
PBT is used to verify critical security and data integrity aspects of the Polar subscription service.
- Webhook Signature Validation: This property ensures that incoming webhooks are authentic and have not been tampered with. The test generates random payloads and secrets, computes the expected HMAC-SHA256 signature, and verifies that the
validateWebhookSignaturemethod accepts it. It also tests that invalid signatures, tampered payloads, and malformed headers are rejected.
This sequence diagram shows the webhook signature validation process tested in PolarServicePropertyTest.
Sources: tests/Unit/Services/PolarServicePropertyTest.php:33-70
- Checkout Session Data Integrity: Ensures that the
CheckoutSessionDTO correctly holds all required data (user email, plan ID, callback URLs) and that its properties are immutable (readonly).
Sources: tests/Unit/Services/PolarServicePropertyTest.php:200-252
Point-of-Sale (POS) Properties
PBT is extensively used to test the complex business rules and data invariants of the POS system.
- Order Total Invariant: Verifies that for any combination of items and discounts,
Order.totalalways equalssubtotal + tax_amount - discount_amount.
Sources: tests/Unit/Services/OrderServicePropertyTest.php:100-154 - Inventory Consistency: Ensures that completing an order correctly decrements product stock, and cancelling a completed order correctly restores it.
Sources: tests/Unit/Services/OrderServicePropertyTest.php:162-269 - Payment Change Calculation: Confirms that for any payment where
amount_paid >= order_total, the calculated change is exactlyamount_paid - order_total.
Sources: tests/Unit/Services/PaymentServicePropertyTest.php:98-132 - Inactive Store Order Rejection: Guarantees that no new orders can be created for a store marked as inactive (
is_active = false).
Sources: tests/Unit/Services/StoreServicePropertyTest.php:61-129 - Table Status State Transition: Checks that a table's status correctly transitions between
availableandoccupiedbased on order creation and completion/cancellation.
This state diagram illustrates the state transitions of a Table entity, as verified in OrderServicePropertyTest.
Sources: tests/Unit/Services/OrderServicePropertyTest.php:278-339
Client-Side Testing (Alpine.js)
The project utilizes Alpine.js for frontend interactivity, and the testing logic is embedded directly within the Blade view files. This approach treats the frontend components as self-contained units with their own state management, validation, and API interaction logic.
The templates.blade.php file provides a comprehensive example with the templatesManager Alpine.js component. This component manages the entire lifecycle of template creation, editing, and deletion on the client side.
Key tested functionalities include:
- State Management: Handling
loading,creating,updating, anddeletingstates to provide user feedback. - Form Handling: Managing complex form state for creating templates, including nested objects for header, body, and buttons (
createForm). - Real-time Validation: Client-side validation methods like
validateName(),validateBody(), andvalidateFooter()provide immediate feedback to the user and control form submission eligibility (isFormValid()). - Dynamic UI: The preview of the WhatsApp message updates in real-time as the user types, driven by methods like
getPreviewBody(). - API Interaction: Methods like
submitCreate(),submitEdit(), andconfirmDelete()handlefetchrequests to the backend API, process responses, and manage API error states (apiError,editApiError).
The flow for creating a new template demonstrates this client-side testing and management approach.
This diagram shows the client-side process for creating a template, managed entirely by an Alpine.js component.
Sources: resources/views/dashboard/templates.blade.php:1005-1126
Integration Test Script
The file test_services.php serves as a simple, script-based integration test. It bootstraps the Laravel application and sequentially calls different services to simulate a complete Point-of-Sale workflow. This script is not part of the automated PHPUnit suite but acts as a valuable tool for quick, end-to-end sanity checks of core service interactions.
The workflow tested is as follows:
- Create a
Category. - Use
ProductServiceto create aProductwithin that category. - Create a
Store,Role, andPosUser. - Use
OrderServiceto create anOrder. - Add the product to the order.
- Calculate order totals.
- Use
PaymentServiceto simulate a payment calculation. - Complete the order using
OrderService. - Verify that the
Product's stock has been correctly reduced.
Sources: test_services.php