Skip to content

Commit

Permalink
REST: Fix StatementValidator to handle InvalidFieldTypeException error
Browse files Browse the repository at this point in the history
Change-Id: Ia781b56024fd25b9f312e9c1817a55d0d24ee4c3
  • Loading branch information
dima koushha committed Jun 26, 2024
1 parent fcb218a commit 56157cb
Show file tree
Hide file tree
Showing 8 changed files with 94 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@ public function validateAndDeserialize( StatementSerializationRequest $request )
"Mandatory field missing in the statement data: {$context[StatementValidator::CONTEXT_FIELD]}",
[ UseCaseError::CONTEXT_PATH => $context[StatementValidator::CONTEXT_FIELD] ]
);
case StatementValidator::CODE_INVALID_FIELD_TYPE:
throw new UseCaseError(
UseCaseError::INVALID_STATEMENT_TYPE,
'Not a valid statement type',
[ UseCaseError::CONTEXT_PATH => $context[StatementValidator::CONTEXT_FIELD] ]
);
default:
throw new LogicException( "Unknown validation error code: {$validationError->getCode()}" );
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use LogicException;
use Wikibase\DataModel\Statement\Statement;
use Wikibase\Repo\RestApi\Application\Serialization\Exceptions\InvalidFieldException;
use Wikibase\Repo\RestApi\Application\Serialization\Exceptions\InvalidFieldTypeException;
use Wikibase\Repo\RestApi\Application\Serialization\Exceptions\MissingFieldException;
use Wikibase\Repo\RestApi\Application\Serialization\StatementDeserializer;

Expand All @@ -15,6 +16,7 @@ class StatementValidator {

public const CODE_INVALID_FIELD = 'statement-validator-code-invalid-statement-field';
public const CODE_MISSING_FIELD = 'statement-validator-code-missing-statement-field';
public const CODE_INVALID_FIELD_TYPE = 'statement-validator-code-invalid-statement-type';

public const CONTEXT_FIELD = 'statement-validator-context-field';
public const CONTEXT_VALUE = 'statement-validator-context-value';
Expand All @@ -40,6 +42,11 @@ public function validate( array $statementSerialization ): ?ValidationError {
self::CONTEXT_VALUE => $e->getValue(),
]
);
} catch ( InvalidFieldTypeException $e ) {
return new ValidationError(
self::CODE_INVALID_FIELD_TYPE,
[ self::CONTEXT_FIELD => $e->getField() ]
);
}

return null;
Expand Down
22 changes: 22 additions & 0 deletions repo/rest-api/tests/mocha/api-testing/AddItemStatementTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ describe( newAddItemStatementRequestBuilder().getRouteDescription(), () => {
{ parameter: 'item_id' }
);
} );

it( 'comment too long', async () => {
const comment = 'x'.repeat( 501 );
const response = await newAddItemStatementRequestBuilder( testItemId, testStatement )
Expand Down Expand Up @@ -239,6 +240,27 @@ describe( newAddItemStatementRequestBuilder().getRouteDescription(), () => {
assertValidError( response, 400, 'statement-data-missing-field', { path: missingField } );
assert.include( response.body.message, missingField );
} );

it( 'invalid statement type: string', async () => {
const invalidStatement = 'statement-not-string';
const response = await newAddItemStatementRequestBuilder( testItemId, invalidStatement )
.assertInvalidRequest()
.makeRequest();

expect( response ).to.have.status( 400 );
assert.strictEqual( response.body.code, 'invalid-value' );
assert.deepEqual( response.body.context, { path: '/statement' } );
} );

it( 'invalid statement type: array', async () => {
const invalidStatement = [ 'statement-not-an-array' ];

const response = await newAddItemStatementRequestBuilder( testItemId, invalidStatement )
.assertInvalidRequest()
.makeRequest();

assertValidError( response, 400, 'invalid-statement-type', { path: '' } );
} );
} );

describe( '404 error response', () => {
Expand Down
22 changes: 22 additions & 0 deletions repo/rest-api/tests/mocha/api-testing/AddPropertyStatementTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,28 @@ describe( newAddPropertyStatementRequestBuilder().getRouteDescription(), () => {
assertValidError( response, 400, 'statement-data-missing-field', { path: missingField } );
assert.include( response.body.message, missingField );
} );

it( 'invalid statement type: string', async () => {
const invalidStatement = 'statement-not-string';

const response = await newAddPropertyStatementRequestBuilder( testPropertyId, invalidStatement )
.assertInvalidRequest()
.makeRequest();

expect( response ).to.have.status( 400 );
assert.strictEqual( response.body.code, 'invalid-value' );
assert.deepEqual( response.body.context, { path: '/statement' } );
} );

it( 'invalid statement type: array', async () => {
const invalidStatement = [ 'statement-not-array' ];

const response = await newAddPropertyStatementRequestBuilder( testPropertyId, invalidStatement )
.assertInvalidRequest()
.makeRequest();

assertValidError( response, 400, 'invalid-statement-type', { path: '' } );
} );
} );

