Passed
Push — master ( c803c1...00f1f1 )
by Eric
13:27
created

StringsTest::camelCaseProvider()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 39
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 1 Features 0
Metric Value
cc 1
eloc 19
nc 1
nop 0
dl 0
loc 39
rs 9.6333
c 2
b 1
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * Utility - Collection of various PHP utility functions.
7
 *
8
 * @author    Eric Sizemore <[email protected]>
9
 *
10
 * @version   2.0.0
11
 *
12
 * @copyright (C) 2017 - 2024 Eric Sizemore
13
 * @license   The MIT License (MIT)
14
 *
15
 * Copyright (C) 2017 - 2024 Eric Sizemore <https://www.secondversion.com>.
16
 *
17
 * Permission is hereby granted, free of charge, to any person obtaining a copy
18
 * of this software and associated documentation files (the "Software"), to
19
 * deal in the Software without restriction, including without limitation the
20
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
21
 * sell copies of the Software, and to permit persons to whom the Software is
22
 * furnished to do so, subject to the following conditions:
23
 *
24
 * The above copyright notice and this permission notice shall be included in
25
 * all copies or substantial portions of the Software.
26
 *
27
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
28
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
29
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
30
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
31
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
32
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
33
 * THE SOFTWARE.
34
 */
35
36
namespace Esi\Utility\Tests;
37
38
use Esi\Utility\Environment;
39
use Esi\Utility\Strings;
40
use InvalidArgumentException;
41
use Iterator;
42
use PHPUnit\Framework\Attributes\CoversClass;
43
use PHPUnit\Framework\Attributes\DataProvider;
44
use PHPUnit\Framework\TestCase;
45
use Random\RandomException;
46
47
/**
48
 * String utility tests.
49
 *
50
 * @internal
51
 */
