summaryrefslogtreecommitdiffstatshomepage
path: root/core/modules/jsonapi/tests/src/Unit/JsonApiSpecTest.php
blob: f7dc9f64517b6c63e10cac0582ed93e2aedb180d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
<?php

declare(strict_types=1);

namespace Drupal\Tests\jsonapi\Unit;

use Drupal\jsonapi\JsonApiSpec;
use Drupal\Tests\UnitTestCase;

// cspell:ignore kitt

/**
 * @coversDefaultClass \Drupal\jsonapi\JsonApiSpec
 * @group jsonapi
 *
 * @internal
 */
class JsonApiSpecTest extends UnitTestCase {

  /**
   * Ensures that member names are properly validated.
   *
   * @dataProvider providerTestIsValidMemberName
   * @covers ::isValidMemberName
   */
  public function testIsValidMemberName($member_name, $expected): void {
    $this->assertSame($expected, JsonApiSpec::isValidMemberName($member_name));
  }

  /**
   * Data provider for testIsValidMemberName.
   */
  public static function providerTestIsValidMemberName() {
    // Copied from http://jsonapi.org/format/upcoming/#document-member-names.
    $data = [];
    $data['alphanumeric-lowercase'] = ['12kittens', TRUE];
    $data['alphanumeric-uppercase'] = ['12KITTENS', TRUE];
    $data['alphanumeric-mixed'] = ['12KiTtEnS', TRUE];
    $data['unicode-above-u+0080'] = ['12🐱🐱', TRUE];
    $data['hyphen-start'] = ['-kittens', FALSE];
    $data['hyphen-middle'] = ['kitt-ens', TRUE];
    $data['hyphen-end'] = ['kittens-', FALSE];
    $data['low-line-start'] = ['_kittens', FALSE];
    $data['low-line-middle'] = ['kitt_ens', TRUE];
    $data['low-line-end'] = ['kittens_', FALSE];
    $data['space-start'] = [' kittens', FALSE];
    $data['space-middle'] = ['kitt ens', TRUE];
    $data['space-end'] = ['kittens ', FALSE];

    // Additional test cases.
    // @todo When D8 requires PHP >= 7, convert to \u{10FFFF}.
    $data['unicode-above-u+0080-highest-allowed'] = ["12􏿿", TRUE];
    $data['single-character'] = ['a', TRUE];

    $unsafe_chars = [
      '+',
      ',',
      '.',
      '[',
      ']',
      '!',
      '"',
      '#',
      '$',
      '%',
      '&',
      '\'',
      '(',
      ')',
      '*',
      '/',
      ':',
      ';',
      '<',
      '=',
      '>',
      '?',
      '@',
      '\\',
      '^',
      '`',
      '{',
      '|',
      '}',
      '~',
    ];
    foreach ($unsafe_chars as $unsafe_char) {
      $data['unsafe-' . $unsafe_char] = ['kitt' . $unsafe_char . 'ens', FALSE];
    }

    // The ASCII control characters are in the range 0x00 to 0x1F plus 0x7F.
    for ($ascii = 0; $ascii <= 0x1F; $ascii++) {
      $data['unsafe-ascii-control-' . $ascii] = ['kitt' . chr($ascii) . 'ens', FALSE];
    }
    $data['unsafe-ascii-control-' . 0x7F] = ['kitt' . chr(0x7F) . 'ens', FALSE];

    return $data;
  }

  /**
   * Provides test cases.
   *
   * @dataProvider providerTestIsValidCustomQueryParameter
   * @covers ::isValidCustomQueryParameter
   * @covers ::isValidMemberName
   */
  public function testIsValidCustomQueryParameter($custom_query_parameter, $expected): void {
    $this->assertSame($expected, JsonApiSpec::isValidCustomQueryParameter($custom_query_parameter));
  }

  /**
   * Data provider for testIsValidCustomQueryParameter.
   */
  public static function providerTestIsValidCustomQueryParameter() {
    $data = static::providerTestIsValidMemberName();

    // All valid member names are also valid custom query parameters, except for
    // single-character ones.
    $data['single-character'][1] = FALSE;

    // Custom query parameter test cases.
    $data['custom-query-parameter-lowercase'] = ['foobar', FALSE];
    $data['custom-query-parameter-dash'] = ['foo-bar', TRUE];
    $data['custom-query-parameter-underscore'] = ['foo_bar', TRUE];
    $data['custom-query-parameter-camel-case'] = ['fooBar', TRUE];

    return $data;
  }

}