visible())->toBeTrue(); }); test('a listener can hide attribution', function () { Event::listen(ResolvingAttribution::class, function (ResolvingAttribution $event): void { $event->visible = false; }); expect(app(Attribution::class)->visible())->toBeFalse(); }); test('one listener declining to hide does not overrule another that hides', function () { Event::listen(ResolvingAttribution::class, function (ResolvingAttribution $event): void { $event->visible = false; }); // Registered second and does nothing — a listener with no opinion // must not undo the first one's answer, which is why the payload is // documented as only ever moving toward false. Event::listen(ResolvingAttribution::class, function (ResolvingAttribution $event): void { // no-op }); expect(app(Attribution::class)->visible())->toBeFalse(); }); test('the answer is resolved per call, never cached', function () { expect(app(Attribution::class)->visible())->toBeTrue(); Event::listen(ResolvingAttribution::class, function (ResolvingAttribution $event): void { $event->visible = false; }); // A queue worker lives for hours across many messages; an answer // memoised on the service or the container would keep sending mail // with a footer the operator turned off that morning. expect(app(Attribution::class)->visible())->toBeFalse(); });