This applies JSON Schema validation in phpunit tests where appropriate: 1) In ModuleSpecHandlerTest, the generated OpenApi specs are validated against the OpenAPI 3 schema. 2) In RestStructureTest, module definition files are validated against the mwapi schema. This patch introduces a new trait to make it easy for phpunit test cases to perform validation. This patch also fixes some issues with the docs/rest/mwapi-1.0.json schema and the includes/Rest/content.v1.json module definition. Change-Id: I966cddb337c9373ed3a369496548a8d8c538ae84
113 lines
3.3 KiB
PHP
113 lines
3.3 KiB
PHP
<?php
|
|
/**
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along
|
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
* http://www.gnu.org/copyleft/gpl.html
|
|
*/
|
|
|
|
use JsonSchema\Constraints\Constraint;
|
|
use JsonSchema\Constraints\Factory;
|
|
use JsonSchema\Validator;
|
|
|
|
/**
|
|
* Trait for validating data structures against JSON schemas.
|
|
*
|
|
* Based on the jsonrainbow/json-schema package, supports Draft-3 and Draft-4
|
|
* schemas.
|
|
*
|
|
* @stable to use in extensions
|
|
* @since 1.43
|
|
*/
|
|
trait JsonSchemaAssertionTrait {
|
|
|
|
/**
|
|
* Load data from a JSON file.
|
|
*
|
|
* @param string $jsonFile The path of the JSON file
|
|
*
|
|
* @return mixed
|
|
*/
|
|
private static function loadJsonData( string $jsonFile ) {
|
|
$json = file_get_contents( $jsonFile );
|
|
|
|
if ( $json === false ) {
|
|
throw new InvalidArgumentException( "Unable to load content of $jsonFile" );
|
|
}
|
|
|
|
return json_decode( $json, false, JSON_THROW_ON_ERROR );
|
|
}
|
|
|
|
/**
|
|
* @param string|array $schema A JSON schema as an array structure, or the
|
|
* file path of a JSON schema file.
|
|
* @param string|array|stdClass $json A JSONic data structure, or a JSON string.
|
|
* @param array<string, string> $resources Mapping of schema IDs to local files,
|
|
* to avoid loading schemas over the network during testing.
|
|
*/
|
|
private function assertMatchesJsonSchema( $schema, $json, array $resources = [] ): void {
|
|
if ( is_string( $json ) ) {
|
|
try {
|
|
$json = json_decode( $json, false, JSON_THROW_ON_ERROR );
|
|
} catch ( JsonException $ex ) {
|
|
self::fail( 'Invalid JSON: ' . $ex->getMessage() );
|
|
}
|
|
}
|
|
if ( is_string( $schema ) ) {
|
|
// Let the JsonException propagate, this indicates a bug in the test,
|
|
// not a test failure.
|
|
$schema = self::loadJsonData( $schema );
|
|
}
|
|
|
|
$factory = new Factory();
|
|
|
|
foreach ( $resources as $id => $rc ) {
|
|
$factory->getSchemaStorage()->addSchema(
|
|
rtrim( $id, '#' ),
|
|
self::loadJsonData( $rc )
|
|
);
|
|
}
|
|
|
|
$validator = new Validator( $factory );
|
|
$validator->validate(
|
|
$json, $schema,
|
|
Constraint::CHECK_MODE_TYPE_CAST
|
|
);
|
|
|
|
if ( !$validator->isValid() ) {
|
|
foreach ( $validator->getErrors() as $error ) {
|
|
$error = json_encode( $error );
|
|
self::fail( "JSON schema validation failed: $error" );
|
|
}
|
|
}
|
|
|
|
$this->addToAssertionCount( 1 );
|
|
}
|
|
|
|
/**
|
|
* Validate a JSON schema.
|
|
*
|
|
* Currently only works for schemas that match Draft-4.
|
|
*
|
|
* @param array $schema The schema to validate.
|
|
* @throws LogicException if the schema is invalid
|
|
*/
|
|
public function assertValidJsonSchema( array $schema ): void {
|
|
// Load the draft-04 schema from the local file
|
|
$metaSchema = MW_INSTALL_PATH . '/vendor/justinrainbow/json-schema/dist/' .
|
|
'schema/json-schema-draft-04.json';
|
|
|
|
self::assertMatchesJsonSchema( $metaSchema, $schema );
|
|
}
|
|
|
|
}
|