gatsby-core-theme 3.0.0 → 5.0.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 (85) hide show
  1. package/CHANGELOG.md +116 -0
  2. package/__mocks__/gatsby.js +16 -4
  3. package/gatsby-node.esm.js +7 -1
  4. package/jest.config.js +8 -1
  5. package/package.json +1 -1
  6. package/src/components/app.js +1 -17
  7. package/src/components/atoms/author/author.test.js +12 -5
  8. package/src/components/atoms/author-box/index.js +10 -11
  9. package/src/components/atoms/breadcrumbs/breadcrumbs.test.js +8 -0
  10. package/src/components/atoms/carousel/pagination-item/pagination-item.test.js +18 -3
  11. package/src/components/atoms/collapse/collapse.test.js +10 -0
  12. package/src/components/atoms/collapse/index.js +3 -1
  13. package/src/components/atoms/content-box/content-box.test.js +9 -6
  14. package/src/components/atoms/content-box/index.js +13 -12
  15. package/src/components/atoms/custom-select/index.js +31 -30
  16. package/src/components/atoms/disclaimer/disclaimer.test.js +16 -1
  17. package/src/components/atoms/iframe/iframe.module.scss +3 -0
  18. package/src/components/atoms/iframe/iframe.test.js +6 -0
  19. package/src/components/atoms/image/image.test.js +19 -6
  20. package/src/components/atoms/image/index.js +2 -4
  21. package/src/components/atoms/info-grid/index.js +10 -12
  22. package/src/components/atoms/label/index.js +2 -2
  23. package/src/components/atoms/label/label.test.js +4 -0
  24. package/src/components/atoms/module-title/index.js +9 -9
  25. package/src/components/atoms/module-title/module-title.test.js +76 -0
  26. package/src/components/atoms/open-graph/open-graph.test.js +34 -5
  27. package/src/components/atoms/operator-cta/operator-cta.test.js +26 -3
  28. package/src/components/atoms/scroll-to-top/scroll-to-top.test.js +6 -0
  29. package/src/components/atoms/search/autocomplete/operator.js +1 -1
  30. package/src/components/atoms/sitemap/index.js +1 -1
  31. package/src/components/atoms/spotlights/index.js +59 -54
  32. package/src/components/atoms/spotlights/spotlights.module.scss +25 -37
  33. package/src/components/atoms/spotlights/spotlights.test.js +13 -15
  34. package/src/components/molecules/carousel/default-slide/index.js +3 -1
  35. package/src/components/molecules/content/content.test.js +127 -0
  36. package/src/components/molecules/content/index.js +0 -1
  37. package/src/components/molecules/header/header.test.js +6 -0
  38. package/src/components/molecules/main/main.test.js +48 -12
  39. package/src/components/molecules/menu/menu.test.js +27 -0
  40. package/src/components/molecules/module/module.test.js +134 -0
  41. package/src/components/molecules/operator-banner/operator-banner.test.js +7 -1
  42. package/src/components/molecules/pagination/pagination-with-midpoints.module.scss +48 -49
  43. package/src/components/molecules/slider/index.js +6 -0
  44. package/src/components/organisms/anchor/index.js +14 -11
  45. package/src/components/organisms/carousel/index.js +16 -3
  46. package/src/components/organisms/cookie-consent/cookie-consent.test.js +7 -1
  47. package/src/components/organisms/form/form.test.js +21 -0
  48. package/src/components/organisms/form/index.js +5 -1
  49. package/src/components/organisms/navigation/index.js +9 -1
  50. package/src/components/organisms/search/index.js +0 -1
  51. package/src/components/organisms/toplist/list/index.js +1 -1
  52. package/src/components/organisms/toplist/list/list.test.js +30 -0
  53. package/src/components/pages/body/index.js +4 -6
  54. package/src/components/pages/tracker/index.js +1 -1
  55. package/src/constants/settings.js +1 -1
  56. package/src/helpers/getters.js +10 -6
  57. package/src/helpers/getters.test.js +1 -3
  58. package/src/helpers/processor/common.test.js +7 -1
  59. package/src/helpers/processor/index.js +2 -3
  60. package/src/helpers/processor/index.test.js +21 -0
  61. package/src/helpers/schema.js +14 -6
  62. package/src/helpers/schema.test.js +17 -14
  63. package/src/hooks/gatsby-img/index.js +1 -1
  64. package/src/hooks/lazy-image/index.js +37 -37
  65. package/src/hooks/lazy-image/lazy-image.test.js +39 -0
  66. package/src/hooks/lazy-picture/index.js +1 -1
  67. package/src/hooks/link/link.test.js +42 -1
  68. package/src/hooks/tabs/tab/tab.test.js +41 -0
  69. package/src/styles/utils/variables/_main.scss +3 -1
  70. package/tests/envVars.js +1 -1
  71. package/tests/factories/modules/content.factory.js +6 -3
  72. package/tests/factories/modules/modules.factory.js +152 -0
  73. package/tests/factories/modules/schema.factory.js +87 -0
  74. package/tests/factories/pages/list.factory.js +2 -1
  75. package/tests/factories/pages/pages.factory.js +192 -0
  76. package/tests/factories/sections/header.factory.js +8 -2
  77. package/src/components/atoms/logo/index.js +0 -36
  78. package/src/components/atoms/logo/logo.module.scss +0 -4
  79. package/src/components/atoms/logo/logo.stories.js +0 -57
  80. package/src/components/atoms/logo/logo.test.js +0 -30
  81. package/src/components/molecules/section/index.js +0 -24
  82. package/src/components/molecules/section/section.test.js +0 -16
  83. package/src/components/molecules/sidebar/index.js +0 -25
  84. package/src/components/molecules/sidebar/sidebar.module.scss +0 -3
  85. package/src/components/molecules/sidebar/sidebar.test.js +0 -30
