diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 69d302ed..241cac8e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -45,7 +45,7 @@ Remember, every time you make a change to the library you will need to re-run `y To run Cypress: -First compile all your changes to `nex-seo` made in the `src` directory: +First compile all your changes to `next-seo` made in the `src` directory: ``` yarn build diff --git a/README.md b/README.md index 15ca910f..8d587129 100644 --- a/README.md +++ b/README.md @@ -61,7 +61,7 @@ If you are using **`pages`** directory then `NextSeo` is **exactly what you need - [dangerouslySetAllPagesToNoFollow](#dangerouslysetallpagestonofollow) - [robotsProps](#robotsprops) - [Twitter](#twitter) - - [facebook](#facebook) + - [Facebook](#facebook) - [Canonical URL](#canonical-url) - [Alternate](#alternate) - [Additional Meta Tags](#additional-meta-tags) diff --git a/cypress/e2e/article.spec.js b/cypress/e2e/article.spec.js index 1c2d537d..e00220a1 100644 --- a/cypress/e2e/article.spec.js +++ b/cypress/e2e/article.spec.js @@ -132,4 +132,63 @@ describe('Article JSON-LD', () => { }); }); }); + + it('matches schema when type LiveBlogPosting', () => { + cy.visit('http://localhost:3000/jsonld/liveBlogPosting'); + cy.get('head script[type="application/ld+json"]').then(tags => { + const jsonLD = JSON.parse(tags[0].innerHTML); + assertSchema(schemas)('LiveBlogPosting', '1.0.0')(jsonLD); + }); + }); + + it('renders with all props when type LiveBlogPosting', () => { + cy.visit('http://localhost:3000/jsonld/liveBlogPosting'); + cy.get('head script[type="application/ld+json"]').then(tags => { + const jsonLD = JSON.parse(tags[0].innerHTML); + expect(jsonLD).to.deep.equal({ + '@context': 'https://schema.org', + '@type': 'LiveBlogPosting', + datePublished: '2023-11-03T11:00:00+02:00', + description: + 'Follow the announcements made during the 2023 Next.js Conf.', + mainEntityOfPage: { + '@type': 'WebPage', + '@id': 'https://example.com/liveblog', + }, + headline: 'Next.js Conf live coverage', + image: [ + 'https://example.com/photos/1x1/photo.jpg', + 'https://example.com/photos/4x3/photo.jpg', + 'https://example.com/photos/16x9/photo.jpg', + ], + dateModified: '2023-11-03T19:00:00+02:00', + author: { + '@type': 'Person', + name: 'Jane Blogs', + }, + coverageStartTime: '2023-11-03T11:00:00+02:00', + coverageEndTime: '2023-11-03T19:00:00+02:00', + liveBlogUpdate: [ + { + '@type': 'BlogPosting', + headline: 'Next.js 14: No New APIs', + articleBody: 'Lorem ipsum dolor sit amet …', + datePublished: '2023-11-03T18:15:00+02:00', + }, + { + '@type': 'BlogPosting', + headline: 'A faster, more personalized web.', + articleBody: 'Lorem ipsum dolor sit amet …', + datePublished: '2023-11-03T11:30:00+02:00', + }, + { + '@type': 'BlogPosting', + headline: 'Conference will start soon', + articleBody: 'In a few hours …', + datePublished: '2023-11-03T11:00:00+02:00', + }, + ], + }); + }); + }); }); diff --git a/cypress/schemas/blog-schema.js b/cypress/schemas/blog-schema.js index 379934d5..dab4f795 100644 --- a/cypress/schemas/blog-schema.js +++ b/cypress/schemas/blog-schema.js @@ -132,6 +132,5 @@ const blog100 = { description: 'This is a mighty good description of this blog.', }, }; - const blogVersions = versionSchemas(blog100); -export default blogVersions; +export { blogVersions as default, blog100 }; diff --git a/cypress/schemas/index.js b/cypress/schemas/index.js index c4892c35..8f849c41 100644 --- a/cypress/schemas/index.js +++ b/cypress/schemas/index.js @@ -3,6 +3,7 @@ import { combineSchemas } from '@cypress/schema-tools'; import articleVersions from './article-schema'; import breadCrumbVersions from './breadcrumb-schema'; import blogVersions from './blog-schema'; +import liveBlogVersions from './liveblog-schema'; import courseVersions from './course-schema'; import localBusiness from './local-business-schema'; import logoVersions from './logo-schema'; @@ -30,11 +31,11 @@ import imageVersions from './image-schema'; import campgroundVersions from './campground-schema'; import parkVersions from './park-schema'; - const schemas = combineSchemas( articleVersions, breadCrumbVersions, blogVersions, + liveBlogVersions, courseVersions, localBusiness, logoVersions, diff --git a/cypress/schemas/liveblog-schema.js b/cypress/schemas/liveblog-schema.js new file mode 100644 index 00000000..be3533bb --- /dev/null +++ b/cypress/schemas/liveblog-schema.js @@ -0,0 +1,72 @@ +import { versionSchemas } from '@cypress/schema-tools'; +import { blog100 } from './blog-schema'; + +const liveblog100 = { + ...blog100, + schema: { + ...blog100.schema, + title: 'LiveBlogPosting', + description: + 'An example schema describing JSON-LD for type: LiveBlogPosting', + properties: { + ...blog100.schema.properties, + coverageStartTime: { + type: 'string', + description: + 'The time when the live blog will begin covering the Event. ' + + "Note that coverage may begin before the Event's start time. The LiveBlogPosting may also be created before coverage begins.", + }, + coverageEndTime: { + type: 'string', + description: + 'The time when the live blog will stop covering the Event. Note that coverage may continue after the Event concludes.', + }, + liveBlogUpdate: { + type: 'array', + items: { + ...blog100.schema, + required: ['@type'], + additionalProperties: true, + }, + description: 'Array of blog posting updates', + }, + }, + }, + example: { + ...blog100.example, + '@type': 'LiveBlogPosting', + dateModified: '2024-05-08T22:15:00+02:00', + datePublished: '2024-05-08T11:13:18+02:00', + mainEntityOfPage: { + '@type': 'WebPage', + '@id': 'https://example.com/liveblog', + }, + headline: 'LiveBlog headline', + coverageStartTime: '2024-05-08T09:00:01+02:00', + coverageEndTime: '2024-05-09T09:00:01+02:00', + liveBlogUpdate: [ + { + '@type': 'BlogPosting', + datePublished: '2024-05-08T22:15:00+02:00', + headline: 'Final update', + articleBody: 'See you soon', + }, + { + '@type': 'BlogPosting', + datePublished: '2024-05-08T09:00:00+02:00', + headline: 'Hello', + articleBody: 'Live coverage demo.', + }, + ], + }, +}; + +// Despite the liveBlogUpdate's required config, we must +['author', 'mainEntityOfPage'].forEach(key => { + liveblog100.schema.properties.liveBlogUpdate.items.properties[ + key + ].required = false; +}); + +const liveBlogVersions = versionSchemas(liveblog100); +export default liveBlogVersions; diff --git a/e2e/pages/jsonld/liveBlogPosting.tsx b/e2e/pages/jsonld/liveBlogPosting.tsx new file mode 100644 index 00000000..e691c549 --- /dev/null +++ b/e2e/pages/jsonld/liveBlogPosting.tsx @@ -0,0 +1,49 @@ +import React from 'react'; +import { ArticleJsonLd } from '../../..'; + +function LiveBlogPosting() { + return ( + <> +