diff --git a/ghost/core/test/e2e-api/admin/__snapshots__/pages.test.js.snap b/ghost/core/test/e2e-api/admin/__snapshots__/pages.test.js.snap index 1c0445b339..caf0708db7 100644 --- a/ghost/core/test/e2e-api/admin/__snapshots__/pages.test.js.snap +++ b/ghost/core/test/e2e-api/admin/__snapshots__/pages.test.js.snap @@ -1488,3 +1488,360 @@ Object { "x-powered-by": "Express", } `; + +exports[`Pages API Update Works with featured collection card 1: [body] 1`] = ` +Object { + "pages": Array [ + Object { + "authors": Any, + "canonical_url": null, + "codeinjection_foot": null, + "codeinjection_head": null, + "comment_id": Any, + "count": Object { + "negative_feedback": 0, + "paid_conversions": 0, + "positive_feedback": 0, + "signups": 0, + }, + "created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "custom_excerpt": null, + "custom_template": null, + "excerpt": " + + +Featured + + + + + + + + +Not so short, bit complex + + +* Lorem +* Aliquam +* Tortor +* Morbi +* Praesent +* Pellentesque + +Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo. + +1234abcdefghijkl + +Definition listConsectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et d", + "feature_image": null, + "feature_image_alt": null, + "feature_image_caption": null, + "featured": false, + "frontmatter": null, + "html": "

Testing

", + "id": StringMatching /\\[a-f0-9\\]\\{24\\}/, + "lexical": "{\\"root\\":{\\"children\\":[{\\"type\\":\\"collection\\",\\"version\\":1,\\"collection\\":\\"featured\\",\\"postCount\\":3,\\"layout\\":\\"grid\\",\\"columns\\":3,\\"header\\":\\"Featured\\"},{\\"children\\":[{\\"detail\\":0,\\"format\\":0,\\"mode\\":\\"normal\\",\\"style\\":\\"\\",\\"text\\":\\"Testing\\",\\"type\\":\\"text\\",\\"version\\":1}],\\"direction\\":\\"ltr\\",\\"format\\":\\"\\",\\"indent\\":0,\\"type\\":\\"paragraph\\",\\"version\\":1}],\\"direction\\":null,\\"format\\":\\"\\",\\"indent\\":0,\\"type\\":\\"root\\",\\"version\\":1}}", + "meta_description": null, + "meta_title": null, + "mobiledoc": null, + "og_description": null, + "og_image": null, + "og_title": null, + "post_revisions": Any, + "primary_author": Any, + "primary_tag": Any, + "published_at": null, + "reading_time": 1, + "show_title_and_feature_image": Any, + "slug": "latest-collection-card-test-2", + "status": "draft", + "tags": Any, + "tiers": Array [ + Object { + "active": true, + "created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "currency": null, + "description": null, + "id": StringMatching /\\[a-f0-9\\]\\{24\\}/, + "monthly_price": null, + "monthly_price_id": null, + "name": "Free", + "slug": "free", + "trial_days": 0, + "type": "free", + "updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "visibility": "public", + "welcome_page_url": null, + "yearly_price": null, + "yearly_price_id": null, + }, + Object { + "active": true, + "created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "currency": "usd", + "description": null, + "id": StringMatching /\\[a-f0-9\\]\\{24\\}/, + "monthly_price": 500, + "monthly_price_id": null, + "name": "Default Product", + "slug": "default-product", + "trial_days": 0, + "type": "paid", + "updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "visibility": "public", + "welcome_page_url": null, + "yearly_price": 5000, + "yearly_price_id": null, + }, + ], + "title": "Latest Collection Card Test", + "twitter_description": null, + "twitter_image": null, + "twitter_title": null, + "updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "url": Any, + "uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/, + "visibility": "public", + }, + ], +} +`; + +exports[`Pages API Update Works with latest collection card 1: [body] 1`] = ` +Object { + "pages": Array [ + Object { + "authors": Any, + "canonical_url": null, + "codeinjection_foot": null, + "codeinjection_head": null, + "comment_id": Any, + "count": Object { + "negative_feedback": 0, + "paid_conversions": 0, + "positive_feedback": 0, + "signups": 0, + }, + "created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "custom_excerpt": null, + "custom_template": null, + "excerpt": " + + +Latest + + + + + + + + + + +Start here for a quick overview of everything you need to know + + +We've crammed the most important information to help you get started with Ghost into this one post. It's your cheat-sheet to get started, and your shortcut to advanced features. + + + +25 Sep 2023 + + + · 2 min + + + + + + + + + + + + +Customizing your brand and design settings + + +How to tweak a few settings in Ghost to transform your site from a generic template to a custom brand with style and personality. + + + +25 Sep 2023 + + + · 3 mi", + "feature_image": null, + "feature_image_alt": null, + "feature_image_caption": null, + "featured": false, + "frontmatter": null, + "html": "

Testing

", + "id": StringMatching /\\[a-f0-9\\]\\{24\\}/, + "lexical": "{\\"root\\":{\\"children\\":[{\\"type\\":\\"collection\\",\\"version\\":1,\\"collection\\":\\"latest\\",\\"postCount\\":3,\\"layout\\":\\"grid\\",\\"columns\\":3,\\"header\\":\\"Latest\\"},{\\"children\\":[{\\"detail\\":0,\\"format\\":0,\\"mode\\":\\"normal\\",\\"style\\":\\"\\",\\"text\\":\\"Testing\\",\\"type\\":\\"text\\",\\"version\\":1}],\\"direction\\":\\"ltr\\",\\"format\\":\\"\\",\\"indent\\":0,\\"type\\":\\"paragraph\\",\\"version\\":1}],\\"direction\\":null,\\"format\\":\\"\\",\\"indent\\":0,\\"type\\":\\"root\\",\\"version\\":1}}", + "meta_description": null, + "meta_title": null, + "mobiledoc": null, + "og_description": null, + "og_image": null, + "og_title": null, + "post_revisions": Any, + "primary_author": Any, + "primary_tag": Any, + "published_at": null, + "reading_time": 1, + "show_title_and_feature_image": Any, + "slug": "latest-collection-card-test", + "status": "draft", + "tags": Any, + "tiers": Array [ + Object { + "active": true, + "created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "currency": null, + "description": null, + "id": StringMatching /\\[a-f0-9\\]\\{24\\}/, + "monthly_price": null, + "monthly_price_id": null, + "name": "Free", + "slug": "free", + "trial_days": 0, + "type": "free", + "updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "visibility": "public", + "welcome_page_url": null, + "yearly_price": null, + "yearly_price_id": null, + }, + Object { + "active": true, + "created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "currency": "usd", + "description": null, + "id": StringMatching /\\[a-f0-9\\]\\{24\\}/, + "monthly_price": 500, + "monthly_price_id": null, + "name": "Default Product", + "slug": "default-product", + "trial_days": 0, + "type": "paid", + "updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "visibility": "public", + "welcome_page_url": null, + "yearly_price": 5000, + "yearly_price_id": null, + }, + ], + "title": "Latest Collection Card Test", + "twitter_description": null, + "twitter_image": null, + "twitter_title": null, + "updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "url": Any, + "uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/, + "visibility": "public", + }, + ], +} +`; diff --git a/ghost/core/test/e2e-api/admin/pages.test.js b/ghost/core/test/e2e-api/admin/pages.test.js index 3e85e7dceb..9eafc97d67 100644 --- a/ghost/core/test/e2e-api/admin/pages.test.js +++ b/ghost/core/test/e2e-api/admin/pages.test.js @@ -1,3 +1,4 @@ +const _ = require('lodash'); const {mobiledocToLexical} = require('@tryghost/kg-converters'); const models = require('../../../core/server/models'); const {agentProvider, fixtureManager, mockManager, matchers} = require('../../utils/e2e-framework'); @@ -164,6 +165,158 @@ describe('Pages API', function () { 'x-cache-invalidate': anyString }); }); + + it('Works with latest collection card', async function () { + const initialLexical = { + root: { + children: [ + { + type: 'collection', + version: 1, + collection: 'latest', + postCount: 3, + layout: 'grid', + columns: 3, + header: 'Latest' + } + ], + direction: null, + format: '', + indent: 0, + type: 'root', + version: 1 + } + }; + + const updatedLexical = _.cloneDeep(initialLexical); + updatedLexical.root.children.push({ + children: [ + { + detail: 0, + format: 0, + mode: 'normal', + style: '', + text: 'Testing', + type: 'text', + version: 1 + } + ], + direction: 'ltr', + format: '', + indent: 0, + type: 'paragraph', + version: 1 + }); + + const page = { + title: 'Latest Collection Card Test', + status: 'draft', + lexical: JSON.stringify(initialLexical) + }; + + const {body: createBody} = await agent + .post('/pages/?formats=mobiledoc,lexical,html', { + headers: { + 'content-type': 'application/json' + } + }) + .body({pages: [page]}) + .expectStatus(201); + + const [createResponse] = createBody.pages; + + await agent + .put(`/pages/${createResponse.id}/?formats=mobiledoc,lexical,html`) + .body({ + pages: [{ + id: createResponse.id, + lexical: JSON.stringify(updatedLexical), + updated_at: createResponse.updated_at // satisfy collision detection + }] + }) + .expectStatus(200) + .matchBodySnapshot({ + pages: [Object.assign({}, matchPageShallowIncludes, { + published_at: null + })] + }); + }); + + it('Works with featured collection card', async function () { + const initialLexical = { + root: { + children: [ + { + type: 'collection', + version: 1, + collection: 'featured', + postCount: 3, + layout: 'grid', + columns: 3, + header: 'Featured' + } + ], + direction: null, + format: '', + indent: 0, + type: 'root', + version: 1 + } + }; + + const updatedLexical = _.cloneDeep(initialLexical); + updatedLexical.root.children.push({ + children: [ + { + detail: 0, + format: 0, + mode: 'normal', + style: '', + text: 'Testing', + type: 'text', + version: 1 + } + ], + direction: 'ltr', + format: '', + indent: 0, + type: 'paragraph', + version: 1 + }); + + const page = { + title: 'Latest Collection Card Test', + status: 'draft', + lexical: JSON.stringify(initialLexical) + }; + + const {body: createBody} = await agent + .post('/pages/?formats=mobiledoc,lexical,html', { + headers: { + 'content-type': 'application/json' + } + }) + .body({pages: [page]}) + .expectStatus(201); + + const [createResponse] = createBody.pages; + + await agent + .put(`/pages/${createResponse.id}/?formats=mobiledoc,lexical,html`) + .body({ + pages: [{ + id: createResponse.id, + lexical: JSON.stringify(updatedLexical), + updated_at: createResponse.updated_at // satisfy collision detection + }] + }) + .expectStatus(200) + .matchBodySnapshot({ + pages: [Object.assign({}, matchPageShallowIncludes, { + published_at: null + })] + }); + }); }); describe('Copy', function () {