Completed
Push — main ( cc6aaa...650471 )
by Colin
16s queued 11s
created

IndentationTest::testIndent()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 2
c 1
b 0
f 0
nc 1
nop 3
dl 0
loc 4
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the colinodell/indentation package.
7
 *
8
 * (c) Colin O'Dell <[email protected]>
9
 *
10
 * Forked from detect-indent,
11
 * (c) Sindre Sorhus <[email protected]> (https://sindresorhus.com)
12
 *
13
 * For the full copyright and license information, please view the LICENSE
14
 * file that was distributed with this source code.
15
 */
16
17
namespace ColinODell\Indentation\Tests;
18
19
use ColinODell\Indentation\Indentation;
20
use PHPUnit\Framework\TestCase;
21
22
final class IndentationTest extends TestCase
23
{
24
    public function testConstructorAndGetters(): void
25
    {
26
        $indentation = new Indentation(4, Indentation::TYPE_SPACE);
27
28
        self::assertSame(4, $indentation->getAmount());
29
        self::assertSame(Indentation::TYPE_SPACE, $indentation->getType());
30
        self::assertSame('    ', (string) $indentation);
31
32
        $indentation = new Indentation(1, Indentation::TYPE_TAB);
33
34
        self::assertSame(1, $indentation->getAmount());
35
        self::assertSame(Indentation::TYPE_TAB, $indentation->getType());
36
        self::assertSame("\t", (string) $indentation);
37
    }
38
39
    /**
40
     * @dataProvider provideCasesForTestDetect
41
     */
42
    public function testDetect(string $filename, Indentation $expected, string $asString): void
43
    {
44
        $actual = Indentation::detect($filename);
45
        self::assertEquals($expected, $actual);
46
        self::assertSame($asString, (string) $actual);
47
    }
48
49
    /**
50
     * @return iterable<array<mixed>>
51
     */
52
    public function provideCasesForTestDetect(): iterable
53
    {
54
        yield 'Detect space indentation' => [
55
            $this->loadFixture('space.js'),
56
            new Indentation(4, Indentation::TYPE_SPACE),
57
            '    ',
58
        ];
59
60
        yield 'Detect tab indentation' => [
61
            $this->loadFixture('tab.js'),
62
            new Indentation(1, Indentation::TYPE_TAB),
63
            "\t",
64
        ];
65
66
        yield 'Detect multiple tabs' => [
67
            $this->loadFixture('tab-four.js'),
68
            new Indentation(4, Indentation::TYPE_TAB),
69
            "\t\t\t\t",
70
        ];
71
72
        yield 'Detect equal tabs and spaces' => [
73
            $this->loadFixture('mixed-tab.js'),
74
            new Indentation(1, Indentation::TYPE_TAB),
75
            "\t",
76
        ];
77
78
        yield 'Detect indent of a file with mostly spaces' => [
79
            $this->loadFixture('mixed-space.js'),
80
            new Indentation(4, Indentation::TYPE_SPACE),
81
            '    ',
82
        ];
83
84
        yield 'Detect indent of a weirdly indented vendor prefixed CSS' => [
85
            $this->loadFixture('vendor-prefixed-css.css'),
86
            new Indentation(4, Indentation::TYPE_SPACE),
87
            '    ',
88
        ];
89
90
        yield 'Return 0 when these is no indentation' => [
91
            '<ul></ul>',
92
            new Indentation(0, Indentation::TYPE_UNKNOWN),
93
            '',
94
        ];
95
96
        yield 'Indentation for fifty-fifty indented files with spaces first' => [
97
            $this->loadFixture('fifty-fifty-space-first.js'),
98
            new Indentation(4, Indentation::TYPE_SPACE),
99
            '    ',
100
        ];
101
102
        yield 'Indentation for fifty-fifty indented files with tabs first' => [
103
            $this->loadFixture('fifty-fifty-tab-first.js'),
104
            new Indentation(1, Indentation::TYPE_TAB),
105
            "\t",
106
        ];
107
108
        yield 'Indentation for files with spaces and tabs last' => [
109
            $this->loadFixture('space-tab-last.js'),
110
            new Indentation(1, Indentation::TYPE_TAB),
111
            "\t",
112
        ];
113
114
        yield 'Indentation of a file with single line comments' => [
115
            $this->loadFixture('single-space-ignore.js'),
116
            new Indentation(4, Indentation::TYPE_SPACE),
117
            '    ',
118
        ];
119
120
        yield 'Indentation for files with single spaces only' => [
121
            $this->loadFixture('single-space-only.js'),
122
            new Indentation(1, Indentation::TYPE_SPACE),
123
            ' ',
124
        ];
125
    }
126
127
    /**
128
     * @dataProvider provideCasesForTestChange
129
     */
130
    public function testChange(string $contents, Indentation $indentation, string $expected): void
131
    {
132
        $actual = Indentation::change($contents, $indentation);
133
        self::assertSame($expected, $actual);
134
    }
135
136
    /**
137
     * @return iterable<array<mixed>>
138
     */
139
    public function provideCasesForTestChange(): iterable
140
    {
141
        yield 'Empty string' => [
142
            '',
143
            new Indentation(4, Indentation::TYPE_SPACE),
144
            '',
145
        ];
146
147
        yield 'No indentation' => [
148
            '<ul></ul>',
149
            new Indentation(4, Indentation::TYPE_SPACE),
150
            '<ul></ul>',
151
        ];
152
153
        yield 'Two spaces to four spaces' => [
154
            "<div>\n  <ul>\n    <li>yay</li>\n  </ul>\n</div>",
155
            new Indentation(4, Indentation::TYPE_SPACE),
156
            "<div>\n    <ul>\n        <li>yay</li>\n    </ul>\n</div>",
157
        ];
158
159
        yield 'Four spaces to two spaces' => [
160
            "<div>\n    <ul>\n        <li>yay</li>\n    </ul>\n</div>",
161
            new Indentation(2, Indentation::TYPE_SPACE),
162
            "<div>\n  <ul>\n    <li>yay</li>\n  </ul>\n</div>",
163
        ];
164
165
        yield 'Two spaces to tabs' => [
166
            "<div>\n  <ul>\n    <li>yay</li>\n  </ul>\n</div>",
167
            new Indentation(1, Indentation::TYPE_TAB),
168
            "<div>\n\t<ul>\n\t\t<li>yay</li>\n\t</ul>\n</div>",
169
        ];
170
171
        yield 'Four spaces to tabs' => [
172
            "<div>\n    <ul>\n        <li>yay</li>\n    </ul>\n</div>",
173
            new Indentation(1, Indentation::TYPE_TAB),
174
            "<div>\n\t<ul>\n\t\t<li>yay</li>\n\t</ul>\n</div>",
175
        ];
176
177
        yield 'Tabs to four spaces' => [
178
            "<div>\n\t<ul>\n\t\t<li>yay</li>\n\t</ul>\n</div>",
179
            new Indentation(4, Indentation::TYPE_SPACE),
180
            "<div>\n    <ul>\n        <li>yay</li>\n    </ul>\n</div>",
181
        ];
182
183
        yield 'Two tabs to two spaces' => [
184
            "<div>\n\t\t<ul>\n\t\t\t\t<li>yay</li>\n\t\t</ul>\n</div>",
185
            new Indentation(2, Indentation::TYPE_SPACE),
186
            "<div>\n  <ul>\n    <li>yay</li>\n  </ul>\n</div>",
187
        ];
188
189
        yield 'Newlines are preserved' => [
190
            "\n<div>\n  <ul>\r\n    <li>yay</li>\r  </ul>\n</div>\n\n",
191
            new Indentation(4, Indentation::TYPE_SPACE),
192
            "\n<div>\n    <ul>\r\n        <li>yay</li>\r    </ul>\n</div>\n\n",
193
        ];
194
    }
195
196
    /**
197
     * @dataProvider provideCasesForTestIndent
198
     */
199
    public function testIndent(string $input, Indentation $indentation, string $expected): void
200
    {
201
        $actual = Indentation::indent($input, $indentation);
202
        self::assertSame($expected, $actual);
203
    }
204
205
    /**
206
     * @return iterable<array<mixed>>
207
     */
208
    public function provideCasesForTestIndent(): iterable
209
    {
210
        yield 'Empty string' => [
211
            '',
212
            new Indentation(4, Indentation::TYPE_SPACE),
213
            '',
214
        ];
215
216
        yield 'No indentation' => [
217
            '<ul></ul>',
218
            new Indentation(0, Indentation::TYPE_SPACE),
219
            '<ul></ul>',
220
        ];
221
222
        yield 'Unknown indentation' => [
223
            '<ul></ul>',
224
            new Indentation(4, Indentation::TYPE_UNKNOWN),
225
            '<ul></ul>',
226
        ];
227
228
        yield 'Add two spaces' => [
229
            "<ul>\n\n  <li>yay</li>\n\n</ul>\n",
230
            new Indentation(2, Indentation::TYPE_SPACE),
231
            "  <ul>\n\n    <li>yay</li>\n\n  </ul>\n",
232
        ];
233
234
        yield 'Add four spaces' => [
235
            "<ul>\n\n  <li>yay</li>\n\n</ul>\n",
236
            new Indentation(4, Indentation::TYPE_SPACE),
237
            "    <ul>\n\n      <li>yay</li>\n\n    </ul>\n",
238
        ];
239
240
        yield 'Add one tab' => [
241
            "<ul>\n\n  <li>yay</li>\n\n</ul>\n",
242
            new Indentation(1, Indentation::TYPE_TAB),
243
            "\t<ul>\n\n\t  <li>yay</li>\n\n\t</ul>\n",
244
        ];
245
    }
246
247
    /**
248
     * @dataProvider provideCasesForTestUnindent
249
     */
250
    public function testUnindent(string $input, string $expected): void
251
    {
252
        $actual = Indentation::unindent($input);
253
        self::assertSame($expected, $actual);
254
    }
255
256
    /**
257
     * @return iterable<array<mixed>>
258
     */
259
    public function provideCasesForTestUnindent(): iterable
260
    {
261
        yield 'Empty string' => [
262
            '',
263
            '',
264
        ];
265
266
        yield 'No indentation' => [
267
            '<ul></ul>',
268
            '<ul></ul>',
269
        ];
270
271
        yield 'All lines have 1 leading space' => [
272
            " Hello\n\n World\n",
273
            "Hello\n\nWorld\n",
274
        ];
275
276
        yield 'All lines have 2 leading spaces' => [
277
            "  Hello\n\n  World\n",
278
            "Hello\n\nWorld\n",
279
        ];
280
281
        yield 'All lines have 1 leading tab' => [
282
            "\tHello\n\n\tWorld\n",
283
            "Hello\n\nWorld\n",
284
        ];
285
286
        yield 'All lines have 2 leading tabs' => [
287
            "\t\tHello\n\n\t\tWorld\n",
288
            "Hello\n\nWorld\n",
289
        ];
290
291
        yield 'Only trim first two spaces' => [
292
            "  <ul>\n    <li>yay</li>\n  </ul>\n",
293
            "<ul>\n  <li>yay</li>\n</ul>\n",
294
        ];
295
296
        yield 'Leading indent of 4 spaces + lots of 2-space-indented contents' => [
297
            <<<INPUT
298
    <ul>
299
      <li>
300
        This content
301
        is indented
302
        by 2 spaces.
303
      </li>
304
      <li>
305
        But the entire
306
        code block
307
        has an extra
308
        4 spaces of indentation
309
        that we should strip.
310
      </li>
311
    </ul>
312
INPUT,
313
            <<<EXPECTED
314
<ul>
315
  <li>
316
    This content
317
    is indented
318
    by 2 spaces.
319
  </li>
320
  <li>
321
    But the entire
322
    code block
323
    has an extra
324
    4 spaces of indentation
325
    that we should strip.
326
  </li>
327
</ul>
328
EXPECTED,
329
        ];
330
331
        yield 'Leading indent of 5 spaces + lots of 2-space-indented contents' => [
332
            <<<INPUT
333
     <ul>
334
       <li>
335
         This content
336
         is indented
337
         by 2 spaces.
338
       </li>
339
       <li>
340
         But the entire
341
         code block
342
         has an extra
343
         5 spaces of indentation
344
         that we should strip.
345
       </li>
346
     </ul>
347
INPUT,
348
            <<<EXPECTED
349
<ul>
350
  <li>
351
    This content
352
    is indented
353
    by 2 spaces.
354
  </li>
355
  <li>
356
    But the entire
357
    code block
358
    has an extra
359
    5 spaces of indentation
360
    that we should strip.
361
  </li>
362
</ul>
363
EXPECTED,
364
        ];
365
366
        yield 'Single leading space with multi-line code comments' => [
367
            " /**\n  * Test\n  */\n",
368
            "/**\n * Test\n */\n",
369
        ];
370
371
        yield 'Mixed leading indentation (tabs then spaces)' => [
372
            "\tHello\n  World!\n",
373
            "\tHello\n  World!\n",
374
        ];
375
376
        yield 'Mixed leading indentation (spaces then tabs)' => [
377
            "  Hello\n\tWorld!\n",
378
            "  Hello\n\tWorld!\n",
379
        ];
380
    }
381
382
    private function loadFixture(string $filename): string
383
    {
384
        $fixture = \file_get_contents(__DIR__ . '/fixtures/' . $filename);
385
        if ($fixture === false) {
386
            $this->fail('Fixture file not found');
387
        }
388
389
        return $fixture;
390
    }
391
}
392