diff --git a/server/__tests__/integration/server/routes/api/v1/campaigns/campaign_put_endpoint.test.js b/server/__tests__/integration/server/routes/api/v1/campaigns/campaign_put_endpoint.test.js new file mode 100644 index 000000000..5ba9b1479 --- /dev/null +++ b/server/__tests__/integration/server/routes/api/v1/campaigns/campaign_put_endpoint.test.js @@ -0,0 +1,56 @@ +const request = require('supertest') +const app = require('../../../../../../../app') +const Campaign = require('../../../../../../../db/models/campaign') + +jest.mock('../../../../../../../db/models/campaign') + +describe('PUT /api/v1/campaigns/:id', () => { + it('should return 200 if successfully updated the campaign', async () => { + const campaignData = { + id: 5, + name: "Sogorea 'Te Land Trust", + organization: "Sogorea 'Te Land Trust", + page_url: 'https://sogoreate-landtrust.org/', + cause: 'Civic Rights', + type: 'Grant' + } + // Mock patchAndFetchById to return a resolved promise + Campaign.query.mockReturnValue({ + patchAndFetchById: jest.fn().mockResolvedValue(campaignData) + }) + const response = await request(app).put('/api/v1/campaigns/5').send({ + campaign: campaignData + }) + expect(response.status).toBe(200) + expect(response.body.campaign).toEqual(campaignData) + }) + + it('should return 400 if no campaign is found', async () => { + // Mock patchAndFetchById to return undefined + Campaign.query.mockReturnValue({ + patchAndFetchById: jest.fn().mockResolvedValue(undefined) + }) + const response = await request(app) + .put('/api/v1/campaigns/999999') + .send({ campaign: { type: 'Accelerator' } }) + + expect(response.status).toBe(404) + expect(response.body.msg).toBe('Campaign not found') + }) + + it('should return 500 for invalid update', async () => { + // Mock patchAndFetchById to throw an error + Campaign.query.mockReturnValue({ + patchAndFetchById: jest.fn().mockRejectedValue(new Error('Server error')) + }) + const response = await request(app) + .put('/api/v1/campaigns/5') + .send({ + campaign: { + type: 'random' + } + }) + + expect(response.status).toBe(500) + }) +}) diff --git a/server/api.js b/server/api.js index c7e5e57e3..32673aacf 100644 --- a/server/api.js +++ b/server/api.js @@ -13,6 +13,9 @@ const checkout = require('./routes/api/checkout') const twilio = require('./routes/api/twilio') const eventLogger = require('./routes/api/event_logger') +// import the whole collection of v1 routes +const v1Router = require('./routes/api/v1/v1.js') + // Created a nested router const apiRouter = express.Router() @@ -36,4 +39,7 @@ apiRouter.use('/checkout', checkout) apiRouter.use('/twilio', twilio) apiRouter.use('/event_logger', eventLogger) +// Create the /v1 portion of the url. +apiRouter.use('/v1', v1Router) + module.exports = apiRouter diff --git a/server/db/models/campaign.js b/server/db/models/campaign.js index 55b9fa70f..1b1ccd244 100644 --- a/server/db/models/campaign.js +++ b/server/db/models/campaign.js @@ -29,21 +29,6 @@ class Campaign extends BaseModel { } } } - - // This object defines the relations to other models. - static get relationMappings() { - const LetterVersion = require('./letter-version') - return { - LetterVersions: { - relation: BaseModel.HasManyRelation, - modelClass: LetterVersion, - join: { - from: 'campaigns.id', - to: 'letter_versions.campaign_id' - } - } - } - } } module.exports = Campaign diff --git a/server/routes/api/v1/campaigns/index.js b/server/routes/api/v1/campaigns/index.js new file mode 100644 index 000000000..0a6e31c48 --- /dev/null +++ b/server/routes/api/v1/campaigns/index.js @@ -0,0 +1,28 @@ +const express = require('express') +const Campaign = require('../../../../db/models/campaign') + +const router = express.Router() + +// PUT request to update a campaign +router.put('/:id', async (req, res) => { + const campaignId = req.params.id + + if (!campaignId) return res.status(404).end() + + try { + const updatedCampaign = await Campaign.query().patchAndFetchById( + campaignId, + req.body.campaign + ) + if (!updatedCampaign) + return res.status(404).json({ msg: 'Campaign not found' }).end() + + return res.status(200).json({ campaign: updatedCampaign }).end() + } catch (error) { + console.error(error.message) + + return res.status(500).json({ msg: error.message }).end() + } +}) + +module.exports = router diff --git a/server/routes/api/v1/v1.js b/server/routes/api/v1/v1.js new file mode 100644 index 000000000..a084330ab --- /dev/null +++ b/server/routes/api/v1/v1.js @@ -0,0 +1,9 @@ +const express = require('express') +const campaigns = require('./campaigns') // If the routes file is named index.js, we can omit it when we do the import instead of writing './campaigns/index'. + +const v1Router = express.Router() + +// Create the final piece of the url /campaigns +v1Router.use('/campaigns', campaigns) + +module.exports = v1Router