@nuskin/foundation-ui-components 1.6.1 → 1.7.0

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 (43) hide show
  1. package/package.json +1 -1
  2. package/src/common/card/NsBrandCard.tsx +94 -0
  3. package/src/common/card/NsCheckoutCard.tsx +92 -0
  4. package/src/common/card/NsHeroCardLevel1.tsx +106 -0
  5. package/src/common/card/NsHeroCardLevel2.tsx +126 -0
  6. package/src/common/card/NsIconText.tsx +153 -0
  7. package/src/common/card/NsLargeCard.tsx +120 -0
  8. package/src/common/card/NsMediumCard.tsx +64 -0
  9. package/src/common/card/NsPost.tsx +60 -0
  10. package/src/common/card/NsSmallFullCard.tsx +90 -0
  11. package/src/common/card/NsXLargeCard.tsx +80 -0
  12. package/src/common/card/cardSizes.ts +12 -0
  13. package/src/common/card/index.ts +10 -2
  14. package/src/common/card/specs/BrandLogo.spec.tsx +1 -1
  15. package/src/common/card/specs/NsBgCard.spec.tsx +2 -2
  16. package/src/common/card/specs/NsBrandCard.spec.tsx +97 -0
  17. package/src/common/card/specs/NsCheckoutCard.spec.tsx +50 -0
  18. package/src/common/card/specs/NsHeroCardLevel1.spec.tsx +48 -0
  19. package/src/common/card/specs/NsHeroCardLevel2.spec.tsx +51 -0
  20. package/src/common/card/specs/NsIconText.spec.tsx +28 -0
  21. package/src/common/card/specs/NsLargeCard.spec.tsx +41 -0
  22. package/src/common/card/specs/NsMediumCard.spec.tsx +35 -0
  23. package/src/common/card/specs/NsPost.spec.tsx +31 -0
  24. package/src/common/card/specs/NsSmallFullCard.spec.tsx +36 -0
  25. package/src/common/card/specs/NsXLargeCard.spec.tsx +35 -0
  26. package/src/common/card/stories/{NsBrandProductCard.stories.tsx → NsBrandCard.stories.tsx} +9 -4
  27. package/src/common/card/stories/NsCheckoutCard.stories.tsx +24 -0
  28. package/src/common/card/stories/NsHeroCardLevel1.stories.tsx +45 -0
  29. package/src/common/card/stories/NsHeroCardLevel2.stories.tsx +50 -0
  30. package/src/common/card/stories/NsIconText.stories.tsx +36 -0
  31. package/src/common/card/stories/NsLargeCard.stories.tsx +32 -0
  32. package/src/common/card/stories/NsMediumCard.stories.tsx +29 -0
  33. package/src/common/card/stories/NsPost.stories.tsx +39 -0
  34. package/src/common/card/stories/NsSmallFullCard.stories.tsx +29 -0
  35. package/src/common/card/stories/NsXLargeCard.stories.tsx +29 -0
  36. package/src/common/carousal/RenderBrand.tsx +3 -2
  37. package/src/common/card/NsBrandProductCard.tsx +0 -47
  38. package/src/common/card/NsFfgCard.tsx +0 -24
  39. package/src/common/card/specs/NsBrandProductCard.spec.tsx +0 -32
  40. package/src/common/card/specs/NsFfgCard.spec.tsx +0 -33
  41. package/src/common/card/stories/NsBgCard.stories.tsx +0 -20
  42. package/src/common/card/stories/NsFfgCard.stories.tsx +0 -73
  43. package/src/common/card/styled/NsFfgStyled.tsx +0 -46