@@ -1,4 +1,5 @@
1
1
  import React from 'react';
2
+ import { navigate } from 'gatsby';
2
3
  import { render, cleanup, fireEvent } from '@testing-library/react';
3
4
  import '@testing-library/jest-dom/extend-expect';
4
5
 
@@ -21,12 +22,17 @@ const setUp = () => {
21
22
  return { container, getByText };
22
23
  };
23
24
  describe('cookie consent component', () => {
24
- test('Children', () => {
25
+ test('Children and declineButton', () => {
25
26
  const { container, getByText } = setUp();
27
+
26
28
  expect(container.querySelectorAll('div.cookieConsent')).toHaveLength(1);
29
+
27
30
  expect(container.querySelectorAll('p')).toHaveLength(1);
28
31
  expect(container.querySelectorAll('b')).toHaveLength(1);
29
32
  expect(getByText('cookie test')).toBeTruthy();
33
+ const declineButton = getByText('Decline Me');
34
+ fireEvent.click(declineButton);
35
+ expect(navigate).toHaveBeenCalled();
30
36
  });
31
37
  test('Buttons', () => {
32
38
  const { container, getByText } = setUp();
@@ -29,10 +29,13 @@ describe('Form Component', () => {
29
29
  test('on change', async () => {
30
30
  render(<Form hasButton type="contact" submitUrl="https://submit-form.com" />);
31
31
  const input = document.querySelector('input[type="text"]');
32
+ const messageInput = document.querySelector('textarea');
32
33
 
33
34
  await waitFor(() => {
34
35
  fireEvent.change(input, { target: { value: 'Mohsen' } });
36
+ fireEvent.change(messageInput, { target: { value: 'EKKK' } });
35
37
  expect(input.value).toBe('Mohsen');
38
+ expect(messageInput.value).toBe('EKKK');
36
39
  }, 3000);
37
40
  });
38
41
 
@@ -52,6 +55,24 @@ describe('Form Component', () => {
52
55
  });
53
56
  expect(ApiCall).toHaveBeenCalled();
54
57
  });
58
+
59
+ test('handle submit with filled fields', async () => {
60
+ const { container } = render(
61
+ <Form hasButton disabled={false} type="newsletter" submitUrl="https://submit-form.com" />
62
+ );
63
+ const nameInput = document.querySelector('input[type="text"]');
64
+ const emailInput = document.querySelector('input[type="email"]');
65
+
66
+ await waitFor(() => {
67
+ fireEvent.change(nameInput, { target: { value: 'Val' } });
68
+ fireEvent.change(emailInput, { target: { value: 'ejk@sl.com' } });
69
+
70
+ expect(nameInput.value).toBe('Val');
71
+ }, 3000);
72
+
73
+ const formElement = container.querySelector('form');
74
+ fireEvent.submit(formElement);
75
+ });
55
76
  });
56
77
  afterEach(() => {
57
78
  cleanup();
@@ -12,6 +12,7 @@ const FormComponent = ({
12
12
  submitUrl = '',
13
13
  hasButton = true,
14
14
  buttonLabel = 'Submit',
15
+ disabled = true,
15
16
  }) => {
16
17
  const recaptchaRef = useRef();
17
18
  const [state, setState] = useState({
@@ -19,7 +20,7 @@ const FormComponent = ({
19
20
  success: false,
20
21
  failed: false,
21
22
  isValid: true,
22
- isDisabled: true,
23
+ isDisabled: disabled,
23
24
  name: '',
24
25
  email: '',
25
26
  message: '',
@@ -43,7 +44,9 @@ const FormComponent = ({
43
44
  }
44
45
  const handleSubmit = (e) => {
45
46
  e.preventDefault();
47
+
46
48
  const { name, email, message, isDisabled } = state;
49
+
47
50
  if (
48
51
  name === '' ||
49
52
  email === '' ||
@@ -171,5 +174,6 @@ FormComponent.propTypes = {
171
174
  submitUrl: PropTypes.string.isRequired,
172
175
  hasButton: PropTypes.bool,
173
176
  buttonLabel: PropTypes.string,
177
+ disabled: PropTypes.bool,
174
178
  };
175
179
  export default FormComponent;
@@ -33,6 +33,7 @@ const Navigation = ({
33
33
  },
34
34
  sticky = true,
35
35
  template,
36
+ children,
36
37
  customStyles,
37
38
  }) => {
38
39
  const navRef = useRef(React.createRef());
@@ -69,7 +70,12 @@ const Navigation = ({
69
70
  to="/"
70
71
  onClick={onClickHandler}
71
72
  >
72
- <img alt="logo" src={logo} width={logoWidth} height={logoHeight} />
73
+ <img
74
+ alt={process.env.GATSBY_SITE_NAME}
75
+ src={logo}
76
+ width={logoWidth}
77
+ height={logoHeight}
78
+ />
73
79
  </Link>
74
80
  {showMenu && (
75
81
  <>
@@ -85,6 +91,7 @@ const Navigation = ({
85
91
  )}
86
92
  </NavigationProvider>
87
93
  </nav>
94
+ {children}
88
95
  </ConditionalWrapper>
89
96
  );
90
97
  };
@@ -110,6 +117,7 @@ Navigation.propTypes = {
110
117
  searchIcon: PropTypes.string,
111
118
  hasSearch: PropTypes.bool,
112
119
  menu: PropTypes.string,
120
+ children: PropTypes.node,
113
121
  options: PropTypes.shape({
114
122
  mobile: PropTypes.shape({
115
123
  animation: PropTypes.string,
@@ -11,7 +11,6 @@ import styles from './search.module.scss';
11
11
 
12
12
  const SearchForm = ({ className, searchIcon, iconWidth = 24, iconHeight = 24 }) => {
13
13
  const { showSearch, setShowSearch, setShowMenu, showMenu } = useContext(NavigationContext);
14
-
15
14
  const Search = showSearch ? loadable(() => import('~molecules/search')) : <></>;
16
15
  const Operator = showSearch ? (
17
16
  loadable(() => import('~atoms/search/autocomplete/operator'))
@@ -88,7 +88,7 @@ List.propTypes = {
88
88
  one_liner: PropTypes.string,
89
89
  }),
90
90
  CustomRow: PropTypes.func,
91
- hasLoadMoreButton: PropTypes.bool,
91
+ hasLoadMoreButton: PropTypes.string,
92
92
  initItemsCount: PropTypes.string,
93
93
  loadItemsCount: PropTypes.string,
94
94
  pageTemplate: PropTypes.string,
@@ -0,0 +1,30 @@
1
+ import React from 'react';
2
+ import { render, cleanup, fireEvent } from '@testing-library/react';
3
+ import '@testing-library/jest-dom/extend-expect';
4
+ import { getListToplistItem } from '~tests/factories/modules/toplist.factory';
5
+
6
+ import List from '.';
7
+
8
+ describe('List', () => {
9
+ test('render list with Load more', () => {
10
+ const { container, getByText } = render(
11
+ <List
12
+ toplist={{ items: getListToplistItem(15) }}
13
+ loadItemsCount="5"
14
+ initItemsCount="5"
15
+ hasLoadMoreButton="1"
16
+ />
17
+ );
18
+ expect(getByText('Load More')).toBeTruthy();
19
+ const button = container.querySelector('button');
20
+ fireEvent.click(button);
21
+ });
22
+
23
+ test('render list without Load more', () => {
24
+ const { container } = render(<List toplist={{ items: getListToplistItem(5) }} />);
25
+ expect(container.querySelector('button')).toBeFalsy();
26
+ });
27
+ });
28
+ afterEach(() => {
29
+ cleanup();
30
+ });
@@ -1,7 +1,7 @@
1
+ /* eslint-disable no-useless-concat */
1
2
  /* eslint-disable no-restricted-globals */
2
3
  import React, { useEffect } from 'react';
3
4
  import PropTypes from 'prop-types';
4
- import loadable from '@loadable/component';
5
5
  import { getSection } from '~helpers/getters';
6
6
  import Header from '~molecules/header';
7
7
  import Main from '~molecules/main';
@@ -18,7 +18,6 @@ function Body({ pageContext, children }) {
18
18
  const main = getBodySection('main');
19
19
  const navigation = getBodySection('navigation');
20
20
  const footer = getBodySection('footer');
21
- const sidebar = getBodySection('sidebar');
22
21
 
23
22
  useEffect(() => {
24
23
  if (!process.env.CANARY_TOKEN) {
@@ -26,8 +25,9 @@ function Body({ pageContext, children }) {
26
25
  }
27
26
 
28
27
  if (
29
- !document.domain.includes(process.env.GATSBY_SITE_NAME) ||
30
- !document.domain.includes(`www.${process.env.GATSBY_SITE_NAME}`)
28
+ document.domain !== `prelive.${process.env.GATSBY_SITE_NAME}` ||
29
+ document.domain !== process.env.GATSBY_SITE_NAME ||
30
+ document.domain !== `www.${process.env.GATSBY_SITE_NAME}`
31
31
  ) {
32
32
  const l = location.href;
33
33
  const r = document.referrer;
@@ -38,14 +38,12 @@ function Body({ pageContext, children }) {
38
38
  }
39
39
  }, []);
40
40
 
41
- const Sidebar = sidebar ? loadable(() => import(`~molecules/sidebar`)) : null;
42
41
  return (
43
42
  <>
44
43
  {navigation && <Navigation template={template} section={navigation} />}
45
44
  {!is404 && <Header section={pageContext} />}
46
45
  {main && !children && <Main section={main} pageContext={pageContext} />}
47
46
  {children && <main>{children}</main>}
48
- {Sidebar && <Sidebar section={sidebar} />}
49
47
  <ScrollToTop />
50
48
  <Footer template={template} section={footer} />
51
49
  <CookieConsent />
@@ -83,7 +83,7 @@ const Tracker = ({
83
83
  </video>
84
84
  );
85
85
  } else if (bgImage) {
86
- background = <LazyImage className={styles.background} src={bgImage} />;
86
+ background = <LazyImage className={styles.background} src={bgImage} alt="background image" />;
87
87
  }
88
88
 
89
89
  return (
@@ -6,8 +6,8 @@ export default {
6
6
  },
7
7
  keep_page_extra_fields: {
8
8
  operator: {
9
- 'Irishluck.ie': true, // needed for card background image
10
9
  'norskespilleautomater.com': true, // needed for inoperative / placeholder fields
10
+ 'Irishluck.ie': true, // needed for card background image
11
11
  'playcasino.co.za': true,
12
12
  },
13
13
  article: {
@@ -90,6 +90,15 @@ export function image(filename, width, height, fit = 'cover') {
90
90
  return `${cloudFrontUrl}/${Buffer.from(imageRequest).toString('base64')}`;
91
91
  }
92
92
 
93
+ export function getImageFilename(src) {
94
+ const srcArr = src?.substring(src?.lastIndexOf('/') + 1)?.split('.');
95
+ if (!srcArr.length) {
96
+ return '';
97
+ }
98
+
99
+ return srcArr[0];
100
+ }
101
+
93
102
  export function getImageExtension(filename) {
94
103
  return filename && filename.split('.').pop();
95
104
  }
@@ -126,12 +135,7 @@ export function getPageImage(page) {
126
135
  return page.relation.thumbnail_filename;
127
136
  }
128
137
  }
129
- if (page.type === 'article') {
130
- if (page.banner) {
131
- return imagePrettyUrl(page.banner);
132
- }
133
- }
134
- if (['operator', 'software_provider'].includes(page.type) && page.relation.logo) {
138
+ if (page.type === 'software_provider' && page.relation.logo) {
135
139
  return imagePrettyUrl(page.relation.logo);
136
140
  }
137
141
  if (page.banner) {
@@ -20,9 +20,7 @@ describe('Getters Helper', () => {
20
20
 
21
21
  test('getPageTitle()', () => {
22
22
  window.location.search = 's=hello';
23
- expect(Getters.getPageTitle({ path: 's' })).toEqual(
24
- 'You searched for hello - norskespilleautomater.com'
25
- );
23
+ expect(Getters.getPageTitle({ path: 's' })).toEqual('You searched for hello - Irishluck.ie');
26
24
  });
27
25
 
28
26
  test('getExtraField()', () => {
@@ -1,4 +1,4 @@
1
- import { groupBy, removeDuplicates } from './common';
1
+ import { groupBy, removeDuplicates, clonePageForCards } from './common';
2
2
  import getPageDataList from '~tests/factories/pages/list.factory';
3
3
 
4
4
  describe('Common Helper', () => {
@@ -18,4 +18,10 @@ describe('Common Helper', () => {
18
18
  const filtered = removeDuplicates(array, 'id');
19
19
  expect(filtered).toHaveLength(2);
20
20
  });
21
+
22
+ test('ClonePageForCards', () => {
23
+ const data = getPageDataList(2);
24
+ const result = clonePageForCards(data, 'comparison_table');
25
+ expect(result?.relation?.bonus?.deposit_methods).toBeFalsy();
26
+ });
21
27
  });
@@ -55,7 +55,7 @@ export function processSitemapPages(pages, markets) {
55
55
  return pageListByMarket;
56
56
  }
57
57
 
58
- function transform(response) {
58
+ export function transform(response) {
59
59
  const transformed = {};
60
60
  Object.keys(response.site_markets).forEach((siteMarket) => {
61
61
  const language = siteMarket.split('_')[1];
@@ -74,7 +74,7 @@ function transform(response) {
74
74
  return transformed;
75
75
  }
76
76
 
77
- function processSections(sections, skipPost = false) {
77
+ export function processSections(sections, skipPost = false) {
78
78
  Object.keys(sections).forEach((sectionKey) => {
79
79
  if (skipPost && sectionKey.includes('post_main')) {
80
80
  return;
@@ -96,7 +96,6 @@ function processSections(sections, skipPost = false) {
96
96
  });
97
97
  }
98
98
  });
99
-
100
99
  return sections;
101
100
  }
102
101
 
@@ -0,0 +1,21 @@
1
+ import { transform, processExtraFields } from './index';
2
+ import pages from '~tests/factories/pages/pages.factory.js';
3
+
4
+ describe('Index Processor', () => {
5
+ test('Transform', () => {
6
+ const results = transform(pages);
7
+ expect(results?.za_en?.page).toBeTruthy();
8
+ });
9
+
10
+ test('processExtraFields', () => {
11
+ const extraFields = {
12
+ logos: { value: 339, type: 'default' },
13
+ };
14
+ processExtraFields(extraFields);
15
+ expect(extraFields?.logos).toBe(339);
16
+ });
17
+ test('processExtraFields null', () => {
18
+ const result = processExtraFields(false);
19
+ expect(result).toBeFalsy();
20
+ });
21
+ });
@@ -98,10 +98,11 @@ export function generateSchemaObject(schema) {
98
98
  }, {});
99
99
  }
100
100
 
101
- export function breadcrumbsSchema(breadcrumbs) {
101
+ export function breadcrumbsSchema(breadcrumbs, path) {
102
102
  const schema = {
103
103
  '@context': 'https://schema.org',
104
104
  '@type': 'BreadcrumbList',
105
+ '@id': `${getUrl(path)}#breadcrumblist`,
105
106
  itemListElement: breadcrumbs.map((breadcrumb, index) => ({
106
107
  '@type': 'ListItem',
107
108
  name: breadcrumb.path,
@@ -177,6 +178,7 @@ export function organizationSchema(page, pageImage) {
177
178
  const schema = {
178
179
  '@context': 'https://schema.org',
179
180
  '@type': 'Organization',
181
+ '@id': `${getUrl(page.path)}#organization`,
180
182
  url: process.env.GATSBY_SITE_URL,
181
183
  name: page.siteSchema?.site_name,
182
184
  logo: pageImage,
@@ -188,13 +190,14 @@ export function organizationSchema(page, pageImage) {
188
190
  return JSON.stringify(generateSchemaObject(schema));
189
191
  }
190
192
 
191
- export function moduleSchemas(modules) {
192
- const schema = modules.map((module) => {
193
+ export function moduleSchemas(modules, path) {
194
+ const schema = modules.map((module, index) => {
193
195
  switch (module.name) {
194
196
  case 'faq': {
195
197
  const moduleSchema = {
196
198
  '@context': 'https://schema.org',
197
199
  '@type': 'FAQPage',
200
+ '@id': `${getUrl(path)}#faqpage${index === 0 ? '' : index}`,
198
201
  mainEntity: module.items?.map((item) => ({
199
202
  '@type': 'Question',
200
203
  acceptedAnswer: {
@@ -233,7 +236,7 @@ export function templateSchemas(page, pageImage) {
233
236
  page.siteInfo?.site_name ||
234
237
  process.env.GATSBY_SITE_NAME,
235
238
  logo:
236
- `${process.env.IMAGE_CDN_URL}/${page.siteInfo?.site_logo}` ||
239
+ (page.siteInfo?.site_logo && `${process.env.IMAGE_CDN_URL}/${page.siteInfo.site_logo}`) ||
237
240
  page.featured_image_object?.url ||
238
241
  pageImage,
239
242
  },
@@ -243,6 +246,7 @@ export function templateSchemas(page, pageImage) {
243
246
  const schema = {
244
247
  '@context': 'https://schema.org',
245
248
  '@type': 'Article',
249
+ '@id': `${getUrl(page.path)}#article`,
246
250
  url: getUrl(page.path),
247
251
  headline: page.title,
248
252
  datePublished: page.created_at,
@@ -260,6 +264,7 @@ export function templateSchemas(page, pageImage) {
260
264
  const schema = {
261
265
  '@context': 'https://schema.org',
262
266
  '@type': 'Review',
267
+ '@id': `${getUrl(page.path)}#review`,
263
268
  name: page.relation?.name || '',
264
269
  reviewBody: page.extra_fields?.operator_summary || '',
265
270
  itemReviewed: {
@@ -284,6 +289,7 @@ export function templateSchemas(page, pageImage) {
284
289
  const schema = {
285
290
  '@context': 'https://schema.org',
286
291
  '@type': 'VideoGame',
292
+ '@id': `${getUrl(page.path)}#videogame`,
287
293
  url: getUrl(page.path),
288
294
  name: page.relation?.name || '',
289
295
  description: page.extra_fields?.game_summary || '',
@@ -319,12 +325,14 @@ export function schemaGenerator(page = {}, pageImage) {
319
325
  // Page Schema
320
326
  page.seo_json_schema,
321
327
  // Breadcrumbs Schema
322
- page.breadcrumbs?.length ? breadcrumbsSchema(page.breadcrumbs) : null,
328
+ page.breadcrumbs?.length ? breadcrumbsSchema(page.breadcrumbs, page.path) : null,
323
329
  // Modules Schemas
324
330
  webPageSchema(page, pageImage),
325
331
  organizationSchema(page, pageImage),
326
332
  templateSchemas(page, pageImage),
327
- ...(page.sections?.main?.modules ? moduleSchemas(page.sections.main.modules) : [null]),
333
+ ...(page.sections?.main?.modules
334
+ ? moduleSchemas(page.sections.main.modules, page.path)
335
+ : [null]),
328
336
  ];
329
337
 
330
338
  return jsonSchema;
@@ -99,12 +99,12 @@ describe('Schema Helper', () => {
99
99
  expect(json.author.foundingDate).toEqual('01/02/03');
100
100
  if (isIL || isNSA) {
101
101
  expect(json.author.publishingPrinciples).toEqual(
102
- isIL
103
- ? 'https://www.irishluck.ie/editorial-principles'
104
- : 'https://www.norskespilleautomater.com/om-oss/prinsipper'
102
+ isNSA
103
+ ? 'https://www.norskespilleautomater.com/om-oss/prinsipper'
104
+ : 'https://www.irishluck.ie/editorial-principles'
105
105
  );
106
106
  } else {
107
- expect(json.author.publishingPrinciples).toEqual(undefined);
107
+ expect(json.author.publishingPrinciples).toEqual(null);
108
108
  }
109
109
 
110
110
  expect(Object.prototype.toString.call(json.author.logo)).toEqual('[object Object]');
@@ -175,16 +175,19 @@ describe('Schema Helper', () => {
175
175
  });
176
176
 
177
177
  test('moduleSchemas(faq)', () => {
178
- const output = Schema.moduleSchemas([
179
- {
180
- name: 'faq',
181
- items: [
182
- { answer: 'Answer A', question: 'Question A' },
183
- { answer: 'Answer B', question: 'Question B' },
184
- { answer: 'Answer C', question: 'Question C' },
185
- ],
186
- },
187
- ])[0];
178
+ const output = Schema.moduleSchemas(
179
+ [
180
+ {
181
+ name: 'faq',
182
+ items: [
183
+ { answer: 'Answer A', question: 'Question A' },
184
+ { answer: 'Answer B', question: 'Question B' },
185
+ { answer: 'Answer C', question: 'Question C' },
186
+ ],
187
+ },
188
+ ],
189
+ '/'
190
+ )[0];
188
191
 
189
192
  const json = parseCheckSchema(output);
190
193
  expect(json['@type']).toEqual('FAQPage');
@@ -6,7 +6,7 @@ import { GatsbyImage } from 'gatsby-plugin-image';
6
6
  export const PureImage = ({
7
7
  filename,
8
8
  className = '',
9
- alt = '',
9
+ alt = 'missing alt',
10
10
  height = '100%',
11
11
  width = '100%',
12
12
  data,
@@ -1,7 +1,7 @@
1
- import React, { useState } from 'react';
1
+ import React, { useState, useEffect } from 'react';
2
2
  // eslint-disable-next-line import/no-extraneous-dependencies
3
3
  import PropTypes from 'prop-types';
4
- import loadable from '@loadable/component';
4
+ import LazyLoad from 'react-lazyload';
5
5
  import { isNativeImageLazyLoadingSupported } from '~helpers/device-detect';
6
6
 
7
7
  export default function LazyImage({
@@ -10,50 +10,22 @@ export default function LazyImage({
10
10
  style = {},
11
11
  className,
12
12
  src = '#',
13
- alt = '',
13
+ alt = 'missing alt',
14
14
  defaultImg,
15
15
  loading = 'lazy',
16
16
  }) {
17
17
  const [errorImage, setErrorImage] = useState(false);
18
+ const [nonNativeLazyLoaded, setNonNativeLazyLoaded] = useState(false);
19
+
20
+ useEffect(() => {
21
+ setNonNativeLazyLoaded(!isNativeImageLazyLoadingSupported());
22
+ }, []);
18
23
 
19
24
  if ((defaultImg && !src) || errorImage === true) {
20
25
  return defaultImg;
21
26
  }
22
27
 
23
- if (!isNativeImageLazyLoadingSupported()) {
24
- const LazyLoad = loadable(() => import(`react-lazyload`));
25
- return (
26
- <>
27
- <LazyLoad
28
- height={height ? `${height}px` : null}
29
- width={width ? `${width}px` : null}
30
- placeholder={<span className="lazyload-placeholder" />}
31
- debounce={0}
32
- >
33
- <img
34
- src={src}
35
- className={className}
36
- height={height}
37
- width={width}
38
- alt={alt}
39
- style={style}
40
- />
41
- </LazyLoad>
42
- <noscript>
43
- <img
44
- src={src}
45
- className={className}
46
- height={height}
47
- width={width}
48
- alt={alt}
49
- style={style}
50
- />
51
- </noscript>
52
- </>
53
- );
54
- }
55
-
56
- return (
28
+ return !nonNativeLazyLoaded ? (
57
29
  <img
58
30
  src={src}
59
31
  loading={loading}
@@ -64,6 +36,34 @@ export default function LazyImage({
64
36
  style={style}
65
37
  onError={() => setErrorImage(true)}
66
38
  />
39
+ ) : (
40
+ <>
41
+ <LazyLoad
42
+ height={height ? `${height}px` : null}
43
+ width={width ? `${width}px` : null}
44
+ placeholder={<span className="lazyload-placeholder" />}
45
+ debounce={0}
46
+ >
47
+ <img
48
+ src={src}
49
+ className={className}
50
+ height={height}
51
+ width={width}
52
+ alt={alt}
53
+ style={style}
54
+ />
55
+ </LazyLoad>
56
+ <noscript>
57
+ <img
58
+ src={src}
59
+ className={className}
60
+ height={height}
61
+ width={width}
62
+ alt={alt}
63
+ style={style}
64
+ />
65
+ </noscript>
66
+ </>
67
67
  );
68
68
  }
69
69
 
@@ -0,0 +1,39 @@
1
+ import React from 'react';
2
+ import { render, cleanup } from '@testing-library/react';
3
+ import '@testing-library/jest-dom/extend-expect';
4
+ import LazyImage from '.';
5
+
6
+ describe('LazyImage function', () => {
7
+ test('LazyImage defaultImg', () => {
8
+ const { container } = render(
9
+ <LazyImage
10
+ src={null}
11
+ defaultImg={<img src="https://cdn.irishluck.ie/jackpot-village-logo-9.png" alt="test" />}
12
+ />
13
+ );
14
+ expect(container.querySelector('img')).toBeTruthy();
15
+ expect(container.querySelector('img')).toHaveAttribute(
16
+ 'src',
17
+ 'https://cdn.irishluck.ie/jackpot-village-logo-9.png'
18
+ );
19
+ });
20
+
21
+ test('LazyImage mock function inisNativeImageLazyLoadingSupported', () => {
22
+ // eslint-disable-next-line global-require
23
+ const func = require('../../helpers/device-detect');
24
+ func.isNativeImageLazyLoadingSupported = jest.fn(() => true);
25
+ const { container } = render(
26
+ <LazyImage src="https://cdn.irishluck.ie/jackpot-village-logo-9.png" />
27
+ );
28
+ expect(container.querySelector('img')).toBeTruthy();
29
+ expect(container.querySelector('img')).toHaveAttribute(
30
+ 'src',
31
+ 'https://cdn.irishluck.ie/jackpot-village-logo-9.png'
32
+ );
33
+ expect(container.querySelector('img')).toHaveAttribute('loading', 'lazy');
34
+ });
35
+ });
36
+
37
+ afterEach(() => {
38
+ cleanup();
39
+ });
@@ -11,7 +11,7 @@ export default function LazyPicture({
11
11
  offset = 200,
12
12
  style = {},
13
13
  className,
14
- alt = '',
14
+ alt = 'missing alt',
15
15
  webp = '',
16
16
  mobileSrc = '',
17
17
  desktopSrc = '',