trait JsonSchemaTestTrait

Trait for testing JSON Schema validity and fit to sample data.

In most cases, tests need only implement the abstract method for providing a full set of representative normalized values.

Hierarchy

7 files declare their use of JsonSchemaTestTrait
DateTimeIso8601NormalizerTest.php in core/modules/serialization/tests/src/Unit/Normalizer/DateTimeIso8601NormalizerTest.php
DateTimeNormalizerTest.php in core/modules/serialization/tests/src/Unit/Normalizer/DateTimeNormalizerTest.php
JsonApiJsonSchemaTestTrait.php in core/modules/jsonapi/tests/src/Traits/JsonApiJsonSchemaTestTrait.php
MarkupNormalizerTest.php in core/modules/serialization/tests/src/Unit/Normalizer/MarkupNormalizerTest.php
NullNormalizerTest.php in core/modules/serialization/tests/src/Unit/Normalizer/NullNormalizerTest.php

... See full list

File

core/modules/serialization/tests/src/Traits/JsonSchemaTestTrait.php, line 18

Namespace

Drupal\Tests\serialization\Traits
View source
trait JsonSchemaTestTrait {
    
    /**
     * Format that should be used when performing test normalizations.
     */
    protected function getJsonSchemaTestNormalizationFormat() : ?string {
        return NULL;
    }
    
    /**
     * Data provider for ::testNormalizedValuesAgainstJsonSchema.
     *
     * @return array
     *   Array of possible normalized values to validate the JSON schema against.
     */
    public static abstract function jsonSchemaDataProvider() : array;
    
    /**
     * Method to make prophecy public for use in data provider closures.
     */
    public function doProphesize(?string $classOrInterface = NULL) : ObjectProphecy {
        return $this->prophesize($classOrInterface);
    }
    
    /**
     * Test that a valid schema is returned for the explicitly supported types.
     *
     * This is in many cases an interface, which would not be normalized directly,
     * however the schema should never return an invalid type. An empty array or
     * a type with only a '$comment' member is valid.
     *
     * @dataProvider supportedTypesDataProvider
     */
    public function testSupportedTypesSchemaIsValid(string $type) : void {
        $this->doTestJsonSchemaIsValid($type, TRUE);
    }
    
    /**
     * Check a schema is valid against the meta-schema.
     *
     * @param array $defined_schema
     *   Defined schema.
     * @param bool $accept_no_schema_type
     *   Whether to accept a schema with no meaningful type construct.
     */
    protected function doCheckSchemaAgainstMetaSchema(array $defined_schema, bool $accept_no_schema_type = FALSE) : void {
        $validator = $this->getValidator();
        // Ensure the schema contains a meaningful type construct.
        if (!$accept_no_schema_type) {
            $this->assertFalse(empty(array_filter(array_keys($defined_schema), fn($key) => in_array($key, [
                'type',
                'allOf',
                'oneOf',
                'anyOf',
                'not',
                '$ref',
            ]))));
        }
        // All associative arrays must be encoded as objects.
        $schema = json_decode(json_encode($defined_schema));
        $validator->validate($schema, (object) [
            '$ref' => 'file://' . __DIR__ . '/../../../src/json-schema-draft-04-meta-schema.json',
        ]);
        $this->assertTrue($validator->isValid());
    }
    
    /**
     * Validate the normalizer's JSON schema.
     *
     * @param mixed $type
     *   Object/type being normalized.
     * @param bool $accept_no_schema_type
     *   Whether to accept a schema with no meaningful type.
     *
     * @return array
     *   Schema, so later tests can avoid retrieving it again.
     */
    public function doTestJsonSchemaIsValid(mixed $type, bool $accept_no_schema_type = FALSE) : array {
        $defined_schema = $this->getNormalizer()
            ->normalize($type, 'json_schema');
        $this->doCheckSchemaAgainstMetaSchema($defined_schema, $accept_no_schema_type);
        return $defined_schema;
    }
    
    /**
     * @return array
     *   Supported types for which to test schema generation.
     */
    public static function supportedTypesDataProvider() : array {
        return array_map(fn($type) => [
            $type,
        ], array_keys((new PrimitiveDataNormalizer())->getSupportedTypes(NULL)));
    }
    
    /**
     * Test normalized values against the JSON schema.
     *
     * @dataProvider jsonSchemaDataProvider
     */
    public function testNormalizedValuesAgainstJsonSchema(mixed $value) : void {
        // Explicitly test the JSON Schema's validity here, because it will depend
        // on the type of the data being normalized, e.g. a class implementing the
        // interface defined in ::getSupportedTypes().
        if ($value instanceof \Closure) {
            $value = $value($this);
        }
        $schema = $this->doTestJsonSchemaIsValid($value);
        $validator = $this->getValidator();
        // Test the value validates to the schema.
        // All associative arrays must be encoded as objects.
        $normalized = json_decode(json_encode($this->getNormalizationForValue($value)));
        $validator->validate($normalized, $schema);
        $this->assertSame([], $validator->getErrors(), 'Validation errors on object ' . print_r($normalized, TRUE) . ' with schema ' . print_r($schema, TRUE));
    }
    
    /**
     * Helper method to retrieve the normalizer.
     *
     * Override this method if the normalizer has a custom getter or is not
     * already present at $this->normalizer.
     *
     * @return \Symfony\Component\Serializer\Normalizer\NormalizerInterface
     *   The normalizer under test.
     */
    protected function getNormalizer() : NormalizerInterface {
        return $this->normalizer;
    }
    
    /**
     * Get the normalization for a value.
     *
     * Override this method if the normalization needs further processing, e.g.
     * in the case of JSON:API module's CacheableDependencyInterface.
     *
     * @param mixed $value
     *   Value to be normalized.
     *
     * @return mixed
     *   Final normalized value.
     */
    protected function getNormalizationForValue(mixed $value) : mixed {
        return $this->getNormalizer()
            ->normalize($value, $this->getJsonSchemaTestNormalizationFormat());
    }
    
    /**
     * Get the JSON Schema Validator.
     *
     * Override this method to add additional schema translations to the loader.
     *
     * @return \JsonSchema\Validator
     *   Schema validator.
     */
    protected function getValidator() : Validator {
        return new Validator();
    }

}

Members

Title Sort descending Modifiers Object type Summary Overrides
JsonSchemaTestTrait::doCheckSchemaAgainstMetaSchema protected function Check a schema is valid against the meta-schema.
JsonSchemaTestTrait::doProphesize public function Method to make prophecy public for use in data provider closures.
JsonSchemaTestTrait::doTestJsonSchemaIsValid public function Validate the normalizer's JSON schema.
JsonSchemaTestTrait::getJsonSchemaTestNormalizationFormat protected function Format that should be used when performing test normalizations. 1
JsonSchemaTestTrait::getNormalizationForValue protected function Get the normalization for a value.
JsonSchemaTestTrait::getNormalizer protected function Helper method to retrieve the normalizer. 1
JsonSchemaTestTrait::getValidator protected function Get the JSON Schema Validator. 1
JsonSchemaTestTrait::jsonSchemaDataProvider abstract public static function Data provider for ::testNormalizedValuesAgainstJsonSchema. 7
JsonSchemaTestTrait::supportedTypesDataProvider public static function
JsonSchemaTestTrait::testNormalizedValuesAgainstJsonSchema public function Test normalized values against the JSON schema.
JsonSchemaTestTrait::testSupportedTypesSchemaIsValid public function Test that a valid schema is returned for the explicitly supported types.

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.