Skip to content

Commit

Permalink
fix problem+json context resolving while expanding violation list (#553)
Browse files Browse the repository at this point in the history
* add jest-fetch-mock

* violation list expanding test cases

* problem+json context resolving fix

* yarn upgrade

* Remove commented import.

* proto typo

* lock rever
  • Loading branch information
PawelSuwinski authored May 13, 2024
1 parent 551ba4c commit cef2c57
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 6 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
"eslint-plugin-tree-shaking": "^1.10.0",
"jest": "^29.0.0",
"jest-environment-jsdom": "^29.0.0",
"jest-fetch-mock": "^3.0.3",
"node-fetch": "^3.2.10",
"playwright": "^1.42.1",
"prettier": "^3.0.0",
Expand Down
96 changes: 96 additions & 0 deletions src/hydra/fetchHydra.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import type { HttpError } from 'react-admin';
import fetchMock from 'jest-fetch-mock';
import fetchHydra from './fetchHydra.js';
import schemaAnalyzer from './schemaAnalyzer.js';

fetchMock.enableMocks();

const headers = {
'Content-Type': 'application/ld+json; charset=utf-8',
Link: '<http://localhost/docs.jsonld>; rel="http://www.w3.org/ns/hydra/core#apiDocumentation"',
};

test.each([
[
'ld+json',
{
'@context': '/contexts/ConstraintViolationList',
'@type': 'ConstraintViolationList',
'hydra:title': 'An error occurred',
'hydra:description':
'plainPassword: Password must be at least 6 characters long.',
violations: [
{
propertyPath: 'plainPassword',
message: 'Password must be at least 6 characters long.',
},
],
},
{ plainPassword: 'Password must be at least 6 characters long.' },
],
[
'problem+json',
{
'@id': '\\/validation_errors\\/6b3befbc-2f01-4ddf-be21-b57898905284',
'@type': 'ConstraintViolationList',
status: 422,
violations: [
{
propertyPath: 'entitlements',
message:
'At least one product must be selected if policy is restricted.',
code: '6b3befbc-2f01-4ddf-be21-b57898905284',
},
],
detail:
'entitlements: At least one product must be selected if policy is restricted.',
'hydra:title': 'An error occurred',
'hydra:description':
'entitlements: At least one product must be selected if policy is restricted.',
type: '\\/validation_errors\\/6b3befbc-2f01-4ddf-be21-b57898905284',
title: 'An error occurred',
},
{
entitlements:
'At least one product must be selected if policy is restricted.',
},
],
])(
'%s violation list expanding',
async (format: string, resBody: object, expected: object) => {
fetchMock.mockResponses(
[
JSON.stringify(resBody),
{
status: 422,
statusText: '422 Unprocessable Content',
headers: {
...headers,
'Content-Type': `application/${format}; charset=utf-8`,
},
},
],
[
JSON.stringify({
'@context': {
'@vocab': 'http://localhost/docs.jsonld#',
hydra: 'http://www.w3.org/ns/hydra/core#',
},
}),
{
status: 200,
statusText: 'OK',
headers,
},
],
);

let violations;
try {
await fetchHydra(new URL('http://localhost/users'));
} catch (error) {
violations = schemaAnalyzer().getSubmissionErrors(error as HttpError);
}
expect(violations).toStrictEqual(expected);
},
);
20 changes: 14 additions & 6 deletions src/hydra/fetchHydra.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
getDocumentationUrlFromHeaders,
} from '@api-platform/api-doc-parser';
import jsonld from 'jsonld';
import type { NodeObject } from 'jsonld';
import type { ContextDefinition, NodeObject } from 'jsonld';
import type { JsonLdObj } from 'jsonld/jsonld-spec';
import type { HttpClientOptions, HydraHttpClientResponse } from '../types.js';

Expand Down Expand Up @@ -54,12 +54,20 @@ function fetchHydra(
return response;
});
};
const base = getDocumentationUrlFromHeaders(headers);

return jsonld
.expand(body, {
base: getDocumentationUrlFromHeaders(headers),
documentLoader,
})
return (
'@context' in body
? jsonld.expand(body, {
base,
documentLoader,
})
: documentLoader(base).then((response) =>
jsonld.expand(body, {
expandContext: response.document as ContextDefinition,
}),
)
)
.then((json) =>
Promise.reject(
new HttpError(
Expand Down

0 comments on commit cef2c57

Please sign in to comment.