🐛 Fixed bug preventing changes to tier benefit capitalization (#18406)

fixes TryGhost/Product#3970

- When saving a tier, it is impossible to change the capitalization of a
benefit
- The logic when saving a tier matches benefits by `name.toLowercase()`
and then overwrites the incoming change with the name from the previous
version of the benefit
- This changes the logic to match benefits the same way using
`name.toLowercase()`, but use the _incoming_ benefit's capitalization
rather than the old benefit's, to allow users to e.g. change 'TEst
benefit' to 'Test benefit'
This commit is contained in:
Chris Raible 2023-10-05 19:04:11 -07:00 committed by GitHub
parent d812781888
commit 70304d92d4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 130 additions and 1 deletions

View File

@ -82,7 +82,7 @@ const Product = ghostBookshelf.Model.extend({
return benefitToSave.name.toLowerCase() === existingBenefit.get('name').toLowerCase();
});
if (existingBenefitModel) {
benefitToSave.name = existingBenefitModel.get('name');
benefitToSave.id = existingBenefitModel.id;
}
});

View File

@ -159,6 +159,84 @@ Object {
}
`;
exports[`Tiers API Can update a benefit's capitalization 1: [body] 1`] = `
Object {
"tiers": Array [
Object {
"active": true,
"benefits": Array [
"TEST BENEFIT",
],
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}/,
"currency": "USD",
"description": null,
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"monthly_price": 100,
"name": "benefit test tier",
"slug": "benefit-test-tier",
"trial_days": 0,
"type": "paid",
"updated_at": null,
"visibility": "public",
"welcome_page_url": null,
"yearly_price": 5000,
},
],
}
`;
exports[`Tiers API Can update a benefit's capitalization 1: [headers] 1`] = `
Object {
"access-control-allow-origin": "http://127.0.0.1:2369",
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
"content-length": "832",
"content-type": "application/json; charset=utf-8",
"content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/,
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
"vary": "Accept-Version, Origin, Accept-Encoding",
"x-powered-by": "Express",
}
`;
exports[`Tiers API Can update a benefit's capitalization 2: [body] 1`] = `
Object {
"tiers": Array [
Object {
"active": true,
"benefits": Array [
"Test benefit",
],
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}/,
"currency": "USD",
"description": null,
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"monthly_price": 100,
"name": "benefit test tier",
"slug": "benefit-test-tier",
"trial_days": 0,
"type": "paid",
"updated_at": null,
"visibility": "public",
"welcome_page_url": null,
"yearly_price": 5000,
},
],
}
`;
exports[`Tiers API Can update a benefit's capitalization 3: [headers] 1`] = `
Object {
"access-control-allow-origin": "http://127.0.0.1:2369",
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
"content-length": "350",
"content-type": "application/json; charset=utf-8",
"content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/,
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
"vary": "Accept-Version, Origin, Accept-Encoding",
"x-powered-by": "Express",
}
`;
exports[`Tiers API Errors when price is negative 1: [body] 1`] = `
Object {
"errors": Array [

View File

@ -5,6 +5,7 @@ const {
mockManager,
matchers
} = require('../../utils/e2e-framework');
const models = require('../../../core/server/models/index');
const {anyContentVersion, anyEtag} = matchers;
describe('Tiers API', function () {
@ -189,4 +190,54 @@ describe('Tiers API', function () {
})
});
});
it('Can update a benefit\'s capitalization', async function () {
const tierData = {
name: 'benefit test tier',
monthly_price: 100,
currency: 'usd',
benefits: ['TEST BENEFIT']
};
let {body: {tiers: [tier]}} = await agent.post('/tiers/')
.body({tiers: [tierData]})
.expectStatus(201)
.matchBodySnapshot({
tiers: Array(1).fill({
id: matchers.anyObjectId,
created_at: matchers.anyISODate,
name: 'benefit test tier',
slug: 'benefit-test-tier',
monthly_price: 100,
currency: 'USD'
})
});
await agent.put(`/tiers/${tier.id}/`)
.body({
tiers: [{
benefits: ['Test benefit']
}]
})
.expectStatus(200);
await agent.get(`/tiers/${tier.id}/`)
.expectStatus(200)
.matchHeaderSnapshot({
'content-version': anyContentVersion,
etag: anyEtag
})
.matchBodySnapshot({
tiers: Array(1).fill({
id: matchers.anyObjectId,
created_at: matchers.anyISODate,
benefits: ['Test benefit']
})
});
const benefit = await models.Benefit.findOne({slug: 'test-benefit'});
assert(benefit.attributes.name === 'Test benefit', 'The benefit should have been updated.');
const previousBenefit = await models.Benefit.findOne({slug: 'test-benefit-2'});
assert(!previousBenefit, 'The previous benefit should have been overwritten');
});
});