Merge pull request 'Add back-end support for albums.' (#7) from backend_albums into master
Reviewed-on: #7pull/10/head
commit
af05e2fd5e
10 changed files with 405 additions and 73 deletions
@ -0,0 +1,40 @@ |
|||||||
|
const models = require('../models'); |
||||||
|
import * as api from '../../client/src/api'; |
||||||
|
import { EndpointError, EndpointHandler, catchUnhandledErrors } from './types'; |
||||||
|
|
||||||
|
export const AlbumDetailsEndpointHandler: EndpointHandler = async (req: any, res: any) => { |
||||||
|
if (!api.checkAlbumDetailsRequest(req)) { |
||||||
|
const e: EndpointError = { |
||||||
|
internalMessage: 'Invalid AlbumDetails request: ' + JSON.stringify(req.body), |
||||||
|
httpStatus: 400 |
||||||
|
}; |
||||||
|
throw e; |
||||||
|
} |
||||||
|
|
||||||
|
try { |
||||||
|
const albums = await models.Album.findAll({ |
||||||
|
include: [models.Artist, models.Tag, models.Song], |
||||||
|
where: { |
||||||
|
id: req.params.id |
||||||
|
} |
||||||
|
}); |
||||||
|
if (albums.length != 1) { |
||||||
|
const e: EndpointError = { |
||||||
|
internalMessage: 'There is no album with id ' + req.params.id + '.', |
||||||
|
httpStatus: 400 |
||||||
|
}; |
||||||
|
throw e; |
||||||
|
} |
||||||
|
let album = albums[0]; |
||||||
|
const response: api.AlbumDetailsResponse = { |
||||||
|
name: album.name, |
||||||
|
artistIds: album.Artists.map((artist: any) => artist.id), |
||||||
|
tagIds: album.Tags.map((tag: any) => tag.id), |
||||||
|
songIds: album.Songs.map((song: any) => song.id), |
||||||
|
storeLinks: album.storeLinks, |
||||||
|
} |
||||||
|
await res.send(response); |
||||||
|
} catch (e) { |
||||||
|
catchUnhandledErrors(e); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,63 @@ |
|||||||
|
const models = require('../models'); |
||||||
|
import * as api from '../../client/src/api'; |
||||||
|
import { EndpointError, EndpointHandler, catchUnhandledErrors } from './types'; |
||||||
|
const { Op } = require("sequelize"); |
||||||
|
|
||||||
|
export const CreateAlbumEndpointHandler: EndpointHandler = async (req: any, res: any) => { |
||||||
|
if (!api.checkCreateAlbumRequest(req)) { |
||||||
|
const e: EndpointError = { |
||||||
|
internalMessage: 'Invalid CreateAlbum request: ' + JSON.stringify(req.body), |
||||||
|
httpStatus: 400 |
||||||
|
}; |
||||||
|
throw e; |
||||||
|
} |
||||||
|
const reqObject: api.CreateAlbumRequest = req.body; |
||||||
|
|
||||||
|
// Start retrieving the artist instances to link the album to.
|
||||||
|
var artistInstancesPromise = reqObject.artistIds && models.Artist.findAll({ |
||||||
|
where: { |
||||||
|
id: { |
||||||
|
[Op.in]: reqObject.artistIds |
||||||
|
} |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
// Start retrieving the tag instances to link the album to.
|
||||||
|
var tagInstancesPromise = reqObject.tagIds && models.Tag.findAll({ |
||||||
|
where: { |
||||||
|
id: { |
||||||
|
[Op.in]: reqObject.tagIds |
||||||
|
} |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
// Upon finish retrieving artists and tags, create the album and associate it.
|
||||||
|
await Promise.all([artistInstancesPromise, tagInstancesPromise]) |
||||||
|
.then((values: any) => { |
||||||
|
var [artists, tags] = values; |
||||||
|
|
||||||
|
if ((reqObject.artistIds && artists.length !== reqObject.artistIds.length) || |
||||||
|
(reqObject.tagIds && tags.length !== reqObject.tagIds.length)) { |
||||||
|
const e: EndpointError = { |
||||||
|
internalMessage: 'Not all albums and/or artists and/or tags exist for CreateAlbum request: ' + JSON.stringify(req.body), |
||||||
|
httpStatus: 400 |
||||||
|
}; |
||||||
|
throw e; |
||||||
|
} |
||||||
|
|
||||||
|
var album = models.Album.build({ |
||||||
|
name: reqObject.name, |
||||||
|
storeLinks: reqObject.storeLinks || [], |
||||||
|
}); |
||||||
|
artists && album.addArtists(artists); |
||||||
|
tags && album.addTags(tags); |
||||||
|
return album.save(); |
||||||
|
}) |
||||||
|
.then((album: any) => { |
||||||
|
const responseObject: api.CreateSongResponse = { |
||||||
|
id: album.id |
||||||
|
}; |
||||||
|
res.status(200).send(responseObject); |
||||||
|
}) |
||||||
|
.catch(catchUnhandledErrors); |
||||||
|
} |
@ -0,0 +1,62 @@ |
|||||||
|
const models = require('../models'); |
||||||
|
import * as api from '../../client/src/api'; |
||||||
|
import { EndpointError, EndpointHandler, catchUnhandledErrors } from './types'; |
||||||
|
const { Op } = require("sequelize"); |
||||||
|
|
||||||
|
export const ModifyAlbumEndpointHandler: EndpointHandler = async (req: any, res: any) => { |
||||||
|
if (!api.checkModifyAlbumRequest(req)) { |
||||||
|
const e: EndpointError = { |
||||||
|
internalMessage: 'Invalid ModifyAlbum request: ' + JSON.stringify(req.body), |
||||||
|
httpStatus: 400 |
||||||
|
}; |
||||||
|
throw e; |
||||||
|
} |
||||||
|
const reqObject: api.ModifyAlbumRequest = req.body; |
||||||
|
|
||||||
|
// Start retrieving the artist instances to link the album to.
|
||||||
|
var artistInstancesPromise = reqObject.artistIds && models.Artist.findAll({ |
||||||
|
where: { |
||||||
|
id: { |
||||||
|
[Op.in]: reqObject.artistIds |
||||||
|
} |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
// Start retrieving the tag instances to link the album to.
|
||||||
|
var tagInstancesPromise = reqObject.tagIds && models.Tag.findAll({ |
||||||
|
where: { |
||||||
|
id: { |
||||||
|
[Op.in]: reqObject.tagIds |
||||||
|
} |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
// Start retrieving the album to modify.
|
||||||
|
var albumInstancePromise = models.Album.findOne({ |
||||||
|
where: { |
||||||
|
id: req.params.id |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
// Upon finish retrieving artists and albums, modify the album.
|
||||||
|
await Promise.all([artistInstancesPromise, tagInstancesPromise, albumInstancePromise]) |
||||||
|
.then(async (values: any) => { |
||||||
|
var [artists, tags, album] = values; |
||||||
|
if (!album) { |
||||||
|
const e: EndpointError = { |
||||||
|
internalMessage: 'There is no album with id ' + req.params.id + '.', |
||||||
|
httpStatus: 400 |
||||||
|
}; |
||||||
|
throw e; |
||||||
|
} |
||||||
|
if (reqObject.artistIds) { album.setArtists(artists) }; |
||||||
|
if (reqObject.tagIds) { album.setTags(tags) }; |
||||||
|
if (reqObject.name) { album.name = reqObject.name }; |
||||||
|
if (reqObject.storeLinks) { album.setStoreIds(reqObject.storeLinks) }; |
||||||
|
await album.save(); |
||||||
|
}) |
||||||
|
.then(() => { |
||||||
|
res.status(200).send({}); |
||||||
|
}) |
||||||
|
.catch(catchUnhandledErrors); |
||||||
|
} |
@ -0,0 +1,97 @@ |
|||||||
|
const chai = require('chai'); |
||||||
|
const chaiHttp = require('chai-http'); |
||||||
|
const express = require('express'); |
||||||
|
const models = require('../../../models'); |
||||||
|
import { SetupApp } from '../../../app'; |
||||||
|
import { expect } from 'chai'; |
||||||
|
import * as helpers from './helpers'; |
||||||
|
|
||||||
|
async function init() { |
||||||
|
chai.use(chaiHttp); |
||||||
|
const app = express(); |
||||||
|
SetupApp(app); |
||||||
|
await models.sequelize.sync({ force: true }); |
||||||
|
return app; |
||||||
|
} |
||||||
|
|
||||||
|
describe('POST /album with no name', () => { |
||||||
|
it('should fail', done => { |
||||||
|
init().then((app) => { |
||||||
|
chai |
||||||
|
.request(app) |
||||||
|
.post('/album') |
||||||
|
.send({}) |
||||||
|
.then((res) => { |
||||||
|
expect(res).to.have.status(400); |
||||||
|
done(); |
||||||
|
}); |
||||||
|
}); |
||||||
|
}); |
||||||
|
}); |
||||||
|
|
||||||
|
describe('POST /album with a correct request', () => { |
||||||
|
it('should succeed', done => { |
||||||
|
init().then((app) => { |
||||||
|
chai |
||||||
|
.request(app) |
||||||
|
.post('/album') |
||||||
|
.send({ |
||||||
|
name: "MyAlbum" |
||||||
|
}) |
||||||
|
.then((res) => { |
||||||
|
expect(res).to.have.status(200); |
||||||
|
expect(res.body).to.deep.equal({ |
||||||
|
id: 1 |
||||||
|
}); |
||||||
|
done(); |
||||||
|
}); |
||||||
|
}); |
||||||
|
}); |
||||||
|
}); |
||||||
|
|
||||||
|
|
||||||
|
describe('PUT /album on nonexistent album', () => { |
||||||
|
it('should fail', done => { |
||||||
|
init().then((app) => { |
||||||
|
chai |
||||||
|
.request(app) |
||||||
|
.put('/album/1') |
||||||
|
.send({ |
||||||
|
id: 1, |
||||||
|
name: "NewAlbumName" |
||||||
|
}) |
||||||
|
.then((res) => { |
||||||
|
expect(res).to.have.status(400); |
||||||
|
done(); |
||||||
|
}) |
||||||
|
}) |
||||||
|
}); |
||||||
|
}); |
||||||
|
|
||||||
|
describe('PUT /album with an existing album', () => { |
||||||
|
it('should succeed', done => { |
||||||
|
init().then((app) => { |
||||||
|
var req = chai.request(app).keepOpen(); |
||||||
|
helpers.createAlbum(req, { name: "MyAlbum" }, 200, { id: 1 }) |
||||||
|
.then(() => helpers.modifyAlbum(req, 1, { name: "MyNewAlbum" }, 200)) |
||||||
|
.then(() => helpers.checkAlbum(req, 1, 200, { name: "MyNewAlbum", storeLinks: [], tagIds: [], songIds: [], artistIds: [] })) |
||||||
|
.then(req.close) |
||||||
|
.then(done); |
||||||
|
}); |
||||||
|
}); |
||||||
|
}); |
||||||
|
|
||||||
|
describe('POST /album with tags', () => { |
||||||
|
it('should succeed', done => { |
||||||
|
init().then((app) => { |
||||||
|
var req = chai.request(app).keepOpen(); |
||||||
|
helpers.createTag(req, { name: "Root" }, 200, { id: 1 }) |
||||||
|
.then(() => helpers.createTag(req, { name: "Leaf", parentId: 1 }, 200, { id: 2 })) |
||||||
|
.then(() => helpers.createAlbum(req, { name: "MyAlbum", tagIds: [ 1, 2 ] }, 200, { id: 1 })) |
||||||
|
.then(() => helpers.checkAlbum(req, 1, 200, { name: "MyAlbum", storeLinks: [], tagIds: [ 1, 2 ], songIds: [], artistIds: [] })) |
||||||
|
.then(req.close) |
||||||
|
.then(done); |
||||||
|
}); |
||||||
|
}); |
||||||
|
}); |
||||||
|
|
Loading…
Reference in new issue