How to — test
Current testing posture across all three repos. Where infrastructure exists, this page shows how to run it. Where it doesn’t, it recommends what to add.
Backend (dropafinder-app-backend)
Infrastructure
PHPUnit is fully configured. phpunit.xml defines two suites:
- Unit →
tests/Unit/ - Feature →
tests/Feature/
Both suites use an in-process bootstrap (vendor/autoload.php) and run with APP_ENV=testing, QUEUE_CONNECTION=sync, and MAIL_MAILER=array.
⚠️ Warning: The
DB_CONNECTIONlines inphpunit.xmlare commented out. The test suite uses whatever database is configured in.envunless you overrideDB_CONNECTIONmanually. For CI or clean local runs, uncomment the SQLite in-memory block:<env name="DB_CONNECTION" value="sqlite"/> <env name="DB_DATABASE" value=":memory:"/>
Existing tests
tests/Feature/
├── AuditLogTest.php
├── BillingControllerTest.php
├── ExampleTest.php
├── LocationImageTest.php
├── SubscriptionEntitlementTest.php
└── UserWorkspaceProvisioningTest.php
tests/Unit/
└── ExampleTest.phpFeature tests are the primary test type. They test full request-response cycles through Laravel’s HTTP kernel.
How to run
cd "/Users/codydavis/Local Sites/dropafinder-app-backend"
# Run all tests
./vendor/bin/phpunit
# Run a single suite
./vendor/bin/phpunit --testsuite Feature
./vendor/bin/phpunit --testsuite Unit
# Run a single file
./vendor/bin/phpunit tests/Feature/AuditLogTest.php
# Run a single test method
./vendor/bin/phpunit --filter testAuditLogIsCreatedAdding a new feature test
php artisan make:test MyFeatureTestGenerated at tests/Feature/MyFeatureTest.php. The base class is Tests\TestCase, which extends Illuminate\Foundation\Testing\TestCase. Use RefreshDatabase or DatabaseTransactions traits to isolate database state:
use Illuminate\Foundation\Testing\RefreshDatabase;
class MyFeatureTest extends TestCase
{
use RefreshDatabase;
public function test_endpoint_returns_data(): void
{
$user = \App\Models\User::factory()->create();
$response = $this->actingAs($user, 'api')
->getJson('/api/my-resource');
$response->assertOk()->assertJsonStructure(['data']);
}
}What to test first
If introducing coverage to an area that has none, prioritize in this order:
- New endpoints — assert correct HTTP status codes, response shape, and authorization (anonymous = 401, wrong workspace = 403).
- Subscription entitlement gates —
SubscriptionEntitlementTest.phpis the model here. - Audit log emission — assert that mutating actions create a row in
audit_logs.
Next.js dashboard (dropafinder-app-nextjs)
Infrastructure
🔴 [NEEDS CLARIFICATION: No test runner is installed and package.json has no test script. Neither Jest nor Vitest is listed in dependencies or devDependencies.]
Available scripts today:
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "eslint"
}The lint script (npm run lint) runs ESLint and is the only automated quality check currently in place.
Recommended path to introduce tests
Add Vitest with @testing-library/react:
npm install --save-dev vitest @vitejs/plugin-react @testing-library/react @testing-library/user-event jsdomCreate vitest.config.ts at the project root and configure the jsdom environment. Once Vitest is installed, the highest-value tests to write first are:
- Normalizer functions (
src/lib/api/normalizers.ts) — pure input/output functions; easy to test, high breakage risk. - Payload transformers (
src/lib/api/payloads.ts) — same category. finderBuilderConfig.tshelpers —buildThemePreset,buildV2Config, etc.- TanStack Query hook integration tests — use
@testing-library/reactwith a query client wrapper.
Current quality gate
cd "/Users/codydavis/Local Sites/dropafinder-app-nextjs"
npm run lintESLint is configured at the project root. Fix all lint errors before pushing to main.
Widget (dropafinder-app-external)
Infrastructure
🔴 [NEEDS CLARIFICATION: No test runner is configured in ext/2/source/package.json. The widget has no test script and Vitest is not installed.]
Available scripts today:
"scripts": {
"dev": "vite",
"build": "vite build",
"build:dev": "vite build --mode development",
"deploy:02": "npm run build && node scripts/deploy-r2.mjs",
"serve": "vite preview"
}Recommended path to introduce tests
The widget is a Svelte + Vite project. Add @vitest/ui and @testing-library/svelte:
npm install --save-dev vitest @testing-library/svelte jsdomHighest-value tests:
- Filtering logic (
src/lib/filtering.js) —applyFinderFilterstakes plain data in, returns plain data out. No DOM needed. - Store initialization (
src/lib/stores.js) —initializeFinderStoresparses the payload shape and populates stores; assert that a given payload produces the expecteddesignStorestate. mapSettings.jsutilities —resolveMapSettings,normalizeMapProvider,isMapStyleVariantSupportedare pure functions.localization.js— translation lookup functions.
Manual verification
Until a test suite exists, verify widget changes through the dashboard Live Preview:
cd "/Users/codydavis/Local Sites/dropafinder-app-external/ext/2/source"
npm run build:devThen open the Finder Builder in the local dashboard at http://localhost:3000 and exercise the changed feature in the Live Preview rail.
Where to next
- Run all three services locally: run-locally
- Ship tested changes: deploy