Repository: garmeeh/next-seo
Pull request #1112 (2022-11-25 06:50:31)

chore: Allow null for TS definitions about width and height of OpenGraphMedia 
Refs issue : https://github.com/garmeeh/next-seo/issues/975

## Description of Change(s):

---

To help get PR's merged faster, the following is required:

[ ] Updated the documentation
[V] Unit/Cypress test covering all cases

<img width="922" alt="image" src="https://user-images.githubusercontent.com/44645706/203917976-9950f1cf-3447-4d34-8287-6cb004ac82de.png">

<img width="565" alt="image" src="https://user-images.githubusercontent.com/44645706/203918065-db7055a9-20c2-46c6-a095-e94ec9bf121d.png">



Please link to relevant Google Docs or schema.org docs for what you are adding so we can review.

Please have a read of the Contributing Guide for full details.

https://github.com/garmeeh/next-seo/blob/master/CONTRIBUTING.md



Patch:
diff --git a/APP_DIRECTORY.md b/APP_DIRECTORY.md
index 0cb9236..34c98b4 100644
--- a/APP_DIRECTORY.md
+++ b/APP_DIRECTORY.md
@@ -18,7 +18,7 @@ If you are interested I carried out some testing and gave feedback to the Next.j
 
 ### Key Changes
 
-- Next.js no longer de-duplicates tags in the head. This means that we can no longer use `<DefaultSeo />` in the same way. Going forward we will solely be use `<NextSeo />`
+- Next.js no longer de-duplicates tags in the head. This means that we can no longer use `<DefaultSeo />` in the same way. Going forward we will solely use `<NextSeo />`
 - `head.js` does not currently support `<script>` tags that do no have `src=""`. So for JSON-LD components they now have to be added via the page. This will result in them being added to the `<body>` of the page. This is 100% ok for SEO and not to worry about. This was confirmed by Google. I have also validated this using schema tool.
 - Next.js no longer auto adds the tags below to your app that you will likely need. I suggest adding them to your root layout in a `<head>` tag.
 
