mirror of
https://github.com/php-flasher/php-flasher.git
synced 2026-03-31 15:07:47 +01:00
add event dispatching system for Livewire integration
Implement consistent event dispatching across Noty, Notyf, Toastr adapters and
themes, following the existing SweetAlert pattern. This enables Livewire
integration for all notification types.
JavaScript Events:
- Noty: flasher:noty:show, flasher:noty:click, flasher:noty:close, flasher:noty:hover
- Notyf: flasher:notyf:click, flasher:notyf:dismiss
- Toastr: flasher:toastr:show, flasher:toastr:click, flasher:toastr:close, flasher:toastr:hidden
- Themes: flasher:theme:click (generic), flasher:theme:{name}:click (specific)
PHP Livewire Listeners:
- LivewireListener for each adapter (Noty, Notyf, Toastr)
- ThemeLivewireListener for theme click events
- Registered in service providers when Livewire is bound
This allows Livewire users to listen for notification events and react
accordingly (e.g., noty:click, theme:flasher:click).
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Flasher\Tests\Laravel\EventListener;
|
||||
|
||||
use Flasher\Laravel\EventListener\ThemeLivewireListener;
|
||||
use Flasher\Prime\EventDispatcher\Event\ResponseEvent;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
final class ThemeLivewireListenerTest extends TestCase
|
||||
{
|
||||
private ThemeLivewireListener $listener;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->listener = new ThemeLivewireListener();
|
||||
}
|
||||
|
||||
public function testGetSubscribedEvents(): void
|
||||
{
|
||||
$this->assertSame(ResponseEvent::class, $this->listener->getSubscribedEvents());
|
||||
}
|
||||
|
||||
public function testInvokeSkipsNonHtmlPresenter(): void
|
||||
{
|
||||
$event = new ResponseEvent('', 'json');
|
||||
|
||||
($this->listener)($event);
|
||||
|
||||
$this->assertSame('', $event->getResponse());
|
||||
}
|
||||
|
||||
public function testInvokeSkipsResponseWithoutFlasherScript(): void
|
||||
{
|
||||
$event = new ResponseEvent('<html><body>No flasher</body></html>', 'html');
|
||||
|
||||
($this->listener)($event);
|
||||
|
||||
$this->assertSame('<html><body>No flasher</body></html>', $event->getResponse());
|
||||
}
|
||||
|
||||
public function testInvokeSkipsDuplicateInjection(): void
|
||||
{
|
||||
$response = '<script type="text/javascript" class="flasher-js"></script>';
|
||||
$response .= '<script type="text/javascript" class="flasher-theme-livewire-js"></script>';
|
||||
|
||||
$event = new ResponseEvent($response, 'html');
|
||||
|
||||
($this->listener)($event);
|
||||
|
||||
$this->assertSame($response, $event->getResponse());
|
||||
}
|
||||
|
||||
public function testInvokeInjectsLivewireScript(): void
|
||||
{
|
||||
$response = '<script type="text/javascript" class="flasher-js"></script>';
|
||||
|
||||
$event = new ResponseEvent($response, 'html');
|
||||
|
||||
($this->listener)($event);
|
||||
|
||||
$this->assertStringContainsString('flasher-theme-livewire-js', $event->getResponse());
|
||||
$this->assertStringContainsString('flasher:theme:click', $event->getResponse());
|
||||
$this->assertStringContainsString('theme:click', $event->getResponse());
|
||||
$this->assertStringContainsString("theme:' + themeName + ':click", $event->getResponse());
|
||||
}
|
||||
}
|
||||
@@ -53,6 +53,23 @@ final class FlasherNotyServiceProviderTest extends TestCase
|
||||
$this->app->expects('singleton');
|
||||
$this->app->expects('alias');
|
||||
$this->app->expects('extend');
|
||||
$this->app->expects('bound')->with('livewire')->andReturn(false);
|
||||
|
||||
$this->serviceProvider->register();
|
||||
$this->serviceProvider->boot();
|
||||
$this->addToAssertionCount(1);
|
||||
}
|
||||
|
||||
public function testBootWithLivewire(): void
|
||||
{
|
||||
$this->app->expects()->make('config')->andReturns($configMock = \Mockery::mock(Repository::class));
|
||||
$configMock->expects('get')->andReturns([]);
|
||||
$configMock->expects('set');
|
||||
|
||||
$this->app->expects('singleton');
|
||||
$this->app->expects('alias');
|
||||
$this->app->expects('extend')->twice();
|
||||
$this->app->expects('bound')->with('livewire')->andReturn(true);
|
||||
|
||||
$this->serviceProvider->register();
|
||||
$this->serviceProvider->boot();
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Flasher\Tests\Noty\Laravel;
|
||||
|
||||
use Flasher\Noty\Laravel\LivewireListener;
|
||||
use Flasher\Prime\EventDispatcher\Event\ResponseEvent;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
final class LivewireListenerTest extends TestCase
|
||||
{
|
||||
private LivewireListener $listener;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->listener = new LivewireListener();
|
||||
}
|
||||
|
||||
public function testGetSubscribedEvents(): void
|
||||
{
|
||||
$this->assertSame(ResponseEvent::class, $this->listener->getSubscribedEvents());
|
||||
}
|
||||
|
||||
public function testInvokeSkipsNonHtmlPresenter(): void
|
||||
{
|
||||
$event = new ResponseEvent('', 'json');
|
||||
|
||||
($this->listener)($event);
|
||||
|
||||
$this->assertSame('', $event->getResponse());
|
||||
}
|
||||
|
||||
public function testInvokeSkipsResponseWithoutFlasherScript(): void
|
||||
{
|
||||
$event = new ResponseEvent('<html><body>No flasher</body></html>', 'html');
|
||||
|
||||
($this->listener)($event);
|
||||
|
||||
$this->assertSame('<html><body>No flasher</body></html>', $event->getResponse());
|
||||
}
|
||||
|
||||
public function testInvokeSkipsDuplicateInjection(): void
|
||||
{
|
||||
$response = '<script type="text/javascript" class="flasher-js"></script>';
|
||||
$response .= '<script type="text/javascript" class="flasher-noty-livewire-js"></script>';
|
||||
|
||||
$event = new ResponseEvent($response, 'html');
|
||||
|
||||
($this->listener)($event);
|
||||
|
||||
$this->assertSame($response, $event->getResponse());
|
||||
}
|
||||
|
||||
public function testInvokeInjectsLivewireScript(): void
|
||||
{
|
||||
$response = '<script type="text/javascript" class="flasher-js"></script>';
|
||||
|
||||
$event = new ResponseEvent($response, 'html');
|
||||
|
||||
($this->listener)($event);
|
||||
|
||||
$this->assertStringContainsString('flasher-noty-livewire-js', $event->getResponse());
|
||||
$this->assertStringContainsString('flasher:noty:show', $event->getResponse());
|
||||
$this->assertStringContainsString('flasher:noty:click', $event->getResponse());
|
||||
$this->assertStringContainsString('flasher:noty:close', $event->getResponse());
|
||||
$this->assertStringContainsString('flasher:noty:hover', $event->getResponse());
|
||||
}
|
||||
}
|
||||
@@ -53,6 +53,23 @@ final class FlasherNotyfServiceProviderTest extends TestCase
|
||||
$this->app->expects('singleton');
|
||||
$this->app->expects('alias');
|
||||
$this->app->expects('extend');
|
||||
$this->app->expects('bound')->with('livewire')->andReturn(false);
|
||||
|
||||
$this->serviceProvider->register();
|
||||
$this->serviceProvider->boot();
|
||||
$this->addToAssertionCount(1);
|
||||
}
|
||||
|
||||
public function testBootWithLivewire(): void
|
||||
{
|
||||
$this->app->expects()->make('config')->andReturns($configMock = \Mockery::mock(Repository::class));
|
||||
$configMock->expects('get')->andReturns([]);
|
||||
$configMock->expects('set');
|
||||
|
||||
$this->app->expects('singleton');
|
||||
$this->app->expects('alias');
|
||||
$this->app->expects('extend')->twice();
|
||||
$this->app->expects('bound')->with('livewire')->andReturn(true);
|
||||
|
||||
$this->serviceProvider->register();
|
||||
$this->serviceProvider->boot();
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Flasher\Tests\Notyf\Laravel;
|
||||
|
||||
use Flasher\Notyf\Laravel\LivewireListener;
|
||||
use Flasher\Prime\EventDispatcher\Event\ResponseEvent;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
final class LivewireListenerTest extends TestCase
|
||||
{
|
||||
private LivewireListener $listener;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->listener = new LivewireListener();
|
||||
}
|
||||
|
||||
public function testGetSubscribedEvents(): void
|
||||
{
|
||||
$this->assertSame(ResponseEvent::class, $this->listener->getSubscribedEvents());
|
||||
}
|
||||
|
||||
public function testInvokeSkipsNonHtmlPresenter(): void
|
||||
{
|
||||
$event = new ResponseEvent('', 'json');
|
||||
|
||||
($this->listener)($event);
|
||||
|
||||
$this->assertSame('', $event->getResponse());
|
||||
}
|
||||
|
||||
public function testInvokeSkipsResponseWithoutFlasherScript(): void
|
||||
{
|
||||
$event = new ResponseEvent('<html><body>No flasher</body></html>', 'html');
|
||||
|
||||
($this->listener)($event);
|
||||
|
||||
$this->assertSame('<html><body>No flasher</body></html>', $event->getResponse());
|
||||
}
|
||||
|
||||
public function testInvokeSkipsDuplicateInjection(): void
|
||||
{
|
||||
$response = '<script type="text/javascript" class="flasher-js"></script>';
|
||||
$response .= '<script type="text/javascript" class="flasher-notyf-livewire-js"></script>';
|
||||
|
||||
$event = new ResponseEvent($response, 'html');
|
||||
|
||||
($this->listener)($event);
|
||||
|
||||
$this->assertSame($response, $event->getResponse());
|
||||
}
|
||||
|
||||
public function testInvokeInjectsLivewireScript(): void
|
||||
{
|
||||
$response = '<script type="text/javascript" class="flasher-js"></script>';
|
||||
|
||||
$event = new ResponseEvent($response, 'html');
|
||||
|
||||
($this->listener)($event);
|
||||
|
||||
$this->assertStringContainsString('flasher-notyf-livewire-js', $event->getResponse());
|
||||
$this->assertStringContainsString('flasher:notyf:click', $event->getResponse());
|
||||
$this->assertStringContainsString('flasher:notyf:dismiss', $event->getResponse());
|
||||
}
|
||||
}
|
||||
@@ -53,6 +53,23 @@ final class FlasherToastrServiceProviderTest extends TestCase
|
||||
$this->app->expects('singleton');
|
||||
$this->app->expects('alias');
|
||||
$this->app->expects('extend');
|
||||
$this->app->expects('bound')->with('livewire')->andReturn(false);
|
||||
|
||||
$this->serviceProvider->register();
|
||||
$this->serviceProvider->boot();
|
||||
$this->addToAssertionCount(1);
|
||||
}
|
||||
|
||||
public function testBootWithLivewire(): void
|
||||
{
|
||||
$this->app->expects()->make('config')->andReturns($configMock = \Mockery::mock(Repository::class));
|
||||
$configMock->expects('get')->andReturns([]);
|
||||
$configMock->expects('set');
|
||||
|
||||
$this->app->expects('singleton');
|
||||
$this->app->expects('alias');
|
||||
$this->app->expects('extend')->twice();
|
||||
$this->app->expects('bound')->with('livewire')->andReturn(true);
|
||||
|
||||
$this->serviceProvider->register();
|
||||
$this->serviceProvider->boot();
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Flasher\Tests\Toastr\Laravel;
|
||||
|
||||
use Flasher\Prime\EventDispatcher\Event\ResponseEvent;
|
||||
use Flasher\Toastr\Laravel\LivewireListener;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
final class LivewireListenerTest extends TestCase
|
||||
{
|
||||
private LivewireListener $listener;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->listener = new LivewireListener();
|
||||
}
|
||||
|
||||
public function testGetSubscribedEvents(): void
|
||||
{
|
||||
$this->assertSame(ResponseEvent::class, $this->listener->getSubscribedEvents());
|
||||
}
|
||||
|
||||
public function testInvokeSkipsNonHtmlPresenter(): void
|
||||
{
|
||||
$event = new ResponseEvent('', 'json');
|
||||
|
||||
($this->listener)($event);
|
||||
|
||||
$this->assertSame('', $event->getResponse());
|
||||
}
|
||||
|
||||
public function testInvokeSkipsResponseWithoutFlasherScript(): void
|
||||
{
|
||||
$event = new ResponseEvent('<html><body>No flasher</body></html>', 'html');
|
||||
|
||||
($this->listener)($event);
|
||||
|
||||
$this->assertSame('<html><body>No flasher</body></html>', $event->getResponse());
|
||||
}
|
||||
|
||||
public function testInvokeSkipsDuplicateInjection(): void
|
||||
{
|
||||
$response = '<script type="text/javascript" class="flasher-js"></script>';
|
||||
$response .= '<script type="text/javascript" class="flasher-toastr-livewire-js"></script>';
|
||||
|
||||
$event = new ResponseEvent($response, 'html');
|
||||
|
||||
($this->listener)($event);
|
||||
|
||||
$this->assertSame($response, $event->getResponse());
|
||||
}
|
||||
|
||||
public function testInvokeInjectsLivewireScript(): void
|
||||
{
|
||||
$response = '<script type="text/javascript" class="flasher-js"></script>';
|
||||
|
||||
$event = new ResponseEvent($response, 'html');
|
||||
|
||||
($this->listener)($event);
|
||||
|
||||
$this->assertStringContainsString('flasher-toastr-livewire-js', $event->getResponse());
|
||||
$this->assertStringContainsString('flasher:toastr:show', $event->getResponse());
|
||||
$this->assertStringContainsString('flasher:toastr:click', $event->getResponse());
|
||||
$this->assertStringContainsString('flasher:toastr:close', $event->getResponse());
|
||||
$this->assertStringContainsString('flasher:toastr:hidden', $event->getResponse());
|
||||
}
|
||||
}
|
||||
@@ -224,4 +224,99 @@ describe('NotyPlugin', () => {
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('event dispatching', () => {
|
||||
it('should set up event callbacks that dispatch custom events', () => {
|
||||
plugin.renderEnvelopes([createEnvelope()])
|
||||
|
||||
// Verify callbacks are set up in options
|
||||
const calledOptions = MockNoty.mock.calls[0][0]
|
||||
expect(calledOptions.callbacks).toBeDefined()
|
||||
expect(calledOptions.callbacks.onShow).toBeInstanceOf(Function)
|
||||
expect(calledOptions.callbacks.onClick).toBeInstanceOf(Function)
|
||||
expect(calledOptions.callbacks.onClose).toBeInstanceOf(Function)
|
||||
expect(calledOptions.callbacks.onHover).toBeInstanceOf(Function)
|
||||
})
|
||||
|
||||
it('should dispatch flasher:noty:show event when onShow callback is called', () => {
|
||||
const eventHandler = vi.fn()
|
||||
window.addEventListener('flasher:noty:show', eventHandler)
|
||||
|
||||
plugin.renderEnvelopes([createEnvelope({ message: 'Test' })])
|
||||
|
||||
const calledOptions = MockNoty.mock.calls[0][0]
|
||||
calledOptions.callbacks.onShow()
|
||||
|
||||
expect(eventHandler).toHaveBeenCalledWith(expect.objectContaining({
|
||||
detail: expect.objectContaining({
|
||||
envelope: expect.objectContaining({ message: 'Test' }),
|
||||
}),
|
||||
}))
|
||||
|
||||
window.removeEventListener('flasher:noty:show', eventHandler)
|
||||
})
|
||||
|
||||
it('should dispatch flasher:noty:click event when onClick callback is called', () => {
|
||||
const eventHandler = vi.fn()
|
||||
window.addEventListener('flasher:noty:click', eventHandler)
|
||||
|
||||
plugin.renderEnvelopes([createEnvelope({ message: 'Click test' })])
|
||||
|
||||
const calledOptions = MockNoty.mock.calls[0][0]
|
||||
calledOptions.callbacks.onClick()
|
||||
|
||||
expect(eventHandler).toHaveBeenCalledWith(expect.objectContaining({
|
||||
detail: expect.objectContaining({
|
||||
envelope: expect.objectContaining({ message: 'Click test' }),
|
||||
}),
|
||||
}))
|
||||
|
||||
window.removeEventListener('flasher:noty:click', eventHandler)
|
||||
})
|
||||
|
||||
it('should dispatch flasher:noty:close event when onClose callback is called', () => {
|
||||
const eventHandler = vi.fn()
|
||||
window.addEventListener('flasher:noty:close', eventHandler)
|
||||
|
||||
plugin.renderEnvelopes([createEnvelope()])
|
||||
|
||||
const calledOptions = MockNoty.mock.calls[0][0]
|
||||
calledOptions.callbacks.onClose()
|
||||
|
||||
expect(eventHandler).toHaveBeenCalled()
|
||||
|
||||
window.removeEventListener('flasher:noty:close', eventHandler)
|
||||
})
|
||||
|
||||
it('should dispatch flasher:noty:hover event when onHover callback is called', () => {
|
||||
const eventHandler = vi.fn()
|
||||
window.addEventListener('flasher:noty:hover', eventHandler)
|
||||
|
||||
plugin.renderEnvelopes([createEnvelope()])
|
||||
|
||||
const calledOptions = MockNoty.mock.calls[0][0]
|
||||
calledOptions.callbacks.onHover()
|
||||
|
||||
expect(eventHandler).toHaveBeenCalled()
|
||||
|
||||
window.removeEventListener('flasher:noty:hover', eventHandler)
|
||||
})
|
||||
|
||||
it('should call original callbacks if provided', () => {
|
||||
const originalOnClick = vi.fn()
|
||||
|
||||
plugin.renderEnvelopes([createEnvelope({
|
||||
options: {
|
||||
callbacks: {
|
||||
onClick: originalOnClick,
|
||||
},
|
||||
},
|
||||
})])
|
||||
|
||||
const calledOptions = MockNoty.mock.calls[0][0]
|
||||
calledOptions.callbacks.onClick()
|
||||
|
||||
expect(originalOnClick).toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -81,7 +81,7 @@ describe('ToastrPlugin', () => {
|
||||
expect(mockToastr.success).toHaveBeenCalledWith(
|
||||
'Hello World',
|
||||
'Greeting',
|
||||
{ timeOut: 5000 },
|
||||
expect.objectContaining({ timeOut: 5000 }),
|
||||
)
|
||||
})
|
||||
|
||||
@@ -218,4 +218,94 @@ describe('ToastrPlugin', () => {
|
||||
expect(mockToastr.warning).toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
|
||||
describe('event dispatching', () => {
|
||||
it('should set up event callbacks that dispatch custom events', () => {
|
||||
plugin.renderEnvelopes([createEnvelope()])
|
||||
|
||||
// Verify options passed to toastr include event callbacks
|
||||
const calledOptions = mockToastr.success.mock.calls[0][2]
|
||||
expect(calledOptions.onShown).toBeInstanceOf(Function)
|
||||
expect(calledOptions.onclick).toBeInstanceOf(Function)
|
||||
expect(calledOptions.onCloseClick).toBeInstanceOf(Function)
|
||||
expect(calledOptions.onHidden).toBeInstanceOf(Function)
|
||||
})
|
||||
|
||||
it('should dispatch flasher:toastr:show event when onShown callback is called', () => {
|
||||
const eventHandler = vi.fn()
|
||||
window.addEventListener('flasher:toastr:show', eventHandler)
|
||||
|
||||
plugin.renderEnvelopes([createEnvelope({ message: 'Show test' })])
|
||||
|
||||
const calledOptions = mockToastr.success.mock.calls[0][2]
|
||||
calledOptions.onShown()
|
||||
|
||||
expect(eventHandler).toHaveBeenCalledWith(expect.objectContaining({
|
||||
detail: expect.objectContaining({
|
||||
envelope: expect.objectContaining({ message: 'Show test' }),
|
||||
}),
|
||||
}))
|
||||
|
||||
window.removeEventListener('flasher:toastr:show', eventHandler)
|
||||
})
|
||||
|
||||
it('should dispatch flasher:toastr:click event when onclick callback is called', () => {
|
||||
const eventHandler = vi.fn()
|
||||
window.addEventListener('flasher:toastr:click', eventHandler)
|
||||
|
||||
plugin.renderEnvelopes([createEnvelope({ message: 'Click test' })])
|
||||
|
||||
const calledOptions = mockToastr.success.mock.calls[0][2]
|
||||
calledOptions.onclick()
|
||||
|
||||
expect(eventHandler).toHaveBeenCalledWith(expect.objectContaining({
|
||||
detail: expect.objectContaining({
|
||||
envelope: expect.objectContaining({ message: 'Click test' }),
|
||||
}),
|
||||
}))
|
||||
|
||||
window.removeEventListener('flasher:toastr:click', eventHandler)
|
||||
})
|
||||
|
||||
it('should dispatch flasher:toastr:close event when onCloseClick callback is called', () => {
|
||||
const eventHandler = vi.fn()
|
||||
window.addEventListener('flasher:toastr:close', eventHandler)
|
||||
|
||||
plugin.renderEnvelopes([createEnvelope()])
|
||||
|
||||
const calledOptions = mockToastr.success.mock.calls[0][2]
|
||||
calledOptions.onCloseClick()
|
||||
|
||||
expect(eventHandler).toHaveBeenCalled()
|
||||
|
||||
window.removeEventListener('flasher:toastr:close', eventHandler)
|
||||
})
|
||||
|
||||
it('should dispatch flasher:toastr:hidden event when onHidden callback is called', () => {
|
||||
const eventHandler = vi.fn()
|
||||
window.addEventListener('flasher:toastr:hidden', eventHandler)
|
||||
|
||||
plugin.renderEnvelopes([createEnvelope()])
|
||||
|
||||
const calledOptions = mockToastr.success.mock.calls[0][2]
|
||||
calledOptions.onHidden()
|
||||
|
||||
expect(eventHandler).toHaveBeenCalled()
|
||||
|
||||
window.removeEventListener('flasher:toastr:hidden', eventHandler)
|
||||
})
|
||||
|
||||
it('should call original callbacks if provided', () => {
|
||||
const originalOnClick = vi.fn()
|
||||
|
||||
plugin.renderEnvelopes([createEnvelope({
|
||||
options: { onclick: originalOnClick },
|
||||
})])
|
||||
|
||||
const calledOptions = mockToastr.success.mock.calls[0][2]
|
||||
calledOptions.onclick()
|
||||
|
||||
expect(originalOnClick).toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -675,4 +675,99 @@ describe('FlasherPlugin', () => {
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('click event dispatching', () => {
|
||||
it('should dispatch flasher:theme:click event when notification is clicked', () => {
|
||||
const eventHandler = vi.fn()
|
||||
window.addEventListener('flasher:theme:click', eventHandler)
|
||||
|
||||
plugin.renderEnvelopes([createEnvelope({ message: 'Click me' })])
|
||||
|
||||
const notification = document.querySelector('.fl-notification') as HTMLElement
|
||||
expect(notification).toBeTruthy()
|
||||
|
||||
notification.click()
|
||||
|
||||
expect(eventHandler).toHaveBeenCalledWith(expect.objectContaining({
|
||||
detail: expect.objectContaining({
|
||||
envelope: expect.objectContaining({ message: 'Click me' }),
|
||||
}),
|
||||
}))
|
||||
|
||||
window.removeEventListener('flasher:theme:click', eventHandler)
|
||||
})
|
||||
|
||||
it('should dispatch theme-specific click event (flasher:theme:{name}:click)', () => {
|
||||
const eventHandler = vi.fn()
|
||||
window.addEventListener('flasher:theme:test:click', eventHandler)
|
||||
|
||||
plugin.renderEnvelopes([createEnvelope({
|
||||
message: 'Theme specific',
|
||||
metadata: { plugin: 'theme.test' },
|
||||
})])
|
||||
|
||||
const notification = document.querySelector('.fl-notification') as HTMLElement
|
||||
notification.click()
|
||||
|
||||
expect(eventHandler).toHaveBeenCalledWith(expect.objectContaining({
|
||||
detail: expect.objectContaining({
|
||||
envelope: expect.objectContaining({ message: 'Theme specific' }),
|
||||
}),
|
||||
}))
|
||||
|
||||
window.removeEventListener('flasher:theme:test:click', eventHandler)
|
||||
})
|
||||
|
||||
it('should dispatch both generic and specific events on click', () => {
|
||||
const genericHandler = vi.fn()
|
||||
const specificHandler = vi.fn()
|
||||
window.addEventListener('flasher:theme:click', genericHandler)
|
||||
window.addEventListener('flasher:theme:test:click', specificHandler)
|
||||
|
||||
plugin.renderEnvelopes([createEnvelope({
|
||||
metadata: { plugin: 'theme.test' },
|
||||
})])
|
||||
|
||||
const notification = document.querySelector('.fl-notification') as HTMLElement
|
||||
notification.click()
|
||||
|
||||
expect(genericHandler).toHaveBeenCalled()
|
||||
expect(specificHandler).toHaveBeenCalled()
|
||||
|
||||
window.removeEventListener('flasher:theme:click', genericHandler)
|
||||
window.removeEventListener('flasher:theme:test:click', specificHandler)
|
||||
})
|
||||
|
||||
it('should not dispatch click event when close button is clicked', () => {
|
||||
const eventHandler = vi.fn()
|
||||
window.addEventListener('flasher:theme:click', eventHandler)
|
||||
|
||||
plugin.renderEnvelopes([createEnvelope()])
|
||||
|
||||
const closeButton = document.querySelector('.fl-close') as HTMLElement
|
||||
expect(closeButton).toBeTruthy()
|
||||
|
||||
closeButton.click()
|
||||
|
||||
expect(eventHandler).not.toHaveBeenCalled()
|
||||
|
||||
window.removeEventListener('flasher:theme:click', eventHandler)
|
||||
})
|
||||
|
||||
it('should handle flasher plugin alias correctly', () => {
|
||||
const eventHandler = vi.fn()
|
||||
window.addEventListener('flasher:theme:flasher:click', eventHandler)
|
||||
|
||||
plugin.renderEnvelopes([createEnvelope({
|
||||
metadata: { plugin: 'flasher' },
|
||||
})])
|
||||
|
||||
const notification = document.querySelector('.fl-notification') as HTMLElement
|
||||
notification.click()
|
||||
|
||||
expect(eventHandler).toHaveBeenCalled()
|
||||
|
||||
window.removeEventListener('flasher:theme:flasher:click', eventHandler)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user