@treely/strapi-slices 2.1.0 → 2.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/dist/components/SEOTags/SEOTags.d.ts +14 -0
  2. package/dist/components/SEOTags/index.d.ts +1 -0
  3. package/dist/components/portfolio/SmallCheckout/SmallCheckout.d.ts +1 -1
  4. package/dist/constants/metadata.d.ts +2 -0
  5. package/dist/constants/sectionsConfig.d.ts +5 -0
  6. package/dist/index.d.ts +16 -1
  7. package/dist/models/HeaderType.d.ts +5 -0
  8. package/dist/models/Image.d.ts +5 -0
  9. package/dist/models/PageMetadata.d.ts +9 -0
  10. package/dist/models/PageProps.d.ts +21 -0
  11. package/dist/models/strapi/StrapiBlogPostProps.d.ts +6 -0
  12. package/dist/models/strapi/StrapiCustomerStoryProps.d.ts +6 -0
  13. package/dist/models/strapi/StrapiPageProps.d.ts +6 -0
  14. package/dist/models/strapi/StrapiProjectProps.d.ts +6 -0
  15. package/dist/slices/FullWidthImageSlider/styles.d.ts +1 -0
  16. package/dist/slices/TextCarousel/styles.d.ts +1 -0
  17. package/dist/strapi-slices.cjs.development.js +232 -11
  18. package/dist/strapi-slices.cjs.development.js.map +1 -1
  19. package/dist/strapi-slices.cjs.production.min.js +1 -1
  20. package/dist/strapi-slices.cjs.production.min.js.map +1 -1
  21. package/dist/strapi-slices.esm.js +224 -11
  22. package/dist/strapi-slices.esm.js.map +1 -1
  23. package/dist/test/mocks/getStaticPropsContext.d.ts +3 -0
  24. package/dist/utils/mergeGlobalAndStrapiBlogPostData.d.ts +5 -0
  25. package/dist/utils/mergeGlobalAndStrapiBlogPostData.test.d.ts +1 -0
  26. package/dist/utils/mergeGlobalAndStrapiCustomerStoryData.d.ts +4 -0
  27. package/dist/utils/mergeGlobalAndStrapiCustomerStoryData.test.d.ts +1 -0
  28. package/dist/utils/mergeGlobalAndStrapiPageData.d.ts +5 -0
  29. package/dist/utils/mergeGlobalAndStrapiPageData.test.d.ts +1 -0
  30. package/dist/utils/mergeGlobalAndStrapiProjectData.d.ts +5 -0
  31. package/dist/utils/mergeGlobalAndStrapiProjectData.test.d.ts +1 -0
  32. package/package.json +1 -2
  33. package/src/components/SEOTags/SEOTags.tsx +53 -0
  34. package/src/components/SEOTags/index.ts +1 -0
  35. package/src/components/portfolio/SmallCheckout/SmallCheckout.tsx +14 -15
  36. package/src/constants/metadata.ts +3 -0
  37. package/src/constants/sectionsConfig.ts +20 -0
  38. package/src/index.tsx +45 -0
  39. package/src/models/HeaderType.ts +6 -0
  40. package/src/models/Image.ts +6 -0
  41. package/src/models/PageMetadata.ts +11 -0
  42. package/src/models/PageProps.ts +32 -0
  43. package/src/models/strapi/StrapiBlogPostProps.ts +7 -0
  44. package/src/models/strapi/StrapiCustomerStoryProps.ts +9 -0
  45. package/src/models/strapi/StrapiPageProps.ts +7 -0
  46. package/src/models/strapi/StrapiProjectProps.ts +7 -0
  47. package/src/slices/ProjectFacts/ProjectFacts.stories.tsx +53 -0
  48. package/src/test/mocks/getStaticPropsContext.ts +9 -0
  49. package/src/utils/mergeGlobalAndStrapiBlogPostData.test.ts +154 -0
  50. package/src/utils/mergeGlobalAndStrapiBlogPostData.ts +68 -0
  51. package/src/utils/mergeGlobalAndStrapiCustomerStoryData.test.ts +149 -0
  52. package/src/utils/mergeGlobalAndStrapiCustomerStoryData.ts +68 -0
  53. package/src/utils/mergeGlobalAndStrapiPageData.test.ts +254 -0
  54. package/src/utils/mergeGlobalAndStrapiPageData.ts +81 -0
  55. package/src/utils/mergeGlobalAndStrapiProjectData.test.ts +243 -0
  56. package/src/utils/mergeGlobalAndStrapiProjectData.ts +79 -0
