Skip to content

Commit 287a924

Browse files
Add ability to fake (#12)
1 parent 2902b8d commit 287a924

File tree

7 files changed

+436
-9
lines changed

7 files changed

+436
-9
lines changed

src/Facades/Fakes/SegmentFake.php

Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
<?php
2+
3+
namespace SlashEquip\LaravelSegment\Facades\Fakes;
4+
5+
use Closure;
6+
use Illuminate\Support\Collection;
7+
use PHPUnit\Framework\Assert as PHPUnit;
8+
use SlashEquip\LaravelSegment\Contracts\CanBeIdentifiedForSegment;
9+
use SlashEquip\LaravelSegment\Contracts\CanBeSentToSegment;
10+
use SlashEquip\LaravelSegment\PendingUserSegment;
11+
use SlashEquip\LaravelSegment\SegmentServiceContract;
12+
use SlashEquip\LaravelSegment\SimpleSegmentEvent;
13+
use SlashEquip\LaravelSegment\SimpleSegmentIdentify;
14+
15+
class SegmentFake implements SegmentServiceContract
16+
{
17+
private CanBeIdentifiedForSegment $user;
18+
19+
private ?array $context = [];
20+
21+
private array $events = [];
22+
23+
private array $identities = [];
24+
25+
public function setGlobalUser(CanBeIdentifiedForSegment $globalUser): void
26+
{
27+
$this->user = $globalUser;
28+
}
29+
30+
public function setGlobalContext(array $globalContext): void
31+
{
32+
$this->context = $globalContext;
33+
}
34+
35+
public function identify(?array $identifyData = []): void
36+
{
37+
$this->identities[] = new SimpleSegmentIdentify($this->user, $identifyData);
38+
}
39+
40+
public function track(string $event, array $eventData = null): void
41+
{
42+
$this->events[] = new SimpleSegmentEvent($this->user, $event, $eventData);
43+
}
44+
45+
public function forUser(CanBeIdentifiedForSegment $user): PendingUserSegment
46+
{
47+
$this->user = $user;
48+
49+
return new PendingUserSegment($this, $user);
50+
}
51+
52+
public function push(CanBeSentToSegment $segment): void
53+
{
54+
if ($segment instanceof SimpleSegmentIdentify) {
55+
$this->identities[] = $segment;
56+
}
57+
58+
if ($segment instanceof SimpleSegmentEvent) {
59+
$this->events[] = $segment;
60+
}
61+
}
62+
63+
public function terminate(): void
64+
{
65+
}
66+
67+
public function assertIdentified(Closure|int $callback = null): void
68+
{
69+
if (is_numeric($callback)) {
70+
$this->assertIdentifiedTimes($callback);
71+
72+
return;
73+
}
74+
75+
PHPUnit::assertTrue(
76+
$this->identities($callback)->count() > 0,
77+
'The expected identities were not called.'
78+
);
79+
}
80+
81+
public function assertIdentifiedTimes(int $times = 1): void
82+
{
83+
$count = collect($this->identities)->count();
84+
85+
PHPUnit::assertSame(
86+
$times, $count,
87+
"The identity was called {$count} times instead of {$times} times."
88+
);
89+
}
90+
91+
public function assertNotIdentified(Closure $callback = null): void
92+
{
93+
PHPUnit::assertCount(
94+
0, $this->identities($callback),
95+
'The unexpected identity was called.'
96+
);
97+
}
98+
99+
public function assertNothingIdentified(): void
100+
{
101+
$identities = collect($this->identities);
102+
103+
PHPUnit::assertEmpty($identities, $identities->count().' events were found unexpectedly.');
104+
}
105+
106+
public function assertTracked(Closure|int $callback = null): void
107+
{
108+
if (is_numeric($callback)) {
109+
$this->assertTrackedTimes($callback);
110+
111+
return;
112+
}
113+
114+
PHPUnit::assertTrue(
115+
$this->events($callback)->count() > 0,
116+
'The expected events were not called.'
117+
);
118+
}
119+
120+
public function assertTrackedTimes(int $times = 1): void
121+
{
122+
$count = collect($this->events)->count();
123+
124+
PHPUnit::assertSame(
125+
$times, $count,
126+
"The event called {$count} times instead of {$times} times."
127+
);
128+
}
129+
130+
public function assertEventTracked(string $event, Closure|int $callback = null): void
131+
{
132+
PHPUnit::assertTrue(
133+
$this->events($callback, $event)->count() > 0,
134+
'The expected events were not called.'
135+
);
136+
}
137+
138+
public function assertNotTracked(Closure $callback = null): void
139+
{
140+
PHPUnit::assertCount(
141+
0, $this->events($callback),
142+
'The unexpected event was called.'
143+
);
144+
}
145+
146+
public function assertEventNotTracked(string $event, Closure|int $callback = null): void
147+
{
148+
PHPUnit::assertCount(
149+
0, $this->events($callback, $event),
150+
'The expected events were not called.'
151+
);
152+
}
153+
154+
public function assertNothingTracked(): void
155+
{
156+
$events = collect($this->events);
157+
158+
PHPUnit::assertEmpty($events, $events->count().' events were found unexpectedly.');
159+
}
160+
161+
private function identities(Closure $callback = null): Collection
162+
{
163+
$identities = collect($this->identities);
164+
165+
if ($identities->isEmpty()) {
166+
return collect();
167+
}
168+
169+
$callback = $callback ?: fn () => true;
170+
171+
return $identities->filter(fn (SimpleSegmentIdentify $identity) => $callback($identity));
172+
}
173+
174+
private function events(Closure $callback = null, string $event = null): Collection
175+
{
176+
$events = collect($this->events);
177+
178+
if ($events->isEmpty()) {
179+
return collect();
180+
}
181+
182+
$callback = $callback ?: fn () => true;
183+
184+
return $events
185+
->when($event, function (Collection $collection) use ($event) {
186+
return $collection->filter(function (SimpleSegmentEvent $segmentEvent) use ($event) {
187+
return $segmentEvent->toSegment()->event === $event;
188+
});
189+
})
190+
->filter(fn (SimpleSegmentEvent $event) => $callback($event));
191+
}
192+
}

src/Facades/Segment.php

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use Illuminate\Support\Facades\Facade;
66
use SlashEquip\LaravelSegment\Contracts\CanBeIdentifiedForSegment;
77
use SlashEquip\LaravelSegment\Contracts\CanBeSentToSegment;
8+
use SlashEquip\LaravelSegment\Facades\Fakes\SegmentFake;
89
use SlashEquip\LaravelSegment\PendingUserSegment;
910
use SlashEquip\LaravelSegment\SegmentService;
1011

@@ -17,10 +18,22 @@
1718
* @method static void push(CanBeSentToSegment $segment)
1819
* @method static void terminate()
1920
*/
21+
22+
/**
23+
* @see \SlashEquip\LaravelSegment\SegmentService
24+
* @see \SlashEquip\LaravelSegment\Facades\Fakes\SegmentFake
25+
*/
2026
class Segment extends Facade
2127
{
22-
protected static function getFacadeAccessor()
28+
protected static function getFacadeAccessor(): string
2329
{
2430
return SegmentService::class;
2531
}
32+
33+
public static function fake(): SegmentFake
34+
{
35+
return tap(new SegmentFake(), function (SegmentFake $fake) {
36+
static::swap($fake);
37+
});
38+
}
2639
}

src/PendingUserSegment.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@
66

77
class PendingUserSegment
88
{
9-
private SegmentService $service;
9+
private SegmentServiceContract $service;
1010

1111
private CanBeIdentifiedForSegment $user;
1212

13-
public function __construct(SegmentService $service, CanBeIdentifiedForSegment $user)
13+
public function __construct(SegmentServiceContract $service, CanBeIdentifiedForSegment $user)
1414
{
1515
$this->service = $service;
1616
$this->user = $user;
@@ -19,7 +19,7 @@ public function __construct(SegmentService $service, CanBeIdentifiedForSegment $
1919
/**
2020
* @param array<string, mixed>|null $eventData
2121
*/
22-
public function track(string $event, ?array $eventData = null): void
22+
public function track(string $event, array $eventData = null): void
2323
{
2424
$this->service->push(
2525
new SimpleSegmentEvent($this->user, $event, $eventData)
@@ -29,7 +29,7 @@ public function track(string $event, ?array $eventData = null): void
2929
/**
3030
* @param array<string, mixed>|null $identifyData
3131
*/
32-
public function identify(?array $identifyData = null): void
32+
public function identify(array $identifyData = null): void
3333
{
3434
$this->service->push(
3535
new SimpleSegmentIdentify($this->user, $identifyData)

src/SegmentService.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
use SlashEquip\LaravelSegment\ValueObjects\SegmentPayload;
1111
use Throwable;
1212

13-
class SegmentService
13+
class SegmentService implements SegmentServiceContract
1414
{
1515
const BATCH_URL = 'https://api.segment.io/v1/batch';
1616

@@ -46,7 +46,7 @@ public function setGlobalContext(array $globalContext): void
4646
/**
4747
* @param array<string, mixed> $eventData
4848
*/
49-
public function track(string $event, ?array $eventData = null): void
49+
public function track(string $event, array $eventData = null): void
5050
{
5151
$this->push(
5252
new SimpleSegmentEvent($this->globalUser, $event, $eventData)
@@ -56,7 +56,7 @@ public function track(string $event, ?array $eventData = null): void
5656
/**
5757
* @param array<string, mixed> $identifyData
5858
*/
59-
public function identify(?array $identifyData = null): void
59+
public function identify(array $identifyData = null): void
6060
{
6161
$this->push(
6262
new SimpleSegmentIdentify($this->globalUser, $identifyData)

src/SegmentServiceContract.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
namespace SlashEquip\LaravelSegment;
4+
5+
use SlashEquip\LaravelSegment\Contracts\CanBeIdentifiedForSegment;
6+
use SlashEquip\LaravelSegment\Contracts\CanBeSentToSegment;
7+
8+
interface SegmentServiceContract
9+
{
10+
public function setGlobalUser(CanBeIdentifiedForSegment $globalUser): void;
11+
12+
public function setGlobalContext(array $globalContext): void;
13+
14+
public function track(string $event, array $eventData = null): void;
15+
16+
public function identify(array $identifyData = null): void;
17+
18+
public function forUser(CanBeIdentifiedForSegment $user): PendingUserSegment;
19+
20+
public function push(CanBeSentToSegment $segment): void;
21+
22+
public function terminate(): void;
23+
}

src/ValueObjects/SegmentPayload.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ public function __construct(
1919
public readonly SegmentPayloadType $type,
2020
public readonly ?string $event = null,
2121
public readonly array $data = [],
22-
?DateTime $timestamp = null
22+
DateTime $timestamp = null
2323
) {
2424
$this->timestamp = $timestamp ?: new DateTime();
2525
$this->timestamp->setTimezone(new DateTimeZone('UTC'));

0 commit comments

Comments
 (0)