@@ -0,0 +1,120 @@
1
+ import Box from '@mui/material/Box';
2
+ import { styled } from '@nuskin/foundation-theme';
3
+ import { NsButton, NsIcon, NsImage, NsLink, NsIconNameType } from '..';
4
+
5
+ type NsLargeCardProps = {
6
+ title: string;
7
+ subtitle: string;
8
+ intro: string;
9
+ icon: NsIconNameType;
10
+ backgroundImageUrl: string;
11
+ backgroundImageAlt: string;
12
+ cardLink: { href: string; title: string };
13
+ isHorizontal?: boolean;
14
+ };
15
+
16
+ const CardContainer = styled((props: any) => <Box {...props} />)(({ isHorizontal }) => {
17
+ let width = 'fit-content',
18
+ paddingLeft = '0px',
19
+ justifyContent,
20
+ fontSizeSub = '11px',
21
+ fontSizeTitle = '26px';
22
+
23
+ if (isHorizontal) {
24
+ width = '400px';
25
+ paddingLeft = '30px';
26
+ justifyContent = 'space-around';
27
+ fontSizeSub = '16px';
28
+ fontSizeTitle = '36px';
29
+ }
30
+ let direction = isHorizontal ? ('row' as 'row') : ('column' as 'column');
31
+
32
+ return {
33
+ display: 'flex',
34
+ flexDirection: direction,
35
+ position: 'relative',
36
+ '.image': {
37
+ width: '375px',
38
+ height: '392px',
39
+ objectFit: 'cover',
40
+ },
41
+ '.content': {
42
+ display: 'flex',
43
+ flexDirection: 'column',
44
+ width,
45
+ paddingLeft,
46
+ justifyContent,
47
+ },
48
+ '.subtitle': {
49
+ fontSize: fontSizeSub,
50
+ fontWeight: '400',
51
+ marginTop: '10px',
52
+ },
53
+ '.title': {
54
+ fontSize: fontSizeTitle,
55
+ fontWeight: '400',
56
+ marginTop: '10px',
57
+ },
58
+ '.cta': {
59
+ display: 'flex',
60
+ flexDirection: 'column' as 'column',
61
+ width: 'fit-content',
62
+ borderBottom: '1px solid black',
63
+ ':hover': {
64
+ opacity: '0.8',
65
+ },
66
+ },
67
+ '.action-link': {
68
+ marginTop: '10px',
69
+ display: 'flex',
70
+ fontWeight: 600,
71
+ ':hover': {
72
+ textDecoration: 'none',
73
+ },
74
+ },
75
+ '.icon': {
76
+ marginLeft: '10px',
77
+ },
78
+ };
79
+ });
80
+
81
+ export default function NsLargeCard({
82
+ title,
83
+ subtitle,
84
+ backgroundImageUrl,
85
+ backgroundImageAlt,
86
+ cardLink,
87
+ intro,
88
+ icon,
89
+ isHorizontal,
90
+ }: NsLargeCardProps) {
91
+ return (
92
+ <CardContainer role="large-card" component="div" data-testid="large-card" isHorizontal={isHorizontal}>
93
+ <NsImage alt={backgroundImageAlt} src={backgroundImageUrl} className="image" />
94
+ <div className="content">
95
+ <article className="subtitle">{subtitle}</article>
96
+ <article className="title">{title}</article>
97
+ <article className="subtitle">{intro}</article>
98
+ {isHorizontal ? (
99
+ <div className="cta">
100
+ <NsLink className="action-link" href={cardLink.href}>
101
+ {cardLink.title}
102
+ <NsIcon className="icon" name={icon} />
103
+ </NsLink>
104
+ </div>
105
+ ) : (
106
+ <NsButton
107
+ className="action-link"
108
+ variant="outlined"
109
+ color="primary"
110
+ href={cardLink.href}
111
+ fullWidth={false}
112
+ darkModeEnabled={false}
113
+ >
114
+ {cardLink.title}
115
+ </NsButton>
116
+ )}
117
+ </div>
118
+ </CardContainer>
119
+ );
120
+ }
@@ -0,0 +1,64 @@
1
+ import Box from '@mui/material/Box';
2
+ import { styled } from '@nuskin/foundation-theme';
3
+ import { NsButton, NsImage } from '..';
4
+
5
+ type NsMediumCardProps = {
6
+ title: string;
7
+ subtitle: string;
8
+ backgroundImageUrl: string;
9
+ backgroundImageAlt: string;
10
+ cardLink: { href: string; title: string };
11
+ };
12
+
13
+ const CardContainer = styled(Box)(() => {
14
+ return {
15
+ display: 'flex',
16
+ flexDirection: 'column',
17
+ position: 'relative',
18
+ '.image': {
19
+ width: '300px',
20
+ height: '300px',
21
+ objectFit: 'cover',
22
+ },
23
+ '.content': {
24
+ display: 'flex',
25
+ flexDirection: 'column',
26
+ },
27
+ '.subtitle': {
28
+ fontSize: '11px',
29
+ fontWeight: '400',
30
+ marginTop: '10px',
31
+ },
32
+ '.title': {
33
+ fontSize: '16px',
34
+ fontWeight: '400',
35
+ marginTop: '10px',
36
+ },
37
+ '.action-link': {
38
+ marginTop: '10px',
39
+ fontSize: '14px',
40
+ alignSelf: 'start',
41
+ },
42
+ };
43
+ });
44
+
45
+ export default function NsMediumCard({
46
+ title,
47
+ subtitle,
48
+ backgroundImageUrl,
49
+ backgroundImageAlt,
50
+ cardLink,
51
+ }: NsMediumCardProps) {
52
+ return (
53
+ <CardContainer role="medium-card" component="div" data-testid="medium-card">
54
+ <NsImage alt={backgroundImageAlt} src={backgroundImageUrl} className="image" />
55
+ <div className="content">
56
+ <article className="title">{title}</article>
57
+ <article className="subtitle">{subtitle}</article>
58
+ <NsButton className="action-link" variant="outlined" color="primary" href={cardLink.href}>
59
+ {cardLink.title}
60
+ </NsButton>
61
+ </div>
62
+ </CardContainer>
63
+ );
64
+ }
@@ -0,0 +1,60 @@
1
+ import Box from '@mui/material/Box';
2
+ import { NsImage } from '../';
3
+ import { AdditionalProps } from '../common.types';
4
+ import { styled } from '@nuskin/foundation-theme';
5
+
6
+ type NsPostProps = {
7
+ text: string;
8
+ body: string;
9
+ backgroundImageUrl: string;
10
+ backgroundImageAlt: string;
11
+ } & AdditionalProps;
12
+
13
+ const CardContainer = styled(Box)(() => {
14
+ return {
15
+ backgroundClip: 'border-box',
16
+ display: 'flex',
17
+ flexDirection: 'column' as 'column', // https://github.com/cssinjs/jss/issues/1344
18
+ wordWrap: 'break-word' as 'break-word',
19
+ position: 'relative',
20
+ overflow: 'hidden',
21
+ height: 'auto',
22
+ width: '165px',
23
+ backgroundColor: '#fff',
24
+ '.image': {
25
+ width: '100%',
26
+ height: '180px',
27
+ display: 'block',
28
+ },
29
+ '.content': {
30
+ padding: '20px',
31
+ display: 'flex',
32
+ flexDirection: 'column',
33
+ },
34
+ '.body-title': {
35
+ fontSize: '18px',
36
+ marginBottom: '5px',
37
+ fontWeight: 600,
38
+ },
39
+ '.body-text': {
40
+ fontSize: '12px',
41
+ color: '#8C8C8C',
42
+ marginBottom: '5px',
43
+ },
44
+ };
45
+ });
46
+
47
+ const NsPost = ({ text, body, backgroundImageUrl, backgroundImageAlt, additionalProps }: NsPostProps) => {
48
+ return (
49
+ <CardContainer data-testid={additionalProps?.testid}>
50
+ <div className="image">
51
+ <NsImage height="auto" width="100%" alt={backgroundImageAlt} src={backgroundImageUrl} />
52
+ </div>
53
+ <div className="content">
54
+ <article className="body-title">{text}</article>
55
+ <article className="body-text">{body}</article>
56
+ </div>
57
+ </CardContainer>
58
+ );
59
+ };
60
+ export default NsPost;
@@ -0,0 +1,90 @@
1
+ import Box from '@mui/material/Box';
2
+ import { styled } from '@nuskin/foundation-theme';
3
+ import { NsImage, NsLink } from '../';
4
+
5
+ type NsSmallFullCardProps = {
6
+ title: string;
7
+ subtitle: string;
8
+ backgroundImageUrl: string;
9
+ backgroundImageAlt: string;
10
+ cardLink: { href: string; title: string };
11
+ };
12
+
13
+ const CardContainer = styled(Box)(() => {
14
+ return {
15
+ backgroundColor: '#fff',
16
+ display: 'flex',
17
+ height: '320px',
18
+ width: '375px',
19
+ position: 'relative',
20
+ '.image': {
21
+ width: '100%',
22
+ height: '100%',
23
+ objectFit: 'cover',
24
+ },
25
+ '.gradientOverlay': {
26
+ position: 'absolute',
27
+ top: 0,
28
+ left: 0,
29
+ width: '100%',
30
+ height: '100%',
31
+ background: 'linear-gradient(to top, rgba(0,0,0,0.6) 0%, transparent 50%);',
32
+ },
33
+ '.content': {
34
+ position: 'absolute',
35
+ height: '100%',
36
+ width: '100%',
37
+ padding: '40px 40px 25px 30px',
38
+ display: 'flex',
39
+ flexDirection: 'column',
40
+ },
41
+ '.subtitle': {
42
+ color: '#fff',
43
+ fontSize: '11px',
44
+ fontWeight: '400',
45
+ marginTop: 'auto',
46
+ },
47
+ '.title': {
48
+ color: '#fff',
49
+ fontSize: '26px',
50
+ fontWeight: '400',
51
+ marginTop: '20px',
52
+ },
53
+ '.action-link': {
54
+ display: 'flex',
55
+ justifyContent: 'center',
56
+ backgroundColor: '#252525',
57
+ color: '#fff',
58
+ marginTop: '20px',
59
+ borderRadius: '4px',
60
+ padding: '10px',
61
+ width: '70%',
62
+ ':hover': {
63
+ textDecoration: 'none',
64
+ backgroundColor: '#3e3e3e',
65
+ },
66
+ },
67
+ };
68
+ });
69
+
70
+ export default function NsSmallFullCard({
71
+ title,
72
+ subtitle,
73
+ backgroundImageUrl,
74
+ backgroundImageAlt,
75
+ cardLink,
76
+ }: NsSmallFullCardProps) {
77
+ return (
78
+ <CardContainer role="small-full-card" component="div" data-testid="small-full-card">
79
+ <NsImage alt={backgroundImageAlt} src={backgroundImageUrl} className="image" />
80
+ <div className="gradientOverlay"></div>
81
+ <div className="content">
82
+ <article className="subtitle">{subtitle}</article>
83
+ <article className="title">{title}</article>
84
+ <NsLink className="action-link" href={cardLink.href}>
85
+ {cardLink.title}
86
+ </NsLink>
87
+ </div>
88
+ </CardContainer>
89
+ );
90
+ }
@@ -0,0 +1,80 @@
1
+ import Box from '@mui/material/Box';
2
+ import { styled } from '@nuskin/foundation-theme';
3
+ import { NsButton, NsImage } from '..';
4
+
5
+ type NsXLargeCardProps = {
6
+ title: string;
7
+ subtitle: string;
8
+ backgroundImageUrl: string;
9
+ backgroundImageAlt: string;
10
+ cardLink: { href: string; title: string };
11
+ };
12
+
13
+ const CardContainer = styled(Box)(() => {
14
+ return {
15
+ backgroundColor: '#fff',
16
+ display: 'flex',
17
+ height: '545px',
18
+ width: '375px',
19
+ position: 'relative',
20
+ '.image': {
21
+ width: '100%',
22
+ height: '100%',
23
+ objectFit: 'cover',
24
+ },
25
+ '.gradientOverlay': {
26
+ position: 'absolute',
27
+ top: 0,
28
+ left: 0,
29
+ width: '100%',
30
+ height: '100%',
31
+ background: 'linear-gradient(to top, rgba(0,0,0,0.6) 0%, transparent 50%);',
32
+ },
33
+ '.content': {
34
+ position: 'absolute',
35
+ height: '100%',
36
+ width: '100%',
37
+ padding: '40px 40px 25px 30px',
38
+ display: 'flex',
39
+ flexDirection: 'column',
40
+ },
41
+ '.subtitle': {
42
+ color: '#fff',
43
+ fontSize: '11px',
44
+ fontWeight: '400',
45
+ marginTop: 'auto',
46
+ },
47
+ '.title': {
48
+ color: '#fff',
49
+ fontSize: '26px',
50
+ fontWeight: '400',
51
+ marginTop: '20px',
52
+ },
53
+ '.action-link': {
54
+ marginTop: '20px',
55
+ width: '70%',
56
+ },
57
+ };
58
+ });
59
+
60
+ export default function NsXLargeCard({
61
+ title,
62
+ subtitle,
63
+ backgroundImageUrl,
64
+ backgroundImageAlt,
65
+ cardLink,
66
+ }: NsXLargeCardProps) {
67
+ return (
68
+ <CardContainer role="x-large-card" component="div" data-testid="x-large-card">
69
+ <NsImage alt={backgroundImageAlt} src={backgroundImageUrl} className="image" />
70
+ <div className="gradientOverlay"></div>
71
+ <div className="content">
72
+ <article className="subtitle">{subtitle}</article>
73
+ <article className="title">{title}</article>
74
+ <NsButton className="action-link" variant="outlined" color="secondary" href={cardLink.href}>
75
+ {cardLink.title}
76
+ </NsButton>
77
+ </div>
78
+ </CardContainer>
79
+ );
80
+ }
@@ -0,0 +1,12 @@
1
+ const cardSizes = {
2
+ small: {
3
+ width: '165px',
4
+ height: '180px',
5
+ },
6
+ large: {
7
+ width: '190px',
8
+ height: '220px',
9
+ },
10
+ };
11
+
12
+ export default cardSizes;
@@ -1,5 +1,13 @@
1
1
  export { default as NsBrandWrapper } from './NsBrandWrapper';