52
#[CoversClass(Strings::class)]
53
class StringsTest extends TestCase
54
{
55
    /**
56
     * Test Strings::getEncoding().
57
     */
58
    public function testGetEncoding(): void
59
    {
60
        self::assertSame('UTF-8', Strings::getEncoding());
61
    }
62
63
    /**
64
     * Test Strings::setEncoding().
65
     */
66
    public function testSetEncoding(): void
67
    {
68
        // With no ini update.
69
        Strings::setEncoding('UCS-2');
70
71
        self::assertSame('UCS-2', Strings::getEncoding());
72
73
        Strings::setEncoding('UTF-8');
74
75
        // With ini update.
76
        Strings::setEncoding('UCS-2', true);
77
78
        self::assertSame('UCS-2', Strings::getEncoding());
79
        self::assertSame('UCS-2', Environment::iniGet('default_charset'));
80
        self::assertSame('UCS-2', Environment::iniGet('internal_encoding'));
81
82
        Strings::setEncoding('UTF-8', true);
83
    }
84
85
    /**
86
     * Test Strings::title().
87
     */
88
    public function testTitle(): void
89
    {
90
        $title = Strings::title('Mary had A little lamb and She Loved it so');
91
        self::assertSame('Mary Had A Little Lamb And She Loved It So', $title);
92
    }
93
94
    /**
95
     * Test Strings::lower().
96
     */
97
    public function testLower(): void
98
    {
99
        self::assertSame('test', Strings::lower('tESt'));
100
        self::assertSame('test', Strings::lower('TEST'));
101
    }
102
103
    /**
104
     * Test Strings::upper().
105
     */
106
    public function testUpper(): void
107
    {
108
        self::assertSame('TEST', Strings::upper('teSt'));
109
    }
110
111
    /**
112
     * Test Strings::substr().
113
     */
114
    public function testSubstr(): void
115
    {
116
        self::assertSame('f', Strings::substr('abcdef', -1));
117
    }
118
119
    /**
120
     * Test Strings::lcfirst().
121
     */
122
    public function testLcfirst(): void
123
    {
124
        self::assertSame('test', Strings::lcfirst('Test'));
125
        self::assertSame('tEST', Strings::lcfirst('TEST'));
126
    }
127
128
    /**
129
     * Test Strings::ucfirst().
130
     */
131
    public function testUcfirst(): void
132
    {
133
        self::assertSame('Test', Strings::ucfirst('test'));
134
        self::assertSame('TEsT', Strings::ucfirst('tEsT'));
135
    }
136
137
    /**
138
     * Test Strings::strcasecmp().
139
     */
140
    public function testStrcasecmp(): void
141
    {
142
        // Returns -1 if string1 is less than string2; 1 if string1 is greater than string2, and 0 if they are equal.
143
        $str1 = 'test';
144
        $str2 = 'Test';
145
146
        self::assertSame(0, Strings::strcasecmp($str1, $str2));
147
148
        $str1 = 'tes';
149
150
        self::assertSame(-1, Strings::strcasecmp($str1, $str2));
151
152
        $str1 = 'testing';
153
154
        self::assertSame(1, Strings::strcasecmp($str1, $str2));
155
    }
156
157
    /**
158
     * Test Strings::beginsWith().
159
     */
160
    public function testBeginsWith(): void
161
    {
162
        self::assertTrue(Strings::beginsWith('this is a test', 'this'));
163
        self::assertFalse(Strings::beginsWith('this is a test', 'test'));
164
165
        self::assertTrue(Strings::beginsWith('THIS IS A TEST', 'this', true));
166
        self::assertFalse(Strings::beginsWith('THIS IS A TEST', 'test', true));
167
168
        self::assertTrue(Strings::beginsWith('THIS IS A TEST', 'this', true, true));
169
        self::assertFalse(Strings::beginsWith('THIS IS A TEST', 'test', true, true));
170
    }
171
172
    /**
173
     * Test Strings::endsWith().
174
     */
175
    public function testEndsWith(): void
176
    {
177
        self::assertTrue(Strings::endsWith('this is a test', 'test'));
178
        self::assertFalse(Strings::endsWith('this is a test', 'this'));
179
180
        self::assertTrue(Strings::endsWith('THIS IS A TEST', 'test', true));
181
        self::assertFalse(Strings::endsWith('THIS IS A TEST', 'this', true));
182
183
        self::assertTrue(Strings::endsWith('THIS IS A TEST', 'test', true, true));
184
        self::assertFalse(Strings::endsWith('THIS IS A TEST', 'this', true, true));
185
    }
186
187
    /**
188
     * Test Strings::doesContain().
189
     */
190
    public function testDoesContain(): void
191
    {
192
        self::assertTrue(Strings::doesContain('start a string', 'a string'));
193
        self::assertFalse(Strings::doesContain('start a string', 'starting'));
194
195
        self::assertTrue(Strings::doesContain('START A STRING', 'a string', true));
196
        self::assertFalse(Strings::doesContain('START A STRING', 'starting', true));
197
198
        self::assertTrue(Strings::doesContain('START A STRING', 'a string', true, true));
199
        self::assertFalse(Strings::doesContain('START A STRING', 'starting', true, true));
200
    }
201
202
    /**
203
     * Test Strings::doesNotContain().
204
     */
205
    public function testDoesNotContain(): void
206
    {
207
        self::assertTrue(Strings::doesNotContain('start a string', 'stringly'));
208
        self::assertFalse(Strings::doesNotContain('start a string', 'string'));
209
210
        self::assertTrue(Strings::doesNotContain('START A STRING', 'stringly', true));
211
        self::assertFalse(Strings::doesNotContain('START A STRING', 'string', true));
212
213
        self::assertTrue(Strings::doesNotContain('START A STRING', 'stringly', true, true));
214
        self::assertFalse(Strings::doesNotContain('START A STRING', 'string', true, true));
215
    }
216
217
    /**
218
     * Provides data for testCamelCase().
219
     *
220
     * Shoutout to Daniel St. Jules (https://github.com/danielstjules/Stringy/) for
221
     * inspiration for this function. This function is based on Stringy/Test/camelizeProvider().
222
     */
223
    public static function camelCaseProvider(): Iterator
224
    {
225
        yield ['camelCase', 'CamelCase'];
226
227
        yield ['camelCase', 'Camel-Case'];
228
229
        yield ['camelCase', 'camel case'];
230
231
        yield ['camelCase', 'camel -case'];
232
233
        yield ['camelCase', 'camel - case'];
234
235
        yield ['camelCase', 'camel_case'];
236
237
        yield ['camelCTest', 'camel c test'];
238
239
        yield ['stringWith1Number', 'string_with1number'];
240
241
        yield ['stringWith22Numbers', 'string-with-2-2 numbers'];
242
243
        yield ['dataRate', 'data_rate'];
244
245
        yield ['backgroundColor', 'background-color'];
246
247
        yield ['yesWeCan', 'yes_we_can'];
248
249
        yield ['mozSomething', '-moz-something'];
250
251
        yield ['carSpeed', '_car_speed_'];
252
253
        yield ['serveHTTP', 'ServeHTTP'];
254
255
        yield ['1Camel2Case', '1camel2case'];
256
257
        yield ['camelΣase', 'camel σase', 'UTF-8'];
258
259
        yield ['στανιλCase', 'Στανιλ case', 'UTF-8'];
260
261
        yield ['σamelCase', 'σamel  Case', 'UTF-8'];
262
    }
263
264
    /**
265
     * Test Strings::camelCase().
266
     */
267
    #[DataProvider('camelCaseProvider')]
268
    public function testCamelCase(string $expected, string $string, ?string $encoding = null): void
269
    {
270
        if ($encoding !== null) {
271
            Strings::setEncoding($encoding);
272
        }
273
274
        $result = Strings::camelCase($string);
275
276
        self::assertSame($expected, $result);
277
    }
278
279
    /**
280
     * Test Strings::ascii().
281
     */
282
    public function testAscii(): void
283
    {
284
        self::assertSame('AA ', Strings::ascii("ǍǺ\xE2\x80\x87"));
285
    }
286
287
    /**
288
     * Test Strings::ascii().
289
     */
290
    public function testAsciiWithLanguage(): void
291
    {
292
        self::assertSame('aaistAAIST', Strings::ascii('ăâîșțĂÂÎȘȚ', 'ro'));
293
    }
294
295
    /**
296
     * Test Strings::slugify().
297
     */
298
    public function testSlugify(): void
299
    {
300
        self::assertSame('a-simple-title', Strings::slugify('A simple title'));
301
        self::assertSame('this-post-it-has-a-dash', Strings::slugify('This post -- it has a dash'));
302
        self::assertSame('123-1251251', Strings::slugify('123----1251251'));
303
304
        self::assertSame('a_simple_title', Strings::slugify('A simple title', '_'));
305
        self::assertSame('this_post_it_has_a_dash', Strings::slugify('This post -- it has a dash', '_'));
306
        self::assertSame('123_1251251', Strings::slugify('123----1251251', '_'));
307
308
        self::assertSame('a-simple-title', Strings::slugify('a-simple-title'));
309
        self::assertSame('', Strings::slugify(' '));
310
311
        self::assertSame('this-is-a-simple-title', Strings::slugify('Țhîș îș ă șîmple țîțle', '-', 'ro'));
312
    }
313
314
    /**
315
     * Test Strings::randomBytes().
316
     */
317
    public function testRandomBytes(): void
318
    {
319
        $bytes = Strings::randomBytes(8);
320
        self::assertNotEmpty($bytes);
321
322
        self::expectException(RandomException::class);
323
        Strings::randomBytes(-10); // @phpstan-ignore-line
324
    }
325
326
    /**
327
     * Test Strings::randomString().
328
     */
329
    public function testRandomString(): void
330
    {
331
        $str = Strings::randomString(16);
332
        self::assertSame(16, Strings::length($str));
333
334
        self::expectException(RandomException::class);
335
        Strings::randomString(-10);
336
    }
337
338
    /**
339
     * Test Strings::validEmail().
340
     */
341
    public function testValidEmail(): void
342
    {
343
        self::assertTrue(Strings::validEmail('[email protected]'));
344
        self::assertTrue(Strings::validEmail('[email protected]'));
345
        self::assertTrue(Strings::validEmail('[email protected]'));
346
        self::assertFalse(Strings::validEmail('j@'));
347
    }
348
349
    /**
350
     * Test Strings::validJson().
351
     */
352
    public function testValidJson(): void
353
    {
354
        self::assertTrue(Strings::validJson('{ "test": { "foo": "bar" } }'));
355
        self::assertFalse(Strings::validJson('{ "": "": "" } }'));
356
    }
357
358
    /**
359
     * Test Strings::obscureEmail().
360
     */
361
    public function testObscureEmail(): void
362
    {
363
        self::assertSame(
364
            '&#97;&#100;&#109;&#105;&#110;&#64;&#115;&#101;&#99;&#111;&#110;&#100;&#118;&#101;&#114;&#115;&#105;&#111;&#110;&#46;&#99;&#111;&#109;',
365
            Strings::obscureEmail('[email protected]')
366
        );
367
368
        self::expectException(InvalidArgumentException::class);
369
        Strings::obscureEmail('thisisnotvalid&!--');
370
    }
371
372
    /**
373
     * Test Strings::guid().
374
     */
375
    public function testGuid(): void
376
    {
377
        $guid = Strings::guid();
378
        self::assertMatchesRegularExpression('/^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i', $guid);
379
    }
380
}
381