import type { PluginFn } from '@japa/runner/types'; import { ApiResponse } from '@japa/api-client'; import type { ApplicationService } from '@adonisjs/core/types'; import type { ComponentSnapshot, ComponentEffects } from '../../types.js'; /** * Parsed Livewire components with snapshot already parsed */ type ParsedLivewireComponents = Array<{ snapshot: ComponentSnapshot; effects: ComponentEffects; }>; /** * Testable response wrapper for Livewire HTTP responses * * Provides a fluent PHP-like API for testing Livewire responses, * similar to `Livewire::test()` in the PHP version. * * @example * ```js * const response = await client.post('/livewire/update').withLivewire() * * response.livewire() * .assertSet('count', 5) * .assertSee('Hello World') * .assertDispatched('user-updated') * ``` */ export declare class TestableResponse { #private; constructor(response: ApiResponse, components: ParsedLivewireComponents, componentIndex?: number); /** * Get the component ID * * @example * ```js * console.log(response.livewire().id()) // 'abc123' * ``` */ id(): string; /** * Get the component name * * @example * ```js * console.log(response.livewire().name()) // 'Users/Index' * ``` */ name(): string; /** * Get a property value from the component data * * @param propertyName - The property name (supports dot notation) * * @example * ```js * console.log(response.livewire().get('count')) // 5 * console.log(response.livewire().get('user.name')) // 'John' * ``` */ get(propertyName: string): any; /** * Get all component data * * @example * ```js * console.log(response.livewire().getData()) // { count: 5, name: 'John' } * ``` */ getData(): Record; /** * Get the component snapshot * * @example * ```js * console.log(response.livewire().snapshot()) * ``` */ snapshot(): ComponentSnapshot; /** * Get the component effects * * @example * ```js * console.log(response.livewire().effects()) * ``` */ effects(): ComponentEffects; /** * Get the rendered HTML * * @example * ```js * console.log(response.livewire().html()) // '
Count: 5
' * ``` */ html(): string; /** * Get all parsed components * * @example * ```js * console.log(response.livewire().components()) * ``` */ components(): ParsedLivewireComponents; /** * Get testable for a specific component by index * * @param index - Component index * * @example * ```js * response.livewire().component(1).assertSet('count', 10) * ``` */ component(index: number): TestableResponse; /** * Assert that a property is set to a specific value * * @param name - Property name (supports dot notation) * @param value - Expected value or callback * * @example * ```js * response.livewire() * .assertSet('count', 5) * .assertSet('user.name', 'John') * .assertSet('items', (items) => items.length > 0) * ``` */ assertSet(name: string, value: any | ((actual: any) => boolean)): this; /** * Assert that a property is NOT set to a specific value * * @param name - Property name (supports dot notation) * @param value - Value that should not match * * @example * ```js * response.livewire().assertNotSet('count', 0) * ``` */ assertNotSet(name: string, value: any): this; /** * Assert array property has specific count * * @param name - Property name * @param count - Expected count * * @example * ```js * response.livewire().assertCount('items', 5) * ``` */ assertCount(name: string, count: number): this; /** * Assert that snapshot data contains a property with value * * @param name - Property name in snapshot data * @param value - Expected value * * @example * ```js * response.livewire().assertSnapshotSet('count', 5) * ``` */ assertSnapshotSet(name: string, value: any): this; /** * Assert that snapshot data does NOT contain a property with value * * @param name - Property name in snapshot data * @param value - Value that should not match * * @example * ```js * response.livewire().assertSnapshotNotSet('count', 0) * ``` */ assertSnapshotNotSet(name: string, value: any): this; /** * Assert that the rendered HTML contains a string * * @param value - String to search for (will be HTML escaped by default) * @param escape - Whether to HTML escape the value (default: true) * * @example * ```js * response.livewire() * .assertSee('Hello World') * .assertSee('Bold', false) * ``` */ assertSee(value: string, escape?: boolean): this; /** * Assert that the rendered HTML does NOT contain a string * * @param value - String that should not be present * @param escape - Whether to HTML escape the value (default: true) * * @example * ```js * response.livewire().assertDontSee('Error') * ``` */ assertDontSee(value: string, escape?: boolean): this; /** * Assert that the raw HTML contains a string (no escaping) * * @param value - Raw HTML string to search for * * @example * ```js * response.livewire().assertSeeHtml('
') * ``` */ assertSeeHtml(value: string): this; /** * Assert that the raw HTML does NOT contain a string * * @param value - Raw HTML string that should not be present * * @example * ```js * response.livewire().assertDontSeeHtml('
') * ``` */ assertDontSeeHtml(value: string): this; /** * Assert that HTML contains strings in order * * @param values - Array of strings that should appear in order * * @example * ```js * response.livewire().assertSeeInOrder(['First', 'Second', 'Third']) * ``` */ assertSeeInOrder(values: string[]): this; /** * Assert that raw HTML contains strings in order * * @param values - Array of HTML strings that should appear in order * * @example * ```js * response.livewire().assertSeeHtmlInOrder(['

', '

', '

']) * ``` */ assertSeeHtmlInOrder(values: string[]): this; /** * Assert that text content (stripped of HTML tags) contains a string * * @param value - Text to search for * * @example * ```js * response.livewire().assertSeeText('Hello World') * ``` */ assertSeeText(value: string): this; /** * Assert that text content does NOT contain a string * * @param value - Text that should not be present * * @example * ```js * response.livewire().assertDontSeeText('Error') * ``` */ assertDontSeeText(value: string): this; /** * Assert that an event was dispatched * * @param event - Event name * @param params - Optional event parameters to match * * @example * ```js * response.livewire() * .assertDispatched('user-updated') * .assertDispatched('post-created', { id: 1 }) * ``` */ assertDispatched(event: string, params?: Record | ((name: string, params: Record) => boolean)): this; /** * Assert that an event was NOT dispatched * * @param event - Event name * * @example * ```js * response.livewire().assertNotDispatched('error-occurred') * ``` */ assertNotDispatched(event: string): this; /** * Assert that an event was broadcasted to a Transmit (SSE) channel * * @param channel - Transmit channel name * @param eventName - Optional event name * * @example * ```js * response.livewire().assertBroadcastedToTransmit('orders/42', 'OrderShipped') * ``` */ assertBroadcastedToTransmit(channel: string, eventName?: string): this; /** * Assert that a redirect was triggered * * @param url - Optional specific URL to match * * @example * ```js * response.livewire() * .assertRedirect() * .assertRedirect('/dashboard') * ``` */ assertRedirect(url?: string): this; /** * Assert that redirect URL contains a string * * @param uri - String that should be in the redirect URL * * @example * ```js * response.livewire().assertRedirectContains('/users') * ``` */ assertRedirectContains(uri: string): this; /** * Assert that no redirect was triggered * * @example * ```js * response.livewire().assertNoRedirect() * ``` */ assertNoRedirect(): this; /** * Assert that there are validation errors * * @param keys - Optional specific keys that should have errors * * @example * ```js * response.livewire() * .assertHasErrors() * .assertHasErrors(['email', 'password']) * ``` */ assertHasErrors(keys?: string | string[]): this; /** * Assert that there are no validation errors * * @param keys - Optional specific keys that should not have errors * * @example * ```js * response.livewire() * .assertHasNoErrors() * .assertHasNoErrors(['email']) * ``` */ assertHasNoErrors(keys?: string | string[]): this; /** * Assert that a file download was triggered * * @param filename - Optional expected filename * * @example * ```js * response.livewire() * .assertFileDownloaded() * .assertFileDownloaded('report.pdf') * ``` */ assertFileDownloaded(filename?: string): this; /** * Assert that no file download was triggered * * @example * ```js * response.livewire().assertNoFileDownloaded() * ``` */ assertNoFileDownloaded(): this; /** * Assert the return value from the last method call * * @param value - Expected return value * * @example * ```js * response.livewire().assertReturned('success') * ``` */ assertReturned(value: any): this; /** * Assert the HTTP status code * * @param code - Expected status code * * @example * ```js * response.livewire().assertStatus(200) * ``` */ assertStatus(code: number): this; /** * Assert successful HTTP status (2xx) * * @example * ```js * response.livewire().assertOk() * ``` */ assertOk(): this; /** * Assert unauthorized status (401) * * @example * ```js * response.livewire().assertUnauthorized() * ``` */ assertUnauthorized(): this; /** * Assert forbidden status (403) * * @example * ```js * response.livewire().assertForbidden() * ``` */ assertForbidden(): this; /** * Assert that snapshot matches exactly * * @param snapshot - Expected snapshot * * @example * ```js * response.livewire().assertSnapshot({ ... }) * ``` */ assertSnapshot(snapshot: ComponentSnapshot): this; /** * Assert that snapshot contains subset * * @param partial - Partial snapshot to match * * @example * ```js * response.livewire().assertSnapshotContains({ memo: { name: 'Users/Index' } }) * ``` */ assertSnapshotContains(partial: Partial): this; /** * Assert that effects match exactly * * @param effects - Expected effects * * @example * ```js * response.livewire().assertEffects({ html: '
...
' }) * ``` */ assertEffects(effects: ComponentEffects): this; /** * Assert that effects contain subset * * @param partial - Partial effects to match * * @example * ```js * response.livewire().assertEffectsContains({ redirect: '/dashboard' }) * ``` */ assertEffectsContains(partial: Partial): this; } declare module '@japa/api-client' { /** * Extended ApiRequest interface with Livewire specific methods * * Adds methods to configure requests for testing Livewire applications, * including setting required headers for Livewire requests. */ interface ApiRequest { /** * Set `X-Livewire` header on the request to mark it as a Livewire request * * This method configures the request to be treated as a Livewire AJAX request * by setting the required headers that Livewire uses for identification. * * @returns The ApiRequest instance for method chaining * * @example * ```js * const response = await client * .post('/livewire/update') * .withLivewire() * ``` */ withLivewire(this: ApiRequest): this; /** * Set header for Livewire navigation requests * * Configures the request to be treated as a Livewire navigation request, * which enables features like progress bar and optimized navigation. * * @returns The ApiRequest instance for method chaining * * @example * ```js * const response = await client * .get('/dashboard') * .withLivewireNavigate() * ``` */ withLivewireNavigate(this: ApiRequest): this; } /** * Extended ApiResponse interface with Livewire specific properties and assertions * * Provides access to a TestableResponse wrapper for PHP-like fluent testing API. */ interface ApiResponse { /** * Get a TestableResponse wrapper for PHP-like fluent Livewire testing * * Returns a wrapper that provides chainable assertion methods similar * to PHP Livewire's `Livewire::test()` API. * * @returns TestableResponse instance for method chaining * * @example * ```js * const response = await client.post('/livewire/update').withLivewire() * * response.livewire() * .assertSet('count', 5) * .assertSee('Hello World') * .assertDispatched('user-updated') * .assertRedirect('/dashboard') * ``` */ livewire(this: ApiResponse): TestableResponse; } } /** * Japa plugin that extends the API client with Livewire testing capabilities * * This plugin adds methods to ApiRequest and ApiResponse classes to support * testing Livewire applications with a PHP-like fluent API. * * @param app - The AdonisJS application service instance * @returns Japa plugin function * * @example * ```js * // Configure in tests/bootstrap.ts * import { livewireApiClient } from '@adonisjs/livewire/plugins/japa/api_client' * * export const plugins: Config['plugins'] = [ * assert(), * apiClient(app), * livewireApiClient(app) * ] * ``` * * @example * ```js * // Use in tests - PHP-like fluent API * test('updates user component', async ({ client }) => { * const response = await client * .post('/livewire/update') * .withLivewire() * * response.livewire() * .assertSet('count', 5) * .assertSee('Hello World') * .assertDispatched('user-updated') * .assertRedirect('/dashboard') * }) * ``` */ export declare function livewireApiClient(_app: ApplicationService): PluginFn; export {};