diff --git a/src/controllers/pageController.test.ts b/src/controllers/pageController.test.ts new file mode 100644 index 0000000..e927f58 --- /dev/null +++ b/src/controllers/pageController.test.ts @@ -0,0 +1,133 @@ +import * as faker from 'faker'; + +import { sequelize, PageLink } from '../models'; +import * as pageController from './pageController'; +import { PageLinkInstance } from '../models/PageLink'; + +beforeEach(async () => { + await sequelize.sync({ force: true }); +}); + +function getRandomPage() { + return { + showId: faker.random.number(), + name: faker.random.alphaNumeric(), + description: faker.hacker.phrase(), + url: faker.internet.url(), + image: faker.image.imageUrl(), + }; +} + +describe('createPage', () => { + it('should add a page link entry to the database', async () => { + const page = getRandomPage(); + + await pageController.createPage(page); + + const pageResultsArray = await PageLink.findAll({ + where: { + name: page.name, + }, + }); + + // We need the `plain: true` option so that we only get the object values we care about. + // See http://docs.sequelizejs.com/manual/tutorial/instances.html#values-of-an-instance + const pageResult = pageResultsArray[0].get({ + plain: true, + }); + + expect(pageResultsArray).toHaveLength(1); + expect(pageResult).toMatchObject(page); + expect(pageResult).toHaveProperty('id'); + expect(pageResult).toHaveProperty('createdAt'); + expect(pageResult).toHaveProperty('updatedAt'); + }); +}); + +describe('getPage', () => { + it('retrieves a page link from the database', async () => { + const page = { + showId: faker.random.number(), + name: faker.random.alphaNumeric(), + description: faker.hacker.phrase(), + url: faker.internet.url(), + image: faker.image.imageUrl(), + }; + await PageLink.create(page); + + const retrievedPageLinkInstance = await pageController.getPage(1); + const retrievedPageLinkAttributes = retrievedPageLinkInstance.get({ + plain: true, + }); + + expect(retrievedPageLinkAttributes).toMatchObject(page); + expect(retrievedPageLinkAttributes).toHaveProperty('id'); + expect(retrievedPageLinkAttributes).toHaveProperty('createdAt'); + expect(retrievedPageLinkAttributes).toHaveProperty('updatedAt'); + }); + + it('returns null if a page with the specified ID cannot be found', async () => { + const retrievedPageLinkInstance = await pageController.getPage(2); + expect(retrievedPageLinkInstance).toBeNull(); + }); +}); + +describe('getAllPages', () => { + it('returns an empty array when the database is empty', async () => { + expect(await pageController.getAllPages()).toHaveLength(0); + }); + + it('returns an array of all pages', async () => { + const page = getRandomPage(); + await PageLink.create(page); + + const allPages = await pageController.getAllPages(); + const retrievedPageLinkAttributes = allPages[0].get({ plain: true }); + + expect(allPages).toHaveLength(1); + expect(retrievedPageLinkAttributes).toMatchObject(page); + }); +}); + +describe('updatePage', () => { + it('updates an existing page from the database', async () => { + await PageLink.create(getRandomPage()); + + const newName = faker.random.alphaNumeric(); + + const updatedPageLinkInstance = await pageController.updatePage(1, { + name: newName, + }); + const retrievedPageLinkAttributes = updatedPageLinkInstance.get({ + plain: true, + }); + + expect(updatedPageLinkAttributes).toHaveProperty('name', newName); + }); + + it('returns null if a page with the specified ID cannot be found', async () => { + const updatedPageLinkInstance = await pageController.updatePage(2, { + name: faker.random.alphaNumeric(), + }); + + expect(updatedPageLinkInstance).toBeNull(); + }); +}); + +describe('deletePage', () => { + it('deletes a page from the database and returns true', async () => { + await PageLink.create(getRandomPage()); + + expect(await PageLink.findAll()).toHaveLength(1); + expect(await pageController.deletePage(1)).toBe(true); + expect(await PageLink.findAll()).toHaveLength(0); + }); + + it('does not delete a page from the database and returns false when the id is invalid', async () => { + await PageLink.create(getRandomPage()); + + expect(await PageLink.findAll()).toHaveLength(1); + expect(await pageController.deletePage(2)).toBe(false); + expect(await PageLink.findAll()).toHaveLength(1); + }); +}); diff --git a/src/controllers/pageController.ts b/src/controllers/pageController.ts new file mode 100644 index 0000000..9becb5a --- /dev/null +++ b/src/controllers/pageController.ts @@ -0,0 +1,83 @@ +import { PageLink } from '../models'; +import { PageLinkAttributes, PageLinkInstance } from '../models/PageLink'; + +/** + * Creates a page with the given attribues + * + * @param {PageLinkAttributes} attributes + * @returns The newly created page. + */ +export function createPage( + attributes: PageLinkAttributes +): Promise { + const newPageLink: PageLinkInstance = await PageLink.create(attribues); + return newPageLink; +} + +/** + * Gets the page with the given id. + * + * @param {number} id + * @returns the page corresponding to id + */ +export function getPage(id: number): Promise { + const pageLink: PageLinkInstance | null = await PageLink.findById(id); + return pageLink; +} + +/** + * Gets all pages. + * + */ +export function getAllPages(): Promise { + const pageLinks: PageLinkInstance[] = await PageLink.all(); + return pageLinks; +} + +/** + * Updates a page with the given attributes. Returns the updated page, or undefined if the page is not updated. + * + * @export + * @param {number} id + * @param {PageLinkAttributes} attributes + * @returns {(PageLinkInstance | null)} + */ +export function updatePage( + id: number, + attributes: PageLinkAttributes +): Promise { + const [numberOfUpdatedPageLinks, updatedPageLinks] = await PageLink.update( + attributes, + { + where: { id }, + returning: true, + } + ); + + if (numberOfUpdatedPageLinks === 1) { + return updatedPageLinks[0]; + } else if (numberOfUpdatedPageLinks !== 0) { + throw new Error( + 'More than 1 rows updated from single id in `updatePage`! This is bad!' + ); + } + return null; +} + +/** + * Deletes a page. Returns true if the page was successfully deleted, false otherwise. + * + * @param {numebr} id + */ +export function deletePage(id: number): Promise { + const numberOfDeletedPageLinks = await PageLink.destroy({ + where: { id }, + }); + + if (numberOfDeletedPageLinks === 1) { + return true; + } else if (numberOfDeletedPageLinks !== 0) { + throw new Error('More than 1 rows deleted from single id! This is bad!'); + } + return false; +}