-
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.
closes #21
- Loading branch information
Daniel J. Lauk
committed
Aug 16, 2021
1 parent
bb41486
commit 95d7b4f
Showing
2 changed files
with
103 additions
and
0 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
import { detectVersion } from './util' | ||
import { fetchWithTimeout } from '../http' | ||
jest.mock('../http') | ||
const mockedFetch = fetchWithTimeout as jest.MockedFunction< | ||
typeof fetchWithTimeout | ||
> | ||
|
||
const DEFAULT_URL = 'http://localhost:8080' | ||
|
||
describe('module api/util', () => { | ||
beforeEach(() => { | ||
mockedFetch.mockClear() | ||
}) | ||
|
||
describe('detectVersion', () => { | ||
it('returns version string from version field in response', async () => { | ||
const version = '1.2.3-rc4' | ||
mockedFetch.mockResolvedValueOnce({ | ||
ok: true, | ||
status: 200, | ||
json: () => Promise.resolve({ version }), | ||
} as Response) | ||
const actualVersion = await detectVersion(DEFAULT_URL) | ||
expect(actualVersion).toBe(version) | ||
}) | ||
|
||
it('returns undefined on HTTP 404', async () => { | ||
mockedFetch.mockResolvedValueOnce({ | ||
ok: false, | ||
status: 404, | ||
statusText: 'not found', | ||
} as Response) | ||
const actualVersion = await detectVersion(DEFAULT_URL) | ||
expect(actualVersion).toBe(undefined) | ||
}) | ||
|
||
it('throws on other HTTP errors', async () => { | ||
const fakeResponses = [ | ||
{ ok: false, status: 400, statusText: 'bad request' }, | ||
{ ok: false, status: 403, statusText: 'forbidden' }, | ||
{ ok: false, status: 405, statusText: 'method not allowed' }, | ||
{ ok: false, status: 406, statusText: 'not acceptable' }, | ||
{ ok: false, status: 408, statusText: 'request timeout' }, | ||
{ ok: false, status: 500, statusText: 'internal server error' }, | ||
{ ok: false, status: 501, statusText: 'not implemented' }, | ||
{ ok: false, status: 502, statusText: 'bad gateway' }, | ||
{ ok: false, status: 503, statusText: 'service unavailable' }, | ||
] | ||
for (const r of fakeResponses) { | ||
mockedFetch.mockResolvedValueOnce(r as Response) | ||
await expect(detectVersion(DEFAULT_URL)).rejects.toThrow() | ||
} | ||
}) | ||
|
||
it('throws if URL is falsy', async () => { | ||
const urls = [null, undefined, ''] | ||
expect.assertions(urls.length) | ||
for (const u of urls) { | ||
await expect(detectVersion(u as string)).rejects.toThrow() | ||
} | ||
}) | ||
}) | ||
}) |
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,40 @@ | ||
import * as decoders from 'decoders' | ||
import { fetchWithTimeout } from '../http' | ||
|
||
type VersionInfo = { | ||
version: string | ||
} | ||
const versionGuard = decoders.guard( | ||
decoders.object({ version: decoders.string }) | ||
) | ||
|
||
/** | ||
* Contact the API provider at base URL `url` and try to read | ||
* version information from endpoint `/version` with a GET request. | ||
* | ||
* @param url base url of the API provider | ||
* @returns A Promise that resolves to either the version string, or undefined if the version could not be read. | ||
*/ | ||
export const detectVersion = async ( | ||
url: RequestInfo | ||
): Promise<string | undefined> => { | ||
if (!url) throw new Error('need url') | ||
const resp = await fetchWithTimeout(url + '/version', { | ||
method: 'GET', | ||
headers: { Accept: 'application/json' }, | ||
}) | ||
if (resp.status === 404) { | ||
return undefined | ||
} | ||
if (!resp.ok) { | ||
throw new Error( | ||
`could not detect version: ${resp.status} ${resp.statusText}` | ||
) | ||
} | ||
try { | ||
const versionInfo: VersionInfo = versionGuard(await resp.json()) | ||
return versionInfo.version | ||
} catch (e) { | ||
throw new Error('received malformed version info') | ||
} | ||
} |