diff --git a/README.md b/README.md
index 1c7e9c4..0bdbe00 100644
--- a/README.md
+++ b/README.md
@@ -3125,7 +3125,7 @@ export default () => (
 | `reviewedBy.type` | People or organizations that will review the content of the web page.                                |
 | `reviewedBy.name` | Name of the entity that have reviewed the content on this web page for accuracy and/or completeness. |
 
-For reference and more info check [Docs](https://schema.org/Brand)
+For reference and more info check [Docs](https://schema.org/WebPage)
 
 ### Image Metadata
 
diff --git a/src/jsonld/event.tsx b/src/jsonld/event.tsx
index ab31d10..b36eebc 100644
--- a/src/jsonld/event.tsx
+++ b/src/jsonld/event.tsx
@@ -56,8 +56,10 @@ function EventJsonLd({
     organizer: Array.isArray(organizer)
       ? organizer.map(setOrganizer)
       : setOrganizer(organizer),
-    eventStatus: `https://schema.org/${eventStatus}`,
-    eventAttendanceMode: `https://schema.org/${eventAttendanceMode}`,
+    eventStatus: eventStatus ? `https://schema.org/${eventStatus}` : undefined,
+    eventAttendanceMode: eventAttendanceMode
+      ? `https://schema.org/${eventAttendanceMode}`
+      : undefined,
   };
 
   return (
diff --git a/src/jsonld/product.tsx b/src/jsonld/product.tsx
index 4949b15..c59b41e 100644
--- a/src/jsonld/product.tsx
+++ b/src/jsonld/product.tsx
@@ -20,7 +20,7 @@ export interface ProductJsonLdProps extends JsonLdProps {
   images?: string[];
   description?: string;
   brand?: string;
-  reviews?: Review[];
+  reviews?: Review | Review[];
   aggregateRating?: AggregateRating;
   offers?: Offers | Offers[];
   aggregateOffer?: AggregateOffer;
diff --git a/src/jsonld/webPage.tsx b/src/jsonld/webPage.tsx
index ebd6c94..bf77658 100644
--- a/src/jsonld/webPage.tsx
+++ b/src/jsonld/webPage.tsx
@@ -1,10 +1,10 @@
 import React from 'react';
 import type { ReviewedBy } from 'src/types';
 
-import { JsonLd } from './jsonld';
+import { JsonLd, JsonLdProps } from './jsonld';
 import { setReviewedBy } from 'src/utils/schema/setReviewedBy';
 
-export interface WebPageJsonLdProps {
+export interface WebPageJsonLdProps extends JsonLdProps {
   keyOverride?: string;
   id: string;
   description?: string;
diff --git a/src/types.ts b/src/types.ts
index a52f034..4033e98 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -95,7 +95,7 @@ export interface VirtualLocation {
   url: string;
 }
 
-export type Location = Place | VirtualLocation;
+export type Location = string | Place | VirtualLocation;
 
 export type EventStatus =
   | 'EventCancelled'
@@ -155,20 +155,22 @@ export interface ItemListElements {
 }
 export interface OpenGraphMedia {
   url: string;
-  width?: number;
-  height?: number;
+  width?: number | null;
+  height?: number | null;
   alt?: string;
   type?: string;
   secureUrl?: string;
 }
 
-export interface Address {
-  streetAddress: string;
-  addressLocality: string;
-  addressRegion?: string;
-  postalCode: string;
-  addressCountry: string;
-}
+export type Address =
+  | string
+  | {
+      streetAddress: string;
+      addressLocality: string;
+      addressRegion?: string;
+      postalCode: string;
+      addressCountry: string;
+    };
 
 export interface Video {
   name: string;
diff --git a/src/utils/schema/setAddress.ts b/src/utils/schema/setAddress.ts
index 07dfab2..16a9c75 100644
--- a/src/utils/schema/setAddress.ts
+++ b/src/utils/schema/setAddress.ts
@@ -2,7 +2,7 @@ import { Address } from 'src/types';
 
 export function setAddress(address?: Address | Address[]) {
   if (!address) return undefined;
-  
+
   if (!Array.isArray(address)) return toPostalAddress(address);
 
   // If array of one address, replace with single address
@@ -13,5 +13,6 @@ export function setAddress(address?: Address | Address[]) {
 }
 
 function toPostalAddress(address: Address) {
+  if (typeof address === 'string') return address;
   return { '@type': 'PostalAddress', ...address };
 }
diff --git a/src/utils/schema/setLocation.ts b/src/utils/schema/setLocation.ts
index 6b3be55..9574e54 100644
--- a/src/utils/schema/setLocation.ts
+++ b/src/utils/schema/setLocation.ts
@@ -1,11 +1,15 @@
 import { Location, Place, VirtualLocation } from 'src/types';
 import { setAddress } from './setAddress';
 
-export function setLocation(location: Location) {
+export function setLocation(location?: Location) {
   if (!location) {
     return undefined;
   }
 
+  if (typeof location === 'string') {
+    return location;
+  }
+
   if ('url' in location) {
     return setVirtualLocation(location);
   } else {


Test patch:
diff --git a/e2e/pages/jsonld/index.tsx b/e2e/pages/jsonld/index.tsx
index a7f6dd0..191f490 100644
--- a/e2e/pages/jsonld/index.tsx
+++ b/e2e/pages/jsonld/index.tsx
@@ -10,7 +10,7 @@ const allJsonLDPages = [
   'corporateContact',
   'course',
   'dataset',
-  'even',
+  'event',
   'faq',
   'howTo',
   'jobPosting',
diff --git a/src/utils/schema/__tests__/setAddress.test.ts b/src/utils/schema/__tests__/setAddress.test.ts
index 2f22bb2..a38bff0 100644
--- a/src/utils/schema/__tests__/setAddress.test.ts
+++ b/src/utils/schema/__tests__/setAddress.test.ts
@@ -22,6 +22,10 @@ describe('setAddress', () => {
     expect(setAddress(undefined)).toBeUndefined();
   });
 
+  test('should accepts simple string and returns it', () => {
+    expect(setAddress('AddressText')).toBe('AddressText');
+  });
+
   test('single address returns correctly', () => {
     const data = setAddress(addressOne);
 
diff --git a/src/utils/schema/__tests__/setLocation.test.ts b/src/utils/schema/__tests__/setLocation.test.ts
new file mode 100644
index 0000000..af114bc
--- /dev/null
+++ b/src/utils/schema/__tests__/setLocation.test.ts
@@ -0,0 +1,37 @@
+import { Place, VirtualLocation } from 'src/types';
+import { setLocation } from '../setLocation';
+
+const virtualLocation: VirtualLocation = {
+  name: 'Virtual Location',
+  sameAs: 'https://example.com',
+  url: 'https://example.com',
+};
+
+const place: Place = {
+  name: 'Place',
+  address: 'Address String',
+};
+
+describe('setLocation', () => {
+  test('should return undefined if location is undefined', () => {
+    expect(setLocation(undefined)).toBeUndefined();
+  });
+
+  test('should accepts simple string and returns it', () => {
+    expect(setLocation('LocationText')).toBe('LocationText');
+  });
+
+  test('returns VirtualLocation correctly', () => {
+    expect(setLocation(virtualLocation)).toMatchObject({
+      '@type': 'VirtualLocation',
+      ...virtualLocation,
+    });
+  });
+
+  test('returns Place correctly', () => {
+    expect(setLocation(place)).toMatchObject({
+      '@type': 'Place',
+      ...place,
+    });
+  });
+});