describe( '404 error response', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,6 @@ describe( 'PUT statement tests', () => {
} );

describe( '400 error response', () => {

it( 'statement ID contains invalid entity ID', async () => {
const statement = entityHelper.newStatementWithRandomStringValue( predicatePropertyId );
const response = await newReplaceRequestBuilder( testItemId, testStatementId.replace( 'Q', 'X' ), statement )
Expand Down Expand Up @@ -263,8 +262,8 @@ describe( 'PUT statement tests', () => {
assert.strictEqual( response.body.expectedType, 'string' );
} );

it( 'invalid statement type', async () => {
const response = await newReplaceRequestBuilder( testItemId, testStatementId, 'invalid' )
it( 'invalid statement type: string', async () => {
const response = await newReplaceRequestBuilder( testItemId, testStatementId, 'statement-not-string' )
.assertInvalidRequest().makeRequest();

expect( response ).to.have.status( 400 );
Expand All @@ -273,6 +272,13 @@ describe( 'PUT statement tests', () => {
assert.strictEqual( response.body.expectedType, 'object' );
} );

it( 'invalid statement type: array', async () => {
const response = await newReplaceRequestBuilder( testItemId, testStatementId, [ 'statement-not-array' ] )
.assertInvalidRequest().makeRequest();

assertValidError( response, 400, 'invalid-statement-type', { path: '' } );
} );

it( 'invalid statement field', async () => {
const statement = entityHelper.newStatementWithRandomStringValue( predicatePropertyId );
const invalidField = 'rank';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,6 @@ describe( 'PUT statement tests', () => {
} );

describe( '400 error response', () => {

it( 'statement ID contains invalid entity ID', async () => {
const statementSerialization = entityHelper.newStatementWithRandomStringValue(
testStatementPropertyId
Expand Down Expand Up @@ -327,8 +326,8 @@ describe( 'PUT statement tests', () => {
assert.strictEqual( response.body.expectedType, 'string' );
} );

it( 'invalid statement type', async () => {
const response = await newReplaceRequestBuilder( testPropertyId, testStatementId, 'invalid' )
it( 'invalid statement type: string', async () => {
const response = await newReplaceRequestBuilder( testPropertyId, testStatementId, 'statement-not-string' )
.assertInvalidRequest().makeRequest();

expect( response ).to.have.status( 400 );
Expand All @@ -337,6 +336,13 @@ describe( 'PUT statement tests', () => {
assert.strictEqual( response.body.expectedType, 'object' );
} );

it( 'invalid statement type: array', async () => {
const response = await newReplaceRequestBuilder( testPropertyId, testStatementId, [ 'statement-not-array' ] )
.assertInvalidRequest().makeRequest();

assertValidError( response, 400, 'invalid-statement-type', { path: '' } );
} );

it( 'invalid statement field', async () => {
const statementSerialization = entityHelper.newStatementWithRandomStringValue(
testStatementPropertyId
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,18 @@ public function statementValidationErrorProvider(): Generator {
]
),
];

yield 'invalid field type' => [
new ValidationError(
StatementValidator::CODE_INVALID_FIELD_TYPE,
[ StatementValidator::CONTEXT_FIELD => '' ]
),
new UseCaseError(
UseCaseError::INVALID_STATEMENT_TYPE,
'Not a valid statement type',
[ UseCaseError::CONTEXT_PATH => '' ]
),
];
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use PHPUnit\Framework\TestCase;
use Wikibase\DataModel\Statement\Statement;
use Wikibase\Repo\RestApi\Application\Serialization\Exceptions\InvalidFieldException;
use Wikibase\Repo\RestApi\Application\Serialization\Exceptions\InvalidFieldTypeException;
use Wikibase\Repo\RestApi\Application\Serialization\Exceptions\MissingFieldException;
use Wikibase\Repo\RestApi\Application\Serialization\Exceptions\SerializationException;
use Wikibase\Repo\RestApi\Application\Serialization\StatementDeserializer;
Expand Down Expand Up @@ -62,6 +63,12 @@ public static function deserializationErrorProvider(): Generator {
StatementValidator::CODE_MISSING_FIELD,
[ StatementValidator::CONTEXT_FIELD => 'property' ],
];

yield 'invalid field type exception' => [
new InvalidFieldTypeException( '' ),
StatementValidator::CODE_INVALID_FIELD_TYPE,
[ StatementValidator::CONTEXT_FIELD => '' ],
];
}

public function testGetValidatedStatement_calledAfterValidate(): void {
Expand Down

0 comments on commit 56157cb

Please sign in to comment.