2
2
  export { default as NsBgCard } from './NsBgCard';
3
- export { default as NsFfgCard } from './NsFfgCard';
4
3
  export { default as NsBrandLogo } from './NsBrandLogo';
5
- export { default as NsBrandProductCard } from './NsBrandProductCard';
4
+ export { default as NsHeroCardLevel1 } from './NsHeroCardLevel1';
5
+ export { default as NsHeroCardLevel2 } from './NsHeroCardLevel2';
6
+ export { default as NsPost } from './NsPost';
7
+ export { default as NsBrandCard } from './NsBrandCard';
8
+ export { default as NsIconText } from './NsIconText';
9
+ export { default as NsCheckoutCard } from './NsCheckoutCard';
10
+ export { default as NsSmallFullCard } from './NsSmallFullCard';
11
+ export { default as NsXLargeCard } from './NsXLargeCard';
12
+ export { default as NsLargeCard } from './NsLargeCard';
13
+ export { default as NsMediumCard } from './NsMediumCard';
@@ -2,7 +2,7 @@ import { render } from '@testing-library/react';
2
2
  import NsBrandLogo from '../NsBrandLogo';
3
3
 
4
4
  describe('BrandLogo component', () => {
5
- it('renders with cover size', () => {
5
+ it('1. renders with cover size', () => {
6
6
  const { container } = render(<NsBrandLogo component="img" />);
7
7
  const cardElement = container.querySelector('img');
8
8
  expect(cardElement).toHaveStyle(`
@@ -5,14 +5,14 @@ describe('NsBgCard component', () => {
5
5
  const props = {
6
6
  backgroundImageUrl: 'https://media.nuskin.com/m/6245528b8f76ad32/webimage-brand-ageLOC.png',
7
7
  };
8
- it('renders with background image', () => {
8
+ it('1. renders with background image', () => {
9
9
  const { container } = render(<NsBgCard {...props} />);
10
10
  const cardElement = container.querySelector('div');
11
11
  expect(cardElement).toHaveStyle(`
12
12
  background-image: url(${props.backgroundImageUrl});
13
13
  `);
14
14
  });
15
- it('renders with cover size', () => {
15
+ it('2. renders with cover size', () => {
16
16
  const { container } = render(<NsBgCard {...props} />);
17
17
  const cardElement = container.querySelector('div');
18
18
  expect(cardElement).toHaveStyle(`
@@ -0,0 +1,97 @@
1
+ import React from 'react';
2
+ import { render, screen } from '@testing-library/react';
3
+ import userEvent from '@testing-library/user-event';
4
+ import NsBrandCard from '../NsBrandCard';
5
+
6
+ describe('NsBrandCard component', () => {
7
+ const props = {
8
+ title: 'ageLOC LumiSpa',
9
+ backgroundImageUrl: 'https://media.nuskin.com/m/3604b5202b0b64c6/webimage-brand-lumispa-optweb.png',
10
+ brandImageUrl: 'https://media.nuskin.com/m/2571a0407433a6e8/webimage-brand-lumispa.png',
11
+ button: true,
12
+ };
13
+
14
+ it('1. renders with correct content and styles', () => {
15
+ render(<NsBrandCard {...props} />);
16
+
17
+ const brandCard = screen.getByTestId('brand-card');
18
+ expect(brandCard).toBeInTheDocument();
19
+
20
+ const brandTitle = screen.getByText('ageLOC LumiSpa');
21
+ expect(brandTitle).toBeInTheDocument();
22
+
23
+ const addToCartButton = screen.getByText('Add to Cart');
24
+ expect(addToCartButton).toBeInTheDocument();
25
+ });
26
+
27
+ it('2. does not render brand title when title is not provided', () => {
28
+ const { container } = render(<NsBrandCard {...{ ...props, title: undefined }} />);
29
+
30
+ const brandTitle = container.querySelector('.brand-title');
31
+ expect(brandTitle).toBeNull();
32
+ });
33
+
34
+ it('3. renders with "Add to Cart" button when button prop is true', () => {
35
+ render(<NsBrandCard {...props} />);
36
+
37
+ const addToCartButton = screen.getByText('Add to Cart');
38
+ expect(addToCartButton).toBeInTheDocument();
39
+ });
40
+
41
+ it('4. does not render button when button prop is false', () => {
42
+ const { container } = render(<NsBrandCard {...{ ...props, button: false }} />);
43
+
44
+ const addToCartButton = container.querySelector('.cta');
45
+ expect(addToCartButton).toBeNull();
46
+ });
47
+
48
+ it('5. calls onClick when the "Add to Cart" button is clicked', () => {
49
+ const onClickMock = jest.fn();
50
+ render(<NsBrandCard {...props} onClick={onClickMock} />);
51
+
52
+ const addToCartButton = screen.getByText('Add to Cart');
53
+ userEvent.click(addToCartButton);
54
+
55
+ expect(onClickMock).toHaveBeenCalled();
56
+ });
57
+
58
+ it('6. applies hover styles on mouseover', () => {
59
+ render(<NsBrandCard {...props} />);
60
+
61
+ const brandCard = screen.getByTestId('brand-card');
62
+ userEvent.hover(brandCard);
63
+
64
+ const brandTitle = screen.getByText('ageLOC LumiSpa');
65
+ expect(brandTitle).toHaveStyle('opacity: 0.7');
66
+ });
67
+
68
+ it('7. renders with correct styles when size is "small"', () => {
69
+ const { container } = render(<NsBrandCard {...props} size="small" />);
70
+
71
+ const cardContainer = container.firstChild;
72
+ const nsBgCardElement = cardContainer?.firstChild;
73
+ expect(cardContainer).toHaveStyle(`
74
+ width: 165px;
75
+ `);
76
+ expect(nsBgCardElement).toHaveStyle(`
77
+ width: 165px;
78
+ height: 180px;
79
+ `);
80
+ });
81
+
82
+ it('8. renders with correct styles when size is "large"', () => {
83
+ render(<NsBrandCard {...props} size="large" />);
84
+ const cardContainer = screen.getByTestId('brand-card') as HTMLElement;
85
+ const computedStyles = window.getComputedStyle(cardContainer);
86
+
87
+ expect(computedStyles.width).toBe('190px');
88
+ });
89
+
90
+ it('9. renders with default styles when size is not provided', () => {
91
+ render(<NsBrandCard {...props} />);
92
+ const cardContainer = screen.getByTestId('brand-card') as HTMLElement;
93
+ const computedStyles = window.getComputedStyle(cardContainer);
94
+
95
+ expect(computedStyles.width).toBe('190px');
96
+ });
97
+ });
@@ -0,0 +1,50 @@
1
+ import React from 'react';
2
+ import { render, screen, fireEvent } from '@testing-library/react';
3
+ import '@testing-library/jest-dom';
4
+ import NsCheckoutCard from '../NsCheckoutCard';
5
+
6
+ describe('NsCheckoutCard component', () => {
7
+ const props = {
8
+ title: 'Section Title',
9
+ address: 'Address',
10
+ icon: 'home' as 'home',
11
+ onClick: jest.fn(),
12
+ };
13
+
14
+ it('1. renders with correct content and styles', () => {
15
+ render(<NsCheckoutCard {...props} />);
16
+
17
+ const checkoutCard = screen.getByTestId('checkout-card');
18
+ expect(checkoutCard).toBeInTheDocument();
19
+
20
+ const titleElement = screen.getByText(props.title);
21
+ expect(titleElement).toBeInTheDocument();
22
+
23
+ const addressElement = screen.getByText(props.address);
24
+ expect(addressElement).toBeInTheDocument();
25
+
26
+ const changeLink = screen.getByText('CHANGE');
27
+ expect(changeLink).toBeInTheDocument();
28
+ });
29
+
30
+ it('2. toggles dropdown icon on click', () => {
31
+ render(<NsCheckoutCard {...props} />);
32
+
33
+ const dropdownIcon = screen.getByTestId('dropdown-icon');
34
+
35
+ fireEvent.click(dropdownIcon);
36
+ // expect(dropdownIcon).toHaveAttribute('name', 'arrowUp');
37
+
38
+ // fireEvent.click(dropdownIcon);
39
+ // expect(dropdownIcon).toHaveAttribute('name', 'arrowDown');
40
+ });
41
+
42
+ it('3. calls onClick when the card is clicked', () => {
43
+ render(<NsCheckoutCard {...props} />);
44
+
45
+ const checkoutCard = screen.getByTestId('checkout-card');
46
+ fireEvent.click(checkoutCard);
47
+
48
+ expect(props.onClick).toHaveBeenCalled();
49
+ });
50
+ });
@@ -0,0 +1,48 @@
1
+ import React from 'react';
2
+ import { render, screen } from '@testing-library/react';
3
+ import userEvent from '@testing-library/user-event';
4
+ import NsHeroCardLevel1 from '../NsHeroCardLevel1';
5
+
6
+ describe('NsHeroCardLevel1 component', () => {
7
+ const props = {
8
+ cardLink: {
9
+ href: 'https://www.forceforgood.org/',
10
+ title: 'SHOP NOW',
11
+ },
12
+ text: 'A skin ready for winter',
13
+ body: 'We have brought these discoveries to life through our powerful skin care products and supplements.',
14
+ backgroundImageUrl:
15
+ 'https://media.nuskin.com/m/9734240cc191163/webimage-lash-brow-serum-carousel-image-launch.png',
16
+ backgroundImageAlt: 'lash brow serum carousel',
17
+ onClick: jest.fn(),
18
+ additionalProps: {
19
+ testid: 'hero-card-level-1',
20
+ },
21
+ };
22
+
23
+ it('1. renders with correct content and styles', () => {
24
+ render(<NsHeroCardLevel1 {...props} />);
25
+
26
+ const heroCard = screen.getByTestId('hero-card-level-1');
27
+ expect(heroCard).toBeInTheDocument();
28
+
29
+ const shopNowLink = screen.getByText('SHOP NOW');
30
+ expect(shopNowLink).toBeInTheDocument();
31
+ });
32
+
33
+ it('2. calls onClick when the card is clicked', () => {
34
+ render(<NsHeroCardLevel1 {...props} />);
35
+
36
+ const heroCard = screen.getByTestId('hero-card-level-1');
37
+ userEvent.click(heroCard);
38
+
39
+ expect(props.onClick).toHaveBeenCalled();
40
+ });
41
+
42
+ it('3. applies hover styles on mouseover', () => {
43
+ render(<NsHeroCardLevel1 {...props} />);
44
+
45
+ const heroCard = screen.getByTestId('hero-card-level-1');
46
+ userEvent.hover(heroCard);
47
+ });
48
+ });