Passed
Pull Request — master (#113)
by
unknown
02:30
created

FlatfileStorageTest::testWithDefaultOptionsMissingPeriodOnImageExtension()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 17
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 9
dl 0
loc 17
rs 9.9666
c 1
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * This file is part of Esi\SimpleCounter.
7
 *
8
 * (c) Eric Sizemore <https://github.com/ericsizemore>
9
 *
10
 * This source file is subject to the MIT license. For the full copyright and
11
 * license information, please view the LICENSE file that was distributed with
12
 * this source code.
13
 */
14
15
namespace Esi\SimpleCounter\Tests;
16
17
use Esi\SimpleCounter\Configuration\FlatfileConfiguration;
18
use Esi\SimpleCounter\Storage\FlatfileStorage;
19
use Esi\Utility\Arrays;
20
use Esi\Utility\Environment;
21
use Esi\Utility\Filesystem;
22
use PHPUnit\Framework\Attributes\CoversClass;
23
use PHPUnit\Framework\Attributes\TestDox;
24
use PHPUnit\Framework\TestCase;
25
use Symfony\Component\OptionsResolver\Exception\InvalidOptionsException;
26
27
use function str_starts_with;
28
29
use const DIRECTORY_SEPARATOR;
30
31
/**
32
 * @internal
33
 *
34
 * @psalm-suppress NullReference
35
 */
36
#[CoversClass(FlatfileStorage::class)]
37
#[CoversClass(FlatfileConfiguration::class)]
38
class FlatfileStorageTest extends TestCase
39
{
40
    /**
41
     * @var string[]
42
     */
43
    private static array $logFiles;
44
45
    /**
46
     * @var string[]
47
     */
48
    private static array $testDirectories;
49
50
    /**
51
     * @var string[]
52
     */
53
    private static array $testInvalidDirectories;
54
55
    #[\Override]
56
    protected function setUp(): void
57
    {
58
        Arrays::set($_SERVER, 'REMOTE_ADDR', '127.0.0.1');
59
60
        self::$testDirectories = [
61
            'logDir'   => \sprintf('%s%s%s', \dirname(__FILE__, 2), DIRECTORY_SEPARATOR, 'logs'),
62
            'imageDir' => \sprintf('%s%s%s', \dirname(__FILE__, 2), DIRECTORY_SEPARATOR, 'images'),
63
        ];
64
65
        self::$testInvalidDirectories = [
66
            'logDir'   => '/this/should/not/exist/logs',
67
            'imageDir' => '/this/should/not/exist/images',
68
        ];
69
70
        self::$logFiles = [
71
            'countFile' => \sprintf('%s%s%s', self::$testDirectories['logDir'], DIRECTORY_SEPARATOR, 'counter.json'),
72
            'ipFile'    => \sprintf('%s%s%s', self::$testDirectories['logDir'], DIRECTORY_SEPARATOR, 'ips.json'),
73
        ];
74
    }
75
76
    #[\Override]
77
    protected function tearDown(): void
78
    {
79
        Arrays::set($_SERVER, 'REMOTE_ADDR', Environment::var('REMOTE_ADDR', null));
80
81
        Filesystem::fileWrite(self::$logFiles['countFile'], '{"currentCount":"0"}');
82
        Filesystem::fileWrite(self::$logFiles['ipFile'], '{"ipList":[""]}');
83
    }
84
85
    public function testDoNotTrack(): void
86
    {
87
        $_SERVER['HTTP_DNT'] = 1;
88
89
        $counter = new FlatfileStorage(FlatfileConfiguration::initOptions(
90
            [
91
                'logDir'   => self::$testDirectories['logDir'],
92
                'imageDir' => self::$testDirectories['imageDir'],
93
                'honorDnt' => true,
94
            ]
95
        ));
96
97
        $count = $counter->display();
98
        self::assertStringEndsWith('0', $count);
99
100
        $counter->display();
101
        $counter->display();
102
        $count = $counter->display();
103
        self::assertStringEndsWith('0', $count);
104
105
        $_SERVER['HTTP_DNT'] = 0;
106
        $count               = $counter->display();
107
        self::assertStringEndsWith('1', $count);
108
    }
109
110
    #[TestDox('getOption is able to return the value of a given option.')]
111
    public function testGetOption(): void
112
    {
113
        $counter = new FlatfileStorage(FlatfileConfiguration::initOptions(
114
            [
115
                'logDir'   => self::$testDirectories['logDir'],
116
                'imageDir' => self::$testDirectories['imageDir'],
117
            ]
118
        ));
119
120
        self::assertSame(self::$testDirectories['logDir'], $counter->getOption('logDir'));
121
    }
122
123
    #[TestDox('An exception of InvalidOptionsException is thrown when providing an invalid location to the count file.')]
124
    public function testInvalidLocationForCounterFile(): void
125
    {
126
        $this->expectException(InvalidOptionsException::class);
127
        new FlatfileStorage(FlatfileConfiguration::initOptions(
128
            [
129
                'logDir'    => self::$testDirectories['logDir'],
130
                'imageDir'  => self::$testDirectories['imageDir'],
131
                'countFile' => 'counters.json',
132
            ]
133
        ));
134
    }
135
136
    #[TestDox('An exception of InvalidOptionsException is thrown when providing an invalid location to the ip file.')]
137
    public function testInvalidLocationForIpFile(): void
138
    {
139
        $this->expectException(InvalidOptionsException::class);
140
        new FlatfileStorage(FlatfileConfiguration::initOptions(
141
            [
142
                'logDir'   => self::$testDirectories['logDir'],
143
                'imageDir' => self::$testDirectories['imageDir'],
144
                'ipFile'   => 'iplist.json',
145
            ]
146
        ));
147
    }
148
149
    #[TestDox('An exception of InvalidOptionsException is thrown when providing the wrong file extension/format for the count file.')]
150
    public function testInvalidOptionForCountFile(): void
151
    {
152
        $this->expectException(InvalidOptionsException::class);
153
        new FlatfileStorage(FlatfileConfiguration::initOptions(
154
            [
155
                'logDir'    => self::$testDirectories['logDir'],
156
                'imageDir'  => self::$testDirectories['imageDir'],
157
                'countFile' => 'counter.txt',
158
            ]
159
        ));
160
    }
161
162
    #[TestDox('New instance with a non-existing directory for "imageDir" throws InvalidOptionsException')]
163
    public function testInvalidOptionForImageDirectory(): void
164
    {
165
        $this->expectException(InvalidOptionsException::class);
166
        new FlatfileStorage(FlatfileConfiguration::initOptions(
167
            [
168
                'logDir'   => self::$testDirectories['logDir'],
169
                'imageDir' => self::$testInvalidDirectories['imageDir'],
170
            ]
171
        ));
172
    }
173
174
    #[TestDox('An exception of InvalidOptionsException is thrown when providing the wrong file extension/format for the ip file.')]
175
    public function testInvalidOptionForIpFile(): void
176
    {
177
        $this->expectException(InvalidOptionsException::class);
178
        new FlatfileStorage(FlatfileConfiguration::initOptions(
179
            [
180
                'logDir'    => self::$testDirectories['logDir'],
181
                'imageDir'  => self::$testDirectories['imageDir'],
182
                'countFile' => 'ips.txt',
183
            ]
184
        ));
185
    }
186
187
    #[TestDox('New instance with a non-existing directory for "logDir" throws InvalidOptionsException')]
188
    public function testInvalidOptionForLogDirectory(): void
189
    {
190
        $this->expectException(InvalidOptionsException::class);
191
        new FlatfileStorage(FlatfileConfiguration::initOptions(
192
            [
193
                'logDir'   => self::$testInvalidDirectories['logDir'],
194
                'imageDir' => self::$testDirectories['imageDir'],
195
            ]
196
        ));
197
    }
198
199
    #[TestDox('Instantiating the FlatfileStorage with a custom visitorTextString properly displays the count with that text.')]
200
    public function testWithCustomVisitorTextString(): void
201
    {
202
        $counter = new FlatfileStorage(FlatfileConfiguration::initOptions(
203
            [
204
                'logDir'            => self::$testDirectories['logDir'],
205
                'imageDir'          => self::$testDirectories['imageDir'],
206
                'visitorTextString' => 'Count: #%s',
207
            ]
208
        ));
209
210
        $count = $counter->display();
211
        self::assertMatchesRegularExpression('/[A-Za-z]+:\s+#[0-9]+/i', $count);
212
    }
213
214
    #[TestDox('Instantiating the FlatfileStorage with a custom visitorTextString not including %s throws an exception.')]
215
    public function testWithCustomVisitorTextStringInvalidFormat(): void
216
    {
217
        $this->expectException(InvalidOptionsException::class);
218
        new FlatfileStorage(FlatfileConfiguration::initOptions(
219
            [
220
                'logDir'            => self::$testDirectories['logDir'],
221
                'imageDir'          => self::$testDirectories['imageDir'],
222
                'visitorTextString' => 'Count: #',
223
            ]
224
        ));
225
    }
226
227
    #[TestDox('Instantiating the FlatfileStorage with default options works properly and accurately.')]
228
    public function testWithDefaultOptions(): void
229
    {
230
        $counter = new FlatfileStorage(FlatfileConfiguration::initOptions(
231
            [
232
                'logDir'   => self::$testDirectories['logDir'],
233
                'imageDir' => self::$testDirectories['imageDir'],
234
            ]
235
        ));
236
237
        $count    = $counter->display();
238
        $countTwo = $counter->display();
239
240
        self::assertNotEmpty($count);
241
        self::assertNotEmpty($countTwo);
242
        self::assertMatchesRegularExpression('/([A-Za-z]+( [A-Za-z]+)+)\s#[0-9]+/i', $count);
243
        self::assertMatchesRegularExpression('/([A-Za-z]+( [A-Za-z]+)+)\s#[0-9]+/i', $countTwo);
244
        self::assertSame($count, $countTwo);
245
    }
246
247
    #[TestDox('Instantiating the FlatfileStorage with a missing dot at the beginning of the imageExt adds the dot.')]
248
    public function testWithDefaultOptionsMissingPeriodOnImageExtension(): void
249
    {
250
        $counter = new FlatfileStorage(FlatfileConfiguration::initOptions(
251
            [
252
                'logDir'   => self::$testDirectories['logDir'],
253
                'imageDir' => self::$testDirectories['imageDir'],
254
                'imageExt' => 'png',
255
            ]
256
        ));
257
258
        self::assertSame('.png', $counter->getOption('imageExt'));
259
260
        $count = $counter->display();
261
262
        self::assertNotEmpty($count);
263
        self::assertMatchesRegularExpression('/([A-Za-z]+( [A-Za-z]+)+)\s#[0-9]+/i', $count);
264
    }
265
266
    #[TestDox('A new visitor (or IP) increments the counter.')]
267
    public function testWithDefaultOptionsNewVisitor(): void
268
    {
269
        $counter = new FlatfileStorage(FlatfileConfiguration::initOptions(
270
            [
271
                'logDir'   => self::$testDirectories['logDir'],
272
                'imageDir' => self::$testDirectories['imageDir'],
273
            ]
274
        ));
275
276
        $oldCount = $counter->display();
277
278
        Arrays::set($_SERVER, 'REMOTE_ADDR', '127.0.0.2');
279
280
        $newCount = $counter->display();
281
282
        self::assertNotEmpty($oldCount);
283
        self::assertNotEmpty($newCount);
284
        self::assertNotSame($oldCount, $newCount);
285
        self::assertMatchesRegularExpression('/([A-Za-z]+( [A-Za-z]+)+)\s#[0-9]+/i', $oldCount);
286
        self::assertMatchesRegularExpression('/([A-Za-z]+( [A-Za-z]+)+)\s#[0-9]+/i', $newCount);
287
288
        Arrays::set($_SERVER, 'REMOTE_ADDR', '127.0.0.1');
289
    }
290
291
    #[TestDox('Instantiating the FlatfileStorage with asImage set to true will display the count as images.')]
292
    public function testWithDefaultOptionsWithImages(): void
293
    {
294
        $counter = new FlatfileStorage(FlatfileConfiguration::initOptions(
295
            [
296
                'logDir'   => self::$testDirectories['logDir'],
297
                'imageDir' => self::$testDirectories['imageDir'],
298
                'asImage'  => true,
299
            ]
300
        ));
301
302
        $count = $counter->display();
303
304
        self::assertNotEmpty($count);
305
        self::assertTrue(str_starts_with($count, '<img '));
306
    }
307
308
    #[TestDox('Instantiating the FlatfileStorage with uniqueOnly set to false properly increments the count.')]
309
    public function testWithDefaultOptionsWithoutUniqueOnly(): void
310
    {
311
        $counter = new FlatfileStorage(FlatfileConfiguration::initOptions(
312
            [
313
                'logDir'     => self::$testDirectories['logDir'],
314
                'imageDir'   => self::$testDirectories['imageDir'],
315
                'uniqueOnly' => false,
316
            ]
317
        ));
318
319
        $count    = $counter->display();
320
        $countTwo = $counter->display();
321
322
        self::assertNotSame($count, $countTwo);
323
        self::assertMatchesRegularExpression('/([A-Za-z]+( [A-Za-z]+)+)\s#[0-9]+/i', $count);
324
        self::assertMatchesRegularExpression('/([A-Za-z]+( [A-Za-z]+)+)\s#[0-9]+/i', $countTwo);
325
    }
326
}
327