diff --git a/test/e2e-api/content/__snapshots__/pages.test.js.snap b/test/e2e-api/content/__snapshots__/pages.test.js.snap new file mode 100644 index 0000000000..f1cfbcbf2c --- /dev/null +++ b/test/e2e-api/content/__snapshots__/pages.test.js.snap @@ -0,0 +1,293 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Pages Content API Can request page 1: [body] 1`] = ` +Object { + "pages": Array [ + Object { + "access": true, + "canonical_url": null, + "codeinjection_foot": null, + "codeinjection_head": null, + "comment_id": "618ba1ffbe2896088840a6e9", + "created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000\\\\\\+\\\\d\\{2\\}:\\\\d\\{2\\}/, + "custom_excerpt": null, + "custom_template": null, + "excerpt": "Static page test is what this is for. +Hopefully you don't find it a bore.", + "feature_image": null, + "feature_image_alt": null, + "feature_image_caption": null, + "featured": false, + "frontmatter": null, + "html": "
Hopefully you don't find it a bore.
", + "id": "618ba1ffbe2896088840a6e9", + "meta_description": null, + "meta_title": null, + "og_description": null, + "og_image": null, + "og_title": null, + "page": true, + "published_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000\\\\\\+\\\\d\\{2\\}:\\\\d\\{2\\}/, + "reading_time": 0, + "slug": "static-page-test", + "title": "This is a static page", + "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\\}\\\\\\.000\\\\\\+\\\\d\\{2\\}:\\\\d\\{2\\}/, + "url": "http://127.0.0.1:2369/static-page-test/", + "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 Content API Can request page 2: [headers] 1`] = ` +Object { + "access-control-allow-origin": "*", + "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", + "content-length": "1076", + "content-type": "application/json; charset=utf-8", + "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, + "vary": "Accept-Encoding", + "x-powered-by": "Express", +} +`; + +exports[`Pages Content API Can request pages 1: [body] 1`] = ` +Object { + "meta": Object { + "pagination": Object { + "limit": 15, + "next": null, + "page": 1, + "pages": 1, + "prev": null, + "total": 5, + }, + }, + "pages": Array [ + Object { + "access": true, + "canonical_url": null, + "codeinjection_foot": null, + "codeinjection_head": null, + "comment_id": "6194d3ce51e2700162531a78", + "created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000\\\\\\+\\\\d\\{2\\}:\\\\d\\{2\\}/, + "custom_excerpt": null, + "custom_template": null, + "excerpt": "Unlike posts, pages in Ghost don't appear in the main feed. They're separate, +individual pages which only show up when you link to them. Great for content +which is important, but separate from your usual posts. + +An about page is a great example of one you might want to set up early on so +people can find out more about you, and what you do. Why should people subscribe +to your site and become a member? Details help! + +> Tip: If you're reading any post or page on your site and you notice something +y", + "feature_image": null, + "feature_image_alt": null, + "feature_image_caption": null, + "featured": false, + "frontmatter": null, + "html": "Unlike posts, pages in Ghost don't appear in the main feed. They're separate, individual pages which only show up when you link to them. Great for content which is important, but separate from your usual posts.
An about page is a great example of one you might want to set up early on so people can find out more about you, and what you do. Why should people subscribe to your site and become a member? Details help!
Tip: If you're reading any post or page on your site and you notice something you want to edit, you can add /edit
to the end of the URL – and you'll be taken directly to the Ghost editor.
Now tell the world what your site is all about.
", + "id": "6194d3ce51e2700162531a78", + "meta_description": null, + "meta_title": null, + "og_description": null, + "og_image": null, + "og_title": null, + "page": true, + "published_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000\\\\\\+\\\\d\\{2\\}:\\\\d\\{2\\}/, + "reading_time": 0, + "slug": "about", + "title": "About this site", + "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\\}\\\\\\.000\\\\\\+\\\\d\\{2\\}:\\\\d\\{2\\}/, + "url": "http://127.0.0.1:2369/about/", + "uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/, + "visibility": "public", + }, + Object { + "access": true, + "canonical_url": null, + "codeinjection_foot": null, + "codeinjection_head": null, + "comment_id": "6194d3ce51e2700162531a79", + "created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000\\\\\\+\\\\d\\{2\\}:\\\\d\\{2\\}/, + "custom_excerpt": null, + "custom_template": null, + "excerpt": "If you want to set up a contact page for people to be able to reach out to you, +the simplest way is to set up a simple page like this and list the different +ways people can reach out to you. + +For example, here's how to reach us! + * @Ghost [https://twitter.com/ghost] on Twitter + * @Ghost [https://www.facebook.com/ghost] on Facebook + * @Ghost [https://instagram.com/ghost] on Instagram + +If you prefer to use a contact form, almost all of the great embedded form +services work great with Ghost and are", + "feature_image": null, + "feature_image_alt": null, + "feature_image_caption": null, + "featured": false, + "frontmatter": null, + "html": "If you want to set up a contact page for people to be able to reach out to you, the simplest way is to set up a simple page like this and list the different ways people can reach out to you.
If you prefer to use a contact form, almost all of the great embedded form services work great with Ghost and are easy to set up:
", + "id": "6194d3ce51e2700162531a79", + "meta_description": null, + "meta_title": null, + "og_description": null, + "og_image": null, + "og_title": null, + "page": true, + "published_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000\\\\\\+\\\\d\\{2\\}:\\\\d\\{2\\}/, + "reading_time": 1, + "slug": "contact", + "title": "Contact", + "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\\}\\\\\\.000\\\\\\+\\\\d\\{2\\}:\\\\d\\{2\\}/, + "url": "http://127.0.0.1:2369/contact/", + "uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/, + "visibility": "public", + }, + Object { + "access": true, + "canonical_url": null, + "codeinjection_foot": null, + "codeinjection_head": null, + "comment_id": "6194d3ce51e2700162531a7b", + "created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000\\\\\\+\\\\d\\{2\\}:\\\\d\\{2\\}/, + "custom_excerpt": null, + "custom_template": null, + "excerpt": "Oh hey, you clicked every link of our starter content and even clicked this +small link in the footer! If you like Ghost and you're enjoying the product so +far, we'd hugely appreciate your support in any way you care to show it. + +Ghost is a non-profit organization, and we give away all our intellectual +property as open source software. If you believe in what we do, there are a +number of ways you can give us a hand, and we hugely appreciate all of them: + + * Contribute code via GitHub [https://gith", + "feature_image": null, + "feature_image_alt": null, + "feature_image_caption": null, + "featured": false, + "frontmatter": null, + "html": "Oh hey, you clicked every link of our starter content and even clicked this small link in the footer! If you like Ghost and you're enjoying the product so far, we'd hugely appreciate your support in any way you care to show it.
Ghost is a non-profit organization, and we give away all our intellectual property as open source software. If you believe in what we do, there are a number of ways you can give us a hand, and we hugely appreciate all of them:
Thanks for checking us out!
", + "id": "6194d3ce51e2700162531a7b", + "meta_description": null, + "meta_title": null, + "og_description": null, + "og_image": null, + "og_title": null, + "page": true, + "published_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000\\\\\\+\\\\d\\{2\\}:\\\\d\\{2\\}/, + "reading_time": 0, + "slug": "contribute", + "title": "Contribute", + "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\\}\\\\\\.000\\\\\\+\\\\d\\{2\\}:\\\\d\\{2\\}/, + "url": "http://127.0.0.1:2369/contribute/", + "uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/, + "visibility": "public", + }, + Object { + "access": true, + "canonical_url": null, + "codeinjection_foot": null, + "codeinjection_head": null, + "comment_id": "6194d3ce51e2700162531a7a", + "created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000\\\\\\+\\\\d\\{2\\}:\\\\d\\{2\\}/, + "custom_excerpt": null, + "custom_template": null, + "excerpt": "Wondering how Ghost fares when it comes to privacy and GDPR rules? Good news: +Ghost does not use any tracking cookies of any kind. + +You can integrate any products, services, ads or integrations with Ghost +yourself if you want to, but it's always a good idea to disclose how subscriber +data will be used by putting together a privacy page.", + "feature_image": null, + "feature_image_alt": null, + "feature_image_caption": null, + "featured": false, + "frontmatter": null, + "html": "Wondering how Ghost fares when it comes to privacy and GDPR rules? Good news: Ghost does not use any tracking cookies of any kind.
You can integrate any products, services, ads or integrations with Ghost yourself if you want to, but it's always a good idea to disclose how subscriber data will be used by putting together a privacy page.
", + "id": "6194d3ce51e2700162531a7a", + "meta_description": null, + "meta_title": null, + "og_description": null, + "og_image": null, + "og_title": null, + "page": true, + "published_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000\\\\\\+\\\\d\\{2\\}:\\\\d\\{2\\}/, + "reading_time": 0, + "slug": "privacy", + "title": "Privacy", + "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\\}\\\\\\.000\\\\\\+\\\\d\\{2\\}:\\\\d\\{2\\}/, + "url": "http://127.0.0.1:2369/privacy/", + "uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/, + "visibility": "public", + }, + Object { + "access": true, + "canonical_url": null, + "codeinjection_foot": null, + "codeinjection_head": null, + "comment_id": "618ba1ffbe2896088840a6e9", + "created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000\\\\\\+\\\\d\\{2\\}:\\\\d\\{2\\}/, + "custom_excerpt": null, + "custom_template": null, + "excerpt": "Static page test is what this is for. +Hopefully you don't find it a bore.", + "feature_image": null, + "feature_image_alt": null, + "feature_image_caption": null, + "featured": false, + "frontmatter": null, + "html": "Hopefully you don't find it a bore.
", + "id": "618ba1ffbe2896088840a6e9", + "meta_description": null, + "meta_title": null, + "og_description": null, + "og_image": null, + "og_title": null, + "page": true, + "published_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000\\\\\\+\\\\d\\{2\\}:\\\\d\\{2\\}/, + "reading_time": 0, + "slug": "static-page-test", + "title": "This is a static page", + "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\\}\\\\\\.000\\\\\\+\\\\d\\{2\\}:\\\\d\\{2\\}/, + "url": "http://127.0.0.1:2369/static-page-test/", + "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 Content API Can request pages 2: [headers] 1`] = ` +Object { + "access-control-allow-origin": "*", + "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", + "content-length": "9207", + "content-type": "application/json; charset=utf-8", + "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, + "vary": "Accept-Encoding", + "x-powered-by": "Express", +} +`; diff --git a/test/e2e-api/content/pages.test.js b/test/e2e-api/content/pages.test.js index c1f19f33a1..6acc5263c0 100644 --- a/test/e2e-api/content/pages.test.js +++ b/test/e2e-api/content/pages.test.js @@ -1,68 +1,57 @@ -const url = require('url'); -const should = require('should'); -const supertest = require('supertest'); -const testUtils = require('../../utils'); -const configUtils = require('../../utils/configUtils'); -const config = require('../../../core/shared/config'); -const localUtils = require('./utils'); +const assert = require('assert'); + +const {agentProvider, fixtureManager, matchers} = require('../../utils/e2e-framework'); +const {anyEtag, anyUuid, anyDateWithTimezoneOffset} = matchers; + +const pageMatcher = { + published_at: anyDateWithTimezoneOffset, + created_at: anyDateWithTimezoneOffset, + updated_at: anyDateWithTimezoneOffset, + uuid: anyUuid +}; describe('Pages Content API', function () { - let request; + let agent; before(async function () { - await localUtils.startGhost(); - request = supertest.agent(config.get('url')); - await testUtils.initFixtures('users:no-owner', 'user:inactive', 'posts', 'tags:extra', 'api_keys'); - }); - - afterEach(function () { - configUtils.restore(); + agent = await agentProvider.getContentAPIAgent(); + await fixtureManager.init('users:no-owner', 'user:inactive', 'posts', 'tags:extra', 'api_keys'); + agent.authenticate(); }); it('Can request pages', async function () { - const key = localUtils.getValidKey(); - const res = await request.get(localUtils.API.getApiQuery(`pages/?key=${key}`)) - .set('Origin', testUtils.API.getURL()) - .expect('Content-Type', /json/) - .expect('Cache-Control', testUtils.cacheRules.private) - .expect(200); + const res = await agent.get(`pages/`) + .expectStatus(200) + .matchHeaderSnapshot({ + etag: anyEtag + }) + .matchBodySnapshot({ + pages: new Array(5) + .fill(pageMatcher) + }); - res.headers.vary.should.eql('Accept-Encoding'); - should.exist(res.headers['access-control-allow-origin']); - should.not.exist(res.headers['x-cache-invalidate']); + assert.equal(res.body.pages[0].slug, 'about'); - const jsonResponse = res.body; - should.exist(jsonResponse.pages); - should.exist(jsonResponse.meta); - jsonResponse.pages.should.have.length(5); - - res.body.pages[0].slug.should.eql('about'); - - const urlParts = url.parse(res.body.pages[0].url); - should.exist(urlParts.protocol); - should.exist(urlParts.host); + const urlParts = new URL(res.body.pages[0].url); + assert.equal(urlParts.protocol, 'http:'); + assert.equal(urlParts.host, '127.0.0.1:2369'); }); it('Can request page', async function () { - const key = localUtils.getValidKey(); - const res = await request.get(localUtils.API.getApiQuery(`pages/${testUtils.DataGenerator.Content.posts[5].id}/?key=${key}`)) - .set('Origin', testUtils.API.getURL()) - .expect('Content-Type', /json/) - .expect('Cache-Control', testUtils.cacheRules.private) - .expect(200); + const res = await agent.get(`pages/${fixtureManager.get('posts', 5).id}/`) + .expectStatus(200) + .matchHeaderSnapshot({ + etag: anyEtag + }) + .matchBodySnapshot({ + pages: new Array(1) + .fill(pageMatcher) + }); - res.headers.vary.should.eql('Accept-Encoding'); - should.exist(res.headers['access-control-allow-origin']); - should.not.exist(res.headers['x-cache-invalidate']); + assert.equal(res.body.pages[0].slug, fixtureManager.get('posts', 5).slug); - const jsonResponse = res.body; - should.exist(jsonResponse.pages); - jsonResponse.pages.should.have.length(1); - - res.body.pages[0].slug.should.eql(testUtils.DataGenerator.Content.posts[5].slug); - - const urlParts = url.parse(res.body.pages[0].url); - should.exist(urlParts.protocol); - should.exist(urlParts.host); + const urlParts = new URL(res.body.pages[0].url); + assert.equal(urlParts.protocol, 'http:'); + assert.equal(urlParts.host, '127.0.0.1:2369'); }); });