This repository has been archived by the owner on May 14, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: allow individual article retrieval
Generates a unique IRI for each article, and allows them to be accessed individually.
- Loading branch information
1 parent
852e951
commit c25a094
Showing
6 changed files
with
93 additions
and
3 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 |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import createHttpError from 'http-errors'; | ||
import { OK } from 'http-status-codes'; | ||
import { Next } from 'koa'; | ||
import url from 'url'; | ||
import { AppContext, AppMiddleware } from '../app'; | ||
import ArticleNotFound from '../errors/article-not-found'; | ||
|
||
export default (): AppMiddleware => ( | ||
async ({ | ||
articles, dataFactory: { namedNode }, request, response, | ||
}: AppContext, next: Next): Promise<void> => { | ||
const id = namedNode(url.resolve(request.origin, request.path)); | ||
|
||
try { | ||
response.dataset = await articles.get(id); | ||
} catch (error) { | ||
if (error instanceof ArticleNotFound) { | ||
throw new createHttpError.NotFound(error.message); | ||
} | ||
|
||
throw error; | ||
} | ||
|
||
response.status = OK; | ||
|
||
await next(); | ||
} | ||
); |
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 |
---|---|---|
@@ -0,0 +1,59 @@ | ||
import { namedNode } from '@rdfjs/data-model'; | ||
import createHttpError from 'http-errors'; | ||
import { OK } from 'http-status-codes'; | ||
import 'jest-rdf'; | ||
import { Response } from 'koa'; | ||
import InMemoryArticles from '../../src/adaptors/in-memory-articles'; | ||
import Articles from '../../src/articles'; | ||
import { WithDataset } from '../../src/middleware/dataset'; | ||
import article from '../../src/routes/article'; | ||
import createContext from '../context'; | ||
import createArticle from '../create-article'; | ||
import runMiddleware, { NextMiddleware } from '../middleware'; | ||
|
||
const makeRequest = async ( | ||
path: string, articles?: Articles, next?: NextMiddleware, | ||
): Promise<WithDataset<Response>> => ( | ||
runMiddleware(article(), createContext({ articles, path }), next) | ||
); | ||
|
||
describe('article', (): void => { | ||
it('should return a successful response', async (): Promise<void> => { | ||
const id = namedNode('http://example.com/path-to/article/one'); | ||
const articles = new InMemoryArticles(); | ||
await articles.set(id, createArticle({ id })); | ||
|
||
const response = await makeRequest('path-to/article/one', articles); | ||
|
||
expect(response.status).toBe(OK); | ||
}); | ||
|
||
it('should return the article', async (): Promise<void> => { | ||
const id = namedNode('http://example.com/path-to/article/one'); | ||
const articles = new InMemoryArticles(); | ||
const article1 = createArticle({ id }); | ||
await articles.set(id, article1); | ||
|
||
const response = await makeRequest('path-to/article/one', articles); | ||
|
||
expect([...response.dataset]).toEqualRdfQuadArray([...article1]); | ||
}); | ||
|
||
it('should throw an error if article is not found', async (): Promise<void> => { | ||
const response = makeRequest('path-to/article/not-found'); | ||
|
||
await expect(response).rejects.toBeInstanceOf(createHttpError.NotFound); | ||
await expect(response).rejects.toHaveProperty('message', 'Article http://example.com/path-to/article/not-found could not be found'); | ||
}); | ||
|
||
it('should call the next middleware', async (): Promise<void> => { | ||
const id = namedNode('http://example.com/path-to/article/one'); | ||
const articles = new InMemoryArticles(); | ||
await articles.set(id, createArticle({ id })); | ||
const next = jest.fn(); | ||
|
||
await makeRequest('path-to/article/one', articles, next); | ||
|
||
expect(next).toHaveBeenCalledTimes(1); | ||
}); | ||
}); |