@@ -0,0 +1,3 @@
1
+ import { GetStaticPropsContext } from 'next';
2
+ declare const getStaticPropsContextMock: GetStaticPropsContext;
3
+ export default getStaticPropsContextMock;
@@ -0,0 +1,5 @@
1
+ import { GetStaticPropsContext } from 'next';
2
+ import { IStrapiData, StrapiBlogPost, StrapiBlogPostProps, StrapiGlobal } from '..';
3
+ import PortfolioProject from '../models/PortfolioProject';
4
+ declare const mergeGlobalAndStrapiBlogPostData: (context: GetStaticPropsContext, global: IStrapiData<StrapiGlobal>, post: IStrapiData<StrapiBlogPost>, blog: IStrapiData<StrapiBlogPost>[], projects: PortfolioProject[]) => StrapiBlogPostProps;
5
+ export default mergeGlobalAndStrapiBlogPostData;
@@ -0,0 +1,4 @@
1
+ import { GetStaticPropsContext } from 'next';
2
+ import { IStrapiData, StrapiCustomerStory, StrapiCustomerStoryProps, StrapiGlobal } from '..';
3
+ declare const mergeGlobalAndStrapiCustomerStoryData: (context: GetStaticPropsContext, global: IStrapiData<StrapiGlobal>, customerStory: IStrapiData<StrapiCustomerStory>, customerStories: IStrapiData<StrapiCustomerStory>[]) => StrapiCustomerStoryProps;
4
+ export default mergeGlobalAndStrapiCustomerStoryData;
@@ -0,0 +1,5 @@
1
+ import { GetStaticPropsContext } from 'next';
2
+ import { IStrapiData, StrapiBlogPost, StrapiCustomerStory, StrapiGlobal, StrapiPage, StrapiPageProps } from '..';
3
+ import PortfolioProject from '../models/PortfolioProject';
4
+ declare const mergeGlobalAndStrapiPageData: (context: GetStaticPropsContext, global: IStrapiData<StrapiGlobal>, page: IStrapiData<StrapiPage>, blogPosts: IStrapiData<StrapiBlogPost>[], customerStories: IStrapiData<StrapiCustomerStory>[], projects: PortfolioProject[]) => StrapiPageProps;
5
+ export default mergeGlobalAndStrapiPageData;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,5 @@
1
+ import { GetStaticPropsContext } from 'next';
2
+ import { IStrapiData, StrapiBlogPost, StrapiGlobal, StrapiProject, StrapiProjectProps } from '..';
3
+ import PortfolioProject from '../models/PortfolioProject';
4
+ declare const mergeGlobalAndStrapiProject: (context: GetStaticPropsContext, global: IStrapiData<StrapiGlobal>, project: IStrapiData<StrapiProject>, blogPosts: IStrapiData<StrapiBlogPost>[], projects: PortfolioProject[]) => StrapiProjectProps;
5
+ export default mergeGlobalAndStrapiProject;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@treely/strapi-slices",
3
- "version": "2.1.0",
3
+ "version": "2.2.1",
4
4
  "license": "MIT",
5
5
  "author": "Tree.ly GmbH",
6
6
  "description": "@treely/strapi-slices is a open source library maintained by Tree.ly.",
@@ -31,7 +31,6 @@
31
31
  "analyze": "size-limit --why",
32
32
  "build": "dts build",
33
33
  "lint": "dts lint",
