-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adds support for discovering with headers
- Loading branch information
1 parent
355bc75
commit dc641c0
Showing
4 changed files
with
162 additions
and
105 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,135 +1,152 @@ | ||
import { Navigator } from '../src' | ||
import { setupServer } from 'msw/node' | ||
import { http, HttpResponse } from 'msw' | ||
import { faker } from '@faker-js/faker' | ||
import { randomProperty } from './data' | ||
import { MockServer } from './server' | ||
|
||
const server = setupServer() | ||
const server = new MockServer() | ||
|
||
beforeAll(() => server.listen()) | ||
afterAll(() => server.close()) | ||
beforeEach(() => server.resetHandlers()) | ||
|
||
describe('navigator', () => { | ||
test('status is 200 when discovering endpoint succeeds', async () => { | ||
const url = 'https://example.com' | ||
server.use(http.get(url, () => HttpResponse.json({}))) | ||
describe('discover', () => { | ||
test('passes headers when discovering endpoint', async () => { | ||
const url = 'https://example.com' | ||
const headerKey = faker.lorem.word() | ||
const headerValue = faker.lorem.word() | ||
const headers = {[headerKey]: headerValue} | ||
server.use(http.get(url, () => HttpResponse.json({}))) | ||
|
||
await Navigator.discover(url, {headers}) | ||
|
||
expect(server.recordedRequests).toHaveLength(1) | ||
expect(server.recordedRequests[0].headers.get(headerKey)).toStrictEqual(headerValue) | ||
}) | ||
|
||
const navigator = await Navigator.discover(url) | ||
test('status is 200 when discovering endpoint succeeds', async () => { | ||
const url = 'https://example.com' | ||
server.use(http.get(url, () => HttpResponse.json({}))) | ||
|
||
expect(navigator.status).toBe(200) | ||
}) | ||
const navigator = await Navigator.discover(url) | ||
|
||
test('resource is empty resource when discovering endpoint returns empty json object', async () => { | ||
const url = 'https://example.com' | ||
const resource = {} | ||
server.use(http.get(url, () => HttpResponse.json(resource))) | ||
expect(navigator.status).toBe(200) | ||
}) | ||
|
||
const navigator = await Navigator.discover(url) | ||
test('resource is empty resource when discovering endpoint returns empty json object', async () => { | ||
const url = 'https://example.com' | ||
const resource = {} | ||
server.use(http.get(url, () => HttpResponse.json(resource))) | ||
|
||
expect(navigator.status).toBe(200) | ||
expect(navigator.resource.toObject()).toStrictEqual(resource) | ||
}) | ||
const navigator = await Navigator.discover(url) | ||
|
||
test('resource has property when discovering endpoint succeeds with json with property', async () => { | ||
const key = faker.lorem.word() | ||
const value = randomProperty() | ||
const url = 'https://example.com' | ||
const resource = { [key]: value } | ||
server.use(http.get(url, () => HttpResponse.json(resource))) | ||
expect(navigator.status).toBe(200) | ||
expect(navigator.resource.toObject()).toStrictEqual(resource) | ||
}) | ||
|
||
const navigator = await Navigator.discover(url) | ||
test('resource has property when discovering endpoint succeeds with json with property', async () => { | ||
const key = faker.lorem.word() | ||
const value = randomProperty() | ||
const url = 'https://example.com' | ||
const resource = { [key]: value } | ||
server.use(http.get(url, () => HttpResponse.json(resource))) | ||
|
||
expect(navigator.status).toBe(200) | ||
expect(navigator.resource.getProperty(key)).toStrictEqual(value) | ||
}) | ||
const navigator = await Navigator.discover(url) | ||
|
||
test('status is status from response when service returns client or server error', async () => { | ||
const statusCode = faker.internet.httpStatusCode({ | ||
types: ['clientError', 'serverError'], | ||
expect(navigator.status).toBe(200) | ||
expect(navigator.resource.getProperty(key)).toStrictEqual(value) | ||
}) | ||
const url = 'https://example.com' | ||
server.use( | ||
http.get(url, () => HttpResponse.json({}, { status: statusCode })), | ||
) | ||
|
||
const navigator = await Navigator.discover(url) | ||
test('status is status from response when service returns client or server error', async () => { | ||
const statusCode = faker.internet.httpStatusCode({ | ||
types: ['clientError', 'serverError'], | ||
}) | ||
const url = 'https://example.com' | ||
server.use( | ||
http.get(url, () => HttpResponse.json({}, { status: statusCode })), | ||
) | ||
|
||
expect(navigator.status).toBe(statusCode) | ||
}) | ||
const navigator = await Navigator.discover(url) | ||
|
||
test('status is 200 when getting relation succeeds', async () => { | ||
const relation = faker.lorem.word() | ||
const url = 'https://example.com' | ||
const linkUrl = 'https://example.com/somethings/123' | ||
const resource = { | ||
_links: { | ||
[relation]: { href: linkUrl }, | ||
}, | ||
} | ||
server.use(http.get(url, () => HttpResponse.json(resource))) | ||
server.use(http.get(linkUrl, () => HttpResponse.json({}))) | ||
const discoveryNavigator = await Navigator.discover(url) | ||
|
||
const navigator = await discoveryNavigator.get(relation) | ||
|
||
expect(navigator.status).toBe(200) | ||
expect(navigator.status).toBe(statusCode) | ||
}) | ||
}) | ||
|
||
test('status is status from response when getting relation returns client or server error', async () => { | ||
const relation = faker.lorem.word() | ||
const url = 'https://example.com' | ||
const linkUrl = 'https://example.com/somethings/123' | ||
const resource = { | ||
_links: { | ||
[relation]: { href: linkUrl }, | ||
}, | ||
} | ||
const statusCode = faker.internet.httpStatusCode({ | ||
types: ['clientError', 'serverError'], | ||
describe('get', () => { | ||
test('status is 200 when getting relation succeeds', async () => { | ||
const relation = faker.lorem.word() | ||
const url = 'https://example.com' | ||
const linkUrl = 'https://example.com/somethings/123' | ||
const resource = { | ||
_links: { | ||
[relation]: { href: linkUrl }, | ||
}, | ||
} | ||
server.use(http.get(url, () => HttpResponse.json(resource))) | ||
server.use(http.get(linkUrl, () => HttpResponse.json({}))) | ||
const discoveryNavigator = await Navigator.discover(url) | ||
|
||
const navigator = await discoveryNavigator.get(relation) | ||
|
||
expect(navigator.status).toBe(200) | ||
}) | ||
server.use(http.get(url, () => HttpResponse.json(resource))) | ||
server.use( | ||
http.get(linkUrl, () => HttpResponse.json({}, { status: statusCode })), | ||
) | ||
const discoveryNavigator = await Navigator.discover(url) | ||
|
||
const navigator = await discoveryNavigator.get(relation) | ||
|
||
expect(navigator.status).toBe(statusCode) | ||
}) | ||
test('status is status from response when getting relation returns client or server error', async () => { | ||
const relation = faker.lorem.word() | ||
const url = 'https://example.com' | ||
const linkUrl = 'https://example.com/somethings/123' | ||
const resource = { | ||
_links: { | ||
[relation]: { href: linkUrl }, | ||
}, | ||
} | ||
const statusCode = faker.internet.httpStatusCode({ | ||
types: ['clientError', 'serverError'], | ||
}) | ||
server.use(http.get(url, () => HttpResponse.json(resource))) | ||
server.use( | ||
http.get(linkUrl, () => HttpResponse.json({}, { status: statusCode })), | ||
) | ||
const discoveryNavigator = await Navigator.discover(url) | ||
|
||
const navigator = await discoveryNavigator.get(relation) | ||
|
||
expect(navigator.status).toBe(statusCode) | ||
}) | ||
|
||
test('linked resource has property when getting relation succeeds with json with property', async () => { | ||
const relation = faker.lorem.word() | ||
const url = 'https://example.com' | ||
const linkUrl = 'https://example.com/somethings/123' | ||
const resource = { | ||
_links: { | ||
[relation]: { href: linkUrl }, | ||
}, | ||
} | ||
const key = faker.lorem.word() | ||
const value = randomProperty() | ||
const linkedResource = { [key]: value } | ||
server.use(http.get(url, () => HttpResponse.json(resource))) | ||
server.use(http.get(linkUrl, () => HttpResponse.json(linkedResource))) | ||
const discoveryNavigator = await Navigator.discover(url) | ||
|
||
const navigator = await discoveryNavigator.get(relation) | ||
|
||
expect(navigator.resource.getProperty(key)).toStrictEqual(value) | ||
}) | ||
test('linked resource has property when getting relation succeeds with json with property', async () => { | ||
const relation = faker.lorem.word() | ||
const url = 'https://example.com' | ||
const linkUrl = 'https://example.com/somethings/123' | ||
const resource = { | ||
_links: { | ||
[relation]: { href: linkUrl }, | ||
}, | ||
} | ||
const key = faker.lorem.word() | ||
const value = randomProperty() | ||
const linkedResource = { [key]: value } | ||
server.use(http.get(url, () => HttpResponse.json(resource))) | ||
server.use(http.get(linkUrl, () => HttpResponse.json(linkedResource))) | ||
const discoveryNavigator = await Navigator.discover(url) | ||
|
||
const navigator = await discoveryNavigator.get(relation) | ||
|
||
expect(navigator.resource.getProperty(key)).toStrictEqual(value) | ||
}) | ||
|
||
test('throws when attempting to get link that does not exist on resource', async () => { | ||
const relation = 'non-existent-relation' | ||
const url = 'https://example.com' | ||
server.use(http.get(url, () => HttpResponse.json({}))) | ||
const navigator = await Navigator.discover(url) | ||
test('throws when attempting to get link that does not exist on resource', async () => { | ||
const relation = 'non-existent-relation' | ||
const url = 'https://example.com' | ||
server.use(http.get(url, () => HttpResponse.json({}))) | ||
const navigator = await Navigator.discover(url) | ||
|
||
const action = async () => await navigator.get(relation) | ||
const action = async () => await navigator.get(relation) | ||
|
||
expect(action).rejects.toThrow( | ||
`Link with relation '${relation}' does not exist on resource.`, | ||
) | ||
expect(action).rejects.toThrow( | ||
`Link with relation '${relation}' does not exist on resource.`, | ||
) | ||
}) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import { SetupServer, setupServer } from 'msw/node' | ||
import { RequestHandler } from 'msw/lib/core/handlers/RequestHandler' | ||
|
||
export class MockServer { | ||
|
||
private readonly server: SetupServer | ||
readonly recordedRequests: Array<Request> = [] | ||
|
||
constructor(...handlers: Array<RequestHandler>) { | ||
this.server = setupServer(...handlers) | ||
this.server.events.on('request:start', ({request}) => { | ||
this.recordedRequests.push(request) | ||
}) | ||
} | ||
|
||
listen() { | ||
this.server.listen() | ||
} | ||
close() { | ||
this.server.close() | ||
} | ||
|
||
resetHandlers(...nextHandlers: Array<RequestHandler>) { | ||
this.server.resetHandlers(...nextHandlers) | ||
} | ||
|
||
use(...handlers: Array<RequestHandler>) { | ||
this.server.use(...handlers) | ||
} | ||
|
||
|
||
} |