Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.11.x will end 14 Nov 2022 (12 months plus 6 months extension).
  • Bug fixes for security issues in 3.11.x will end 13 Nov 2023 (18 months plus 12 months extension).
  • PHP version: minimum PHP 7.3.0 Note: minimum PHP version has increased since Moodle 3.10. PHP 7.4.x is supported too.
   1  <?php
   2  // This file is part of Moodle - http://moodle.org/
   3  //
   4  // Moodle is free software: you can redistribute it and/or modify
   5  // it under the terms of the GNU General Public License as published by
   6  // the Free Software Foundation, either version 3 of the License, or
   7  // (at your option) any later version.
   8  //
   9  // Moodle is distributed in the hope that it will be useful,
  10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12  // GNU General Public License for more details.
  13  //
  14  // You should have received a copy of the GNU General Public License
  15  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
  16  
  17  /**
  18   * Unit tests for core_table\local\filter\numeric_comparison_filter.
  19   *
  20   * @package   core_table
  21   * @category  test
  22   * @copyright 2020 Andrew Nicols <andrew@nicols.co.uk>
  23   * @license   http://www.gnu.org/copyleft/gpl.html GNU Public License
  24   */
  25  
  26  declare(strict_types=1);
  27  
  28  namespace core_table\local\filter;
  29  
  30  use advanced_testcase;
  31  use InvalidArgumentException;
  32  use TypeError;
  33  
  34  /**
  35   * Unit tests for core_table\local\filter\numeric_comparison_filter.
  36   *
  37   * @package   core_table
  38   * @category  test
  39   * @copyright 2020 Andrew Nicols <andrew@nicols.co.uk>
  40   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  41   */
  42  class numeric_comparison_filter_test extends advanced_testcase {
  43      /**
  44       * Ensure that the add_filter_value function works as expected with valid values.
  45       */
  46      public function test_add_filter_value_valid(): void {
  47          $filter = new numeric_comparison_filter('example');
  48  
  49          // Initially an empty list.
  50          $this->assertEmpty($filter->get_filter_values());
  51  
  52          // Adding a value should return that value.
  53          $filter->add_filter_value(json_encode((object) [
  54              'direction' => '>',
  55              'value' => 100,
  56          ]));
  57          $this->assertEquals([
  58              (object) [
  59                  'direction' => '>',
  60                  'value' => 100,
  61              ],
  62          ], $filter->get_filter_values());
  63  
  64          // Adding a second value should add that value.
  65          // The values should sorted.
  66          $filter->add_filter_value(json_encode((object) [
  67              'direction' => '<=',
  68              'value' => 1000,
  69          ]));
  70          $this->assertEquals([
  71              (object) [
  72                  'direction' => '<=',
  73                  'value' => 1000,
  74              ],
  75              (object) [
  76                  'direction' => '>',
  77                  'value' => 100,
  78              ],
  79          ], $filter->get_filter_values());
  80  
  81          // Adding a duplicate value should not lead to that value being added again.
  82          $filter->add_filter_value(json_encode((object) [
  83              'direction' => '>',
  84              'value' => 100,
  85          ]));
  86          $this->assertEquals([
  87              (object) [
  88                  'direction' => '<=',
  89                  'value' => 1000,
  90              ],
  91              (object) [
  92                  'direction' => '>',
  93                  'value' => 100,
  94              ],
  95          ], $filter->get_filter_values());
  96      }
  97  
  98      /**
  99       * Ensure that the add_filter_value function rejects invalid types.
 100       *
 101       * @dataProvider add_filter_value_invalid_types_provider
 102       * @param mixed $values
 103       * @param string $exceptiontype
 104       * @param string $exceptionmessage
 105       */
 106      public function test_add_filter_value_type_invalid($values, string $exceptiontype, string $exceptionmessage): void {
 107          $filter = new numeric_comparison_filter('example');
 108  
 109          // Adding empty string is not supported.
 110          $this->expectException($exceptiontype);
 111          $this->expectExceptionMessage($exceptionmessage);
 112          call_user_func_array([$filter, 'add_filter_value'], $values);
 113      }
 114  
 115      /**
 116       * Data provider for add_filter_value tests with invalid types.
 117       *
 118       * @return array
 119       */
 120      public function add_filter_value_invalid_types_provider(): array {
 121          return [
 122              'Null' => [
 123                  [null],
 124                  TypeError::class,
 125                  "The value supplied was of type 'NULL'. A string representing a json-encoded value was expected.",
 126              ],
 127              'Single value string' => [
 128                  [''],
 129                  InvalidArgumentException::class,
 130                  "A json-encoded object containing both a direction, and comparison value was expected.",
 131              ],
 132              'Single value integer' => [
 133                  [42],
 134                  TypeError::class,
 135                  "The value supplied was of type 'integer'. A string representing a json-encoded value was expected.",
 136              ],
 137              'Single value float' => [
 138                  [4.2],
 139                  TypeError::class,
 140                  "The value supplied was of type 'double'. A string representing a json-encoded value was expected.",
 141              ],
 142              'Single value bool' => [
 143                  [false],
 144                  TypeError::class,
 145                  "The value supplied was of type 'boolean'. A string representing a json-encoded value was expected.",
 146              ],
 147              'Single value array' => [
 148                  [[]],
 149                  TypeError::class,
 150                  "The value supplied was of type 'array'. A string representing a json-encoded value was expected.",
 151              ],
 152              'Single value object' => [
 153                  [(object) []],
 154                  TypeError::class,
 155                  "The value supplied was of type 'stdClass'. A string representing a json-encoded value was expected.",
 156              ],
 157              'Single value class' => [
 158                  [new filter('example')],
 159                  TypeError::class,
 160                  "The value supplied was of type '" . filter::class . "'. A string representing a json-encoded value was expected.",
 161              ],
 162  
 163              'json-encoded single value null' => [
 164                  // Note a json-encoded null is the stringy 'null'.
 165                  [json_encode(null)],
 166                  InvalidArgumentException::class,
 167                  "A json-encoded object containing both a direction, and comparison value was expected.",
 168              ],
 169              'json-encoded single value string' => [
 170                  [json_encode('')],
 171                  InvalidArgumentException::class,
 172                  "The value supplied was a json encoded 'string'. " .
 173                      "An object containing both a direction, and comparison value was expected.",
 174              ],
 175              'json-encoded single value integer' => [
 176                  [json_encode(42)],
 177                  InvalidArgumentException::class,
 178                  "The value supplied was a json encoded 'string'. " .
 179                      "An object containing both a direction, and comparison value was expected.",
 180              ],
 181              'json-encoded single value double' => [
 182                  [json_encode(4.2)],
 183                  InvalidArgumentException::class,
 184                  "The value supplied was a json encoded 'string'. " .
 185                      "An object containing both a direction, and comparison value was expected.",
 186              ],
 187              'json-encoded single value bool' => [
 188                  [json_encode(false)],
 189                  InvalidArgumentException::class,
 190                  "The value supplied was a json encoded 'string'. " .
 191                      "An object containing both a direction, and comparison value was expected.",
 192              ],
 193              'json-encoded single value array' => [
 194                  [json_encode([])],
 195                  InvalidArgumentException::class,
 196                  "The value supplied was a json encoded 'string'. " .
 197                      "An object containing both a direction, and comparison value was expected.",
 198              ],
 199  
 200              'json-encoded empty object' => [
 201                  [json_encode((object) [])],
 202                  InvalidArgumentException::class,
 203                  "A 'direction' must be provided.",
 204              ],
 205              'json-encoded single value class' => [
 206                  // A class will contain any public properties when json-encoded. It is treated in the same was a stdClass.
 207                  [json_encode(new filter('example'))],
 208                  InvalidArgumentException::class,
 209                  "A 'direction' must be provided.",
 210              ],
 211  
 212              'Direction provided, value missing' => [
 213                  [json_encode([
 214                      'direction' => '>',
 215                  ])],
 216                  InvalidArgumentException::class,
 217                  "A 'value' must be provided.",
 218              ],
 219  
 220              'Direction invalid +' => [
 221                  [json_encode([
 222                      'direction' => '+',
 223                      'value' => 100,
 224                  ])],
 225                  InvalidArgumentException::class,
 226                  "Invalid direction specified '+'."
 227              ],
 228              'Direction invalid -' => [
 229                  [json_encode([
 230                      'direction' => '-',
 231                      'value' => 100,
 232                  ])],
 233                  InvalidArgumentException::class,
 234                  "Invalid direction specified '-'."
 235              ],
 236  
 237              'Value string' => [
 238                  [json_encode([
 239                      'direction' => '>',
 240                      'value' => "example",
 241                  ])],
 242                  TypeError::class,
 243                  "The value supplied was of type 'string'. A numeric value was expected."
 244              ],
 245              'Value bool' => [
 246                  [json_encode([
 247                      'direction' => '>',
 248                      'value' => false,
 249                  ])],
 250                  TypeError::class,
 251                  "The value supplied was of type 'boolean'. A numeric value was expected."
 252              ],
 253              'Value array' => [
 254                  [json_encode([
 255                      'direction' => '>',
 256                      'value' => [],
 257                  ])],
 258                  TypeError::class,
 259                  "The value supplied was of type 'array'. A numeric value was expected."
 260              ],
 261              'Value stdClass' => [
 262                  [json_encode([
 263                      'direction' => '>',
 264                      'value' => (object) [],
 265                  ])],
 266                  TypeError::class,
 267                  "The value supplied was of type 'stdClass'. A numeric value was expected."
 268              ],
 269              'Value class' => [
 270                  // A class will contain any public properties when json-encoded. It is treated in the same was a stdClass.
 271                  [json_encode([
 272                      'direction' => '>',
 273                      'value' => new filter('example'),
 274                  ])],
 275                  TypeError::class,
 276                  "The value supplied was of type 'stdClass'. A numeric value was expected."
 277              ],
 278          ];
 279      }
 280  }