34
- "prepare": "dts build",
35
34
  "size": "size-limit",
36
35
  "start": "dts watch",
37
36
  "test": "dts test --passWithNoTests",
@@ -0,0 +1,53 @@
1
+ import React from 'react';
2
+ import Head from 'next/head';
3
+ import {
4
+ DEFAULT_SHARE_ALT,
5
+ DEFAULT_SHARE_IMAGE,
6
+ } from '../../constants/metadata';
7
+
8
+ interface SEOTagsProps {
9
+ title: string;
10
+ description: string;
11
+ shareImage?: {
12
+ url: string;
13
+ alt: string;
14
+ };
15
+ metaTitleSuffix?: string;
16
+ favicon?: string;
17
+ domain?: string;
18
+ }
19
+
20
+ export const SEOTags: React.FC<SEOTagsProps> = ({
21
+ title,
22
+ description,
23
+ shareImage,
24
+ metaTitleSuffix = 'Tree.ly',
25
+ favicon = 'https://cdn.tree.ly/favicon.ico',
26
+ domain = 'tree.ly',
27
+ }: SEOTagsProps) => {
28
+ const shareImageUrl = shareImage?.url ?? DEFAULT_SHARE_IMAGE;
29
+ const shareImageAlt = shareImage?.alt ?? DEFAULT_SHARE_ALT;
30
+
31
+ return (
32
+ <Head>
33
+ <title>{`${title} - ${metaTitleSuffix}`}</title>
34
+ <meta name="description" content={description} />
35
+ <link rel="icon" href={favicon} />
36
+
37
+ <meta property="og:url" content={`https://${domain}`} />
38
+ <meta property="og:type" content="website" />
39
+ <meta property="og:title" content={title} />
40
+ <meta property="og:description" content={description} />
41
+ <meta property="og:image" content={shareImageUrl} />
42
+ <meta property="og:image:alt" content={shareImageAlt} />
43
+
44
+ <meta name="twitter:card" content="summary_large_image" />
45
+ <meta property="twitter:domain" content={domain} />
46
+ <meta property="twitter:url" content={`https://${domain}`} />
47
+ <meta name="twitter:title" content={title} />
48
+ <meta name="twitter:description" content={description} />
49
+ <meta name="twitter:image" content={shareImageUrl} />
50
+ <meta name="twitter:image:alt" content={shareImageAlt} />
51
+ </Head>
52
+ );
53
+ };
@@ -0,0 +1 @@
1
+ export { SEOTags } from './SEOTags';
@@ -1,6 +1,4 @@
1
- import React, { useContext, useCallback } from 'react';
2
- import { CDN_URI, FPM_API_URI } from '../../../constants/api';
3
- import StrapiLinkButton from '../../../components/StrapiLinkButton';
1
+ import React, { useCallback, useContext } from 'react';
4
2
  import {
5
3
  BoemlyFormControl,
6
4
  Box,
@@ -21,12 +19,14 @@ import {
21
19
  } from 'formik';
22
20
  import { useRouter } from 'next/router';
23
21
  import Image from 'next/image';
24
- import StrapiLink from '../../../models/strapi/StrapiLink';
22
+ import { StrapiLink } from '../../..';
23
+ import { IntlContext } from '../../ContextProvider';
25
24
  import {
26
25
  MAXIMUM_CONTRIBUTION_VALUE_IN_MONEY,
27
26
  MINIMUM_CONTRIBUTION_VALUE_IN_MONEY,
28
27
  } from '../../../constants/domain';
29
- import { IntlContext } from '../../ContextProvider';
28
+ import { CDN_URI, FPM_API_URI } from '../../../constants/api';
29
+ import StrapiLinkButton from '../../StrapiLinkButton';
30
30
 
31
31
  export interface SmallCheckoutProps {
32
32
  batchId: string;
@@ -85,13 +85,12 @@ const SmallCheckout = ({
85
85
  [locale]
86
86
  );
87
87
 
88
- const onSubmit = async ({ contributionValueCurrency }: SmallCheckoutForm) => {
88
+ const onSubmit = async ({ contributionValueCurrency }: SmallCheckoutForm) =>
89
89
  push(
90
90
  `${FPM_API_URI}/v1/webhooks/shop/checkout?batchId=${batchId}&quantity=${Math.floor(
91
91
  contributionValueCurrency / pricePerKg
92
92
  )}`
93
93
  );
94
- };
95
94
 
96
95
  return (
97
96
  <Flex
@@ -143,12 +142,12 @@ const SmallCheckout = ({
143
142
  <BoemlyFormControl
144
143
  id="contributionValueCurrency"
145
144
  size="md"
146
- inputType="NumberInput"
147
- numberInputProps={{
145
+ inputProps={{
146
+ type: 'number',
148
147
  value: field.value,
149
- onChange: (valueString) => {
148
+ onChange: (e) => {
150
149
  // valueAsNumber might be NaN
151
- const value = parseInt(valueString || '0', 10);
150
+ const value = e.target.valueAsNumber || 0;
152
151
 
153
152
  setValues({
154
153
  contributionValueCurrency: value,
@@ -182,11 +181,11 @@ const SmallCheckout = ({
182
181
  <BoemlyFormControl
183
182
  id="contributionValueKgs"
184
183
  size="md"
185
- inputType="NumberInput"
186
- numberInputProps={{
184
+ inputProps={{
185
+ type: 'number',
187
186
  value: field.value,
188
- onChange: (valueString) => {
189
- const value = parseInt(valueString || '0', 10);
187
+ onChange: (e) => {
188
+ const value = e.target.valueAsNumber || 0;
190
189
 
191
190
  setValues({
192
191
  contributionValueCurrency:
@@ -0,0 +1,3 @@
1
+ export const DEFAULT_SHARE_IMAGE =
2
+ 'https://cdn.tree.ly/assets/v3/app/share-image-generic.webp';
3
+ export const DEFAULT_SHARE_ALT = 'Share Image';
@@ -0,0 +1,20 @@
1
+ export const EXTENDABLE_HEADER_SECTIONS = [
2
+ 'sections.hero',
3
+ 'sections.map-hero',
4
+ 'sections.full-width-image',
5
+ 'sections.small-hero',
6
+ 'sections.small-hero-light',
7
+ ];
8
+ export const DARK_THEME_HEADER_SECTIONS = [
9
+ 'sections.hero',
10
+ 'sections.small-hero',
11
+ ];
12
+ export const SECTIONS_WITH_BLOG_POSTS = [
13
+ 'sections.blog',
14
+ 'sections.blog-cards',
15
+ ];
16
+ export const SECTIONS_WITH_CUSTOMER_STORIES = ['sections.customer-stories'];
17
+ export const SECTIONS_WITH_PROJECTS = [
18
+ 'sections.projects-map',
19
+ 'sections.project-facts',
20
+ ];
package/src/index.tsx CHANGED
@@ -5,10 +5,12 @@ import StrapiAuthor from './models/strapi/StrapiAuthor';
5
5
  import StrapiAvatarWithName from './models/strapi/StrapiAvatarWithName';
6
6
  import StrapiBanner from './models/strapi/StrapiBanner';
7
7
  import StrapiBlogPost from './models/strapi/StrapiBlogPost';
8
+ import StrapiBlogPostProps from './models/strapi/StrapiBlogPostProps';
8
9
  import StrapiButtonWithVariant from './models/strapi/StrapiButtonWithVariant';
9
10
  import StrapiCategory from './models/strapi/StrapiCategory';
10
11
  import StrapiContactArea from './models/strapi/StrapiContactArea';
11
12
  import StrapiCustomerStory from './models/strapi/StrapiCustomerStory';
13
+ import StrapiCustomerStoryProps from './models/strapi/StrapiCustomerStoryProps';
12
14
  import StrapiDefaultHeader from './models/strapi/StrapiDefaultHeader';
13
15
  import StrapiGlobal from './models/strapi/StrapiGlobal';
14
16
  import StrapiGlossaryItem from './models/strapi/StrapiGlossaryItem';
@@ -25,18 +27,51 @@ import StrapiMedia from './models/strapi/StrapiMedia';
25
27
  import StrapiMetadata from './models/strapi/StrapiMetadata';
26
28
  import StrapiNavMenu from './models/strapi/StrapiNavMenu';
27
29
  import StrapiPage from './models/strapi/StrapiPage';
30
+ import StrapiPageProps from './models/strapi/StrapiPageProps';
28
31
  import StrapiPortfolio from './models/strapi/StrapiPortfolio';
29
32
  import StrapiPortfolioCard from './models/strapi/StrapiPortfolioCard';
30
33
  import StrapiProject from './models/strapi/StrapiProject';
34
+ import StrapiProjectProps from './models/strapi/StrapiProjectProps';
31
35
  import StrapiProjectCard from './models/strapi/StrapiProjectCard';
32
36
  import StrapiQuoteCard from './models/strapi/StrapiQuoteCard';
33
37
  import StrapiShapesCard from './models/strapi/StrapiShapesCard';
34
38
  import StrapiTextCardWithIcons from './models/strapi/StrapiTextCardWithIcons';
35
39
  import StrapiTopBanner from './models/strapi/StrapiTopBanner';
36
40
 
41
+ import HeaderType from './models/HeaderType';
42
+ import Image from './models/Image';
43
+ import PageMetadata from './models/PageMetadata';
44
+ import PageProps from './models/PageProps';
45
+
46
+ import mergeGlobalAndStrapiBlogPostData from './utils/mergeGlobalAndStrapiBlogPostData';
47
+ import mergeGlobalAndStrapiCustomerStoryData from './utils/mergeGlobalAndStrapiCustomerStoryData';
48
+ import mergeGlobalAndStrapiPageData from './utils/mergeGlobalAndStrapiPageData';
49
+ import mergeGlobalAndStrapiProjectData from './utils/mergeGlobalAndStrapiProjectData';
50
+
51
+ import {
52
+ SECTIONS_WITH_BLOG_POSTS,
53
+ SECTIONS_WITH_CUSTOMER_STORIES,
54
+ SECTIONS_WITH_PROJECTS,
55
+ } from './constants/sectionsConfig';
56
+
57
+ export * from './components/SEOTags';
37
58
  export * from './components/SliceRenderer';
38
59
 
60
+ export {
61
+ // Utils
62
+ mergeGlobalAndStrapiBlogPostData,
63
+ mergeGlobalAndStrapiCustomerStoryData,
64
+ mergeGlobalAndStrapiPageData,
65
+ mergeGlobalAndStrapiProjectData,
66
+
67
+ // Constants
68
+ SECTIONS_WITH_BLOG_POSTS,
69
+ SECTIONS_WITH_CUSTOMER_STORIES,
70
+ SECTIONS_WITH_PROJECTS,
71
+ };
72
+
39
73
  export type {
74
+ // Strapi Models
40
75
  IStrapi,
41
76
  IStrapiData,
42
77
  IStrapiResponse,
@@ -44,10 +79,12 @@ export type {
44
79
  StrapiAvatarWithName,
45
80
  StrapiBanner,
46
81
  StrapiBlogPost,
82
+ StrapiBlogPostProps,
47
83
  StrapiButtonWithVariant,
48
84
  StrapiCategory,
49
85
  StrapiContactArea,
50
86
  StrapiCustomerStory,
87
+ StrapiCustomerStoryProps,
51
88
  StrapiDefaultHeader,
52
89
  StrapiGlobal,
53
90
  StrapiGlossaryItem,
@@ -64,12 +101,20 @@ export type {
64
101
  StrapiMetadata,
65
102
  StrapiNavMenu,
66
103
  StrapiPage,
104
+ StrapiPageProps,
67
105
  StrapiPortfolio,
68
106
  StrapiPortfolioCard,
69
107
  StrapiProject,
108
+ StrapiProjectProps,
70
109
  StrapiProjectCard,
71
110
  StrapiQuoteCard,
72
111
  StrapiShapesCard,
73
112
  StrapiTextCardWithIcons,
74
113
  StrapiTopBanner,
114
+
115
+ // Models
116
+ HeaderType,
117
+ Image,
118
+ PageMetadata,
119
+ PageProps,
75
120
  };
@@ -0,0 +1,6 @@
1
+ interface HeaderType {
2
+ extendable: boolean;
3
+ theme: 'dark' | 'light';
4
+ }
5
+
6
+ export default HeaderType;
@@ -0,0 +1,6 @@
1
+ interface Image {
2
+ url: string;
3
+ alt: string;
4
+ }
5
+
6
+ export default Image;
@@ -0,0 +1,11 @@
1
+ import Image from './Image';
2
+
3
+ interface PageMetadata {
4
+ title: string;
5
+ description: string;
6
+ shareImage?: Image;
7
+ metaTitleSuffix?: string;
8
+ favicon?: string;
9
+ }
10
+
11
+ export default PageMetadata;
@@ -0,0 +1,32 @@
1
+ import {
2
+ IStrapiData,
3
+ StrapiBanner,
4
+ StrapiBlogPost,
5
+ StrapiCustomerStory,
6
+ StrapiLink,
7
+ StrapiLinkList,
8
+ StrapiNavMenu,
9
+ StrapiTopBanner,
10
+ } from '..';
11
+ import { ReactNode } from 'react';
12
+ import PortfolioProject from './PortfolioProject';
13
+ import PageMetadata from './PageMetadata';
14
+ import HeaderType from './HeaderType';
15
+
16
+ interface PageProps {
17
+ headerType?: HeaderType;
18
+ headerNavMenus?: StrapiNavMenu[];
19
+ headerButtons?: StrapiLink[];
20
+ footerLinks?: StrapiLinkList[];
21
+ hideFooter?: boolean;
22
+ children?: ReactNode;
23
+ metadata: PageMetadata;
24
+ slices: any[];
25
+ blogPosts: IStrapiData<StrapiBlogPost>[];
26
+ projects: PortfolioProject[];
27
+ banner?: StrapiBanner;
28
+ topBanner?: StrapiTopBanner;
29
+ customerStories: IStrapiData<StrapiCustomerStory>[];
30
+ }
31
+
32
+ export default PageProps;
@@ -0,0 +1,7 @@
1
+ import PageProps from '../PageProps';
2
+ import IStrapiData from './IStrapiData';
3
+ import StrapiBlogPost from './StrapiBlogPost';
4
+
5
+ interface StrapiBlogPostProps extends PageProps, IStrapiData<StrapiBlogPost> {}
6
+
7
+ export default StrapiBlogPostProps;
@@ -0,0 +1,9 @@
1
+ import PageProps from '../PageProps';
2
+ import IStrapiData from './IStrapiData';
3
+ import StrapiCustomerStory from './StrapiCustomerStory';
4
+
5
+ interface StrapiCustomerStoryProps
6
+ extends PageProps,
7
+ IStrapiData<StrapiCustomerStory> {}
8
+
9
+ export default StrapiCustomerStoryProps;
@@ -0,0 +1,7 @@
1
+ import PageProps from '../PageProps';
2
+ import IStrapiData from './IStrapiData';
3
+ import StrapiPage from './StrapiPage';
4
+
5
+ interface StrapiPageProps extends PageProps, IStrapiData<StrapiPage> {}
6
+
7
+ export default StrapiPageProps;
@@ -0,0 +1,7 @@
1
+ import PageProps from '../PageProps';
2
+ import IStrapiData from './IStrapiData';
3
+ import StrapiProject from './StrapiProject';
4
+
5
+ interface StrapiProjectProps extends PageProps, IStrapiData<StrapiProject> {}
6
+
7
+ export default StrapiProjectProps;
@@ -2,6 +2,7 @@ import React from 'react';
2
2
  import { StoryFn, Meta } from '@storybook/react';
3
3
 
4
4
  import fpmProjectMock from '../../test/integrationMocks/fpmProjectMock';
5
+ import { storybookStrapiAvatarMock } from '../../test/storybookMocks/storybookStrapiMedia';
5
6
  import CreditsAvailableState from '../../models/CreditsAvailableState';
6
7
  import ProjectFacts from '.';
7
8
 
@@ -90,3 +91,55 @@ FullProps.args = {
90
91
  },
91
92
  },
92
93
  };
94
+
95
+ export const WithContact = Template.bind({});
96
+ WithContact.args = {
97
+ project: fpmProjectMock,
98
+ slice: {
99
+ projectId: fpmProjectMock.id,
100
+
101
+ contactTitle: 'Contact Title',
102
+ contactText: 'Contact Text',
103
+ contactButton: {
104
+ id: 1,
105
+ text: 'Contact our Sales Team',
106
+ url: 'https://example.org',
107
+ },
108
+ contactAvatar: {
109
+ id: 1,
110
+ alt: 'Avatar image alt text',
111
+ img: {
112
+ data: storybookStrapiAvatarMock,
113
+ },
114
+ },
115
+ },
116
+ };
117
+
118
+ export const WithDocumentsAndContact = Template.bind({});
119
+ WithDocumentsAndContact.args = {
120
+ project: fpmProjectMock,
121
+ slice: {
122
+ projectId: fpmProjectMock.id,
123
+
124
+ documentUrls: [
125
+ { id: 1, text: 'Document 1', url: 'https://example.org' },
126
+ { id: 2, text: 'Document 2', url: 'https://example.org' },
127
+ { id: 3, text: 'Document 3', url: 'https://example.org' },
128
+ ],
129
+
130
+ contactTitle: 'Contact Title',
131
+ contactText: 'Contact Text',
132
+ contactButton: {
133
+ id: 1,
134
+ text: 'Contact our Sales Team',
135
+ url: 'https://example.org',
136
+ },
137
+ contactAvatar: {
138
+ id: 1,
139
+ alt: 'Avatar image alt text',
140
+ img: {
141
+ data: storybookStrapiAvatarMock,
142
+ },
143
+ },
144
+ },
145
+ };
@@ -0,0 +1,9 @@
1
+ import { GetStaticPropsContext } from 'next';
2
+
3
+ const getStaticPropsContextMock: GetStaticPropsContext = {
4
+ locales: ['en', 'de'],
5
+ locale: 'en',
6
+ defaultLocale: 'en',
7
+ };
8
+
9
+ export default getStaticPropsContextMock;
@@ -0,0 +1,154 @@
1
+ import mergeGlobalAndStrapiBlogPostData from './mergeGlobalAndStrapiBlogPostData';
2
+ import { strapiBlogPostMock } from '../test/strapiMocks/strapiBlogPost';
3
+ import minimalGlobalData from '../test/strapiMocks/minimalGlobalData';
4
+ import getStaticPropsContextMock from '../test/mocks/getStaticPropsContext';
5
+ import { strapiMetadataMock } from '../test/strapiMocks/strapiMetadata';
6
+
7
+ describe('The mergeGlobalAndStrapiBlogPostData util', () => {
8
+ it('returns the global metadata if there is no page metadata', () => {
9
+ const pageDataWithoutMetadata = {
10
+ ...strapiBlogPostMock,
11
+ attributes: {
12
+ ...strapiBlogPostMock.attributes,
13
+ metadata: null,
14
+ },
15
+ };
16
+
17
+ const result = mergeGlobalAndStrapiBlogPostData(
18
+ getStaticPropsContextMock,
19
+ minimalGlobalData,
20
+ pageDataWithoutMetadata,
21
+ [],
22
+ []
23
+ );
24
+
25
+ expect(result.attributes.metadata).toBe(
26
+ minimalGlobalData.attributes.metadata
27
+ );
28
+ expect(result.metadata.title).toBe(
29
+ minimalGlobalData.attributes.metadata.title
30
+ );
31
+ expect(result.metadata.description).toBe(
32
+ minimalGlobalData.attributes.metadata.description
33
+ );
34
+ });
35
+
36
+ it('returns the pages metadata if the page data includes metadata', () => {
37
+ const pageDataWithMetadata = {
38
+ ...strapiBlogPostMock,
39
+ data: {
40
+ ...strapiBlogPostMock,
41
+ attributes: {
42
+ ...strapiBlogPostMock.attributes,
43
+ metadata: strapiMetadataMock,
44
+ },
45
+ },
46
+ };
47
+
48
+ const result = mergeGlobalAndStrapiBlogPostData(
49
+ getStaticPropsContextMock,
50
+ minimalGlobalData,
51
+ pageDataWithMetadata,
52
+ [],
53
+ []
54
+ );
55
+
56
+ expect(result.attributes.metadata?.title).toBe(strapiMetadataMock.title);
57
+ expect(result.metadata?.title).toBe(strapiMetadataMock.title);
58
+ });
59
+
60
+ it('returns the navbar links if there are links in the global data', () => {
61
+ const result = mergeGlobalAndStrapiBlogPostData(
62
+ getStaticPropsContextMock,
63
+ {
64
+ ...minimalGlobalData,
65
+ attributes: {
66
+ ...minimalGlobalData.attributes,
67
+ navbar: {
68
+ ...minimalGlobalData.attributes.navbar,
69
+ navMenus: [
70
+ {
71
+ link: {
72
+ id: Infinity,
73
+ text: 'Text',
74
+ url: '/',
75
+ },
76
+ title: 'Title',
77
+ items: [],
78
+ },
79
+ ],
80
+ },
81
+ },
82
+ },
83
+ strapiBlogPostMock,
84
+ [],
85
+ []
86
+ );
87
+
88
+ expect(result.headerNavMenus).toStrictEqual([
89
+ {
90
+ title: 'Title',
91
+ items: [],
92
+ link: { id: Infinity, text: 'Text', url: '/' },
93
+ },
94
+ ]);
95
+ });
96
+
97
+ it('returns the navbar buttons if there are buttons in the global data', () => {
98
+ const result = mergeGlobalAndStrapiBlogPostData(
99
+ getStaticPropsContextMock,
100
+ {
101
+ ...minimalGlobalData,
102
+ attributes: {
103
+ ...minimalGlobalData.attributes,
104
+ navbar: {
105
+ ...minimalGlobalData.attributes.navbar,
106
+ buttons: [
107
+ {
108
+ id: Infinity,
109
+ text: 'Header button',
110
+ url: '/',
111
+ },
112
+ ],
113
+ },
114
+ },
115
+ },
116
+ strapiBlogPostMock,
117
+ [],
118
+ []
119
+ );
120
+
121
+ expect(result.headerButtons).toStrictEqual([
122
+ { id: Infinity, text: 'Header button', url: '/' },
123
+ ]);
124
+ });
125
+
126
+ it('returns the footer links if there are links in the global data', () => {
127
+ const result = mergeGlobalAndStrapiBlogPostData(
128
+ getStaticPropsContextMock,
129
+ {
130
+ ...minimalGlobalData,
131
+ attributes: {
132
+ ...minimalGlobalData.attributes,
133
+ footer: {
134
+ ...minimalGlobalData.attributes.footer,
135
+ links: [
136
+ {
137
+ id: Infinity,
138
+ title: 'Title',
139
+ links: [],
140
+ },
141
+ ],
142
+ },
143
+ },
144
+ },
145
+ strapiBlogPostMock,
146
+ [],
147
+ []
148
+ );
149
+
150
+ expect(result.footerLinks).toStrictEqual([
151
+ { id: Infinity, title: 'Title', links: [] },
152
+ ]);
153
+ });
154
+ });