@purpurds/content-block 5.9.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.
@@ -0,0 +1 @@
1
+ ._purpur-content-block_1c7ua_1{display:flex;flex-direction:column;align-items:flex-start;gap:var(--purpur-spacing-400)}@media (min-width: 1024px){._purpur-content-block_1c7ua_1{align-items:center;flex-direction:row;gap:var(--purpur-spacing-300)}._purpur-content-block_1c7ua_1:nth-child(2n){flex-direction:row-reverse}}@media (min-width: 1024px){._purpur-content-block_1c7ua_1 ._purpur-content-block__section_1c7ua_18{width:50%}}._purpur-content-block_1c7ua_1 ._purpur-content-block__image-wrapper_1c7ua_22{width:100%}._purpur-content-block_1c7ua_1 ._purpur-content-block__video-wrapper_1c7ua_25 video,._purpur-content-block_1c7ua_1 ._purpur-content-block__image-wrapper_1c7ua_22 img{border-radius:var(--purpur-border-radius-md)}@media (min-width: 600px){._purpur-content-block_1c7ua_1 ._purpur-content-block__video-wrapper_1c7ua_25 video,._purpur-content-block_1c7ua_1 ._purpur-content-block__image-wrapper_1c7ua_22 img{border-radius:var(--purpur-border-radius-lg)}}._purpur-content-block_1c7ua_1 ._purpur-content-block__content-wrapper_1c7ua_35{display:flex;flex-direction:column;gap:var(--purpur-spacing-150)}._purpur-content-block_1c7ua_1 ._purpur-content-block__badge_1c7ua_40{width:fit-content}._purpur-content-block_1c7ua_1 ._purpur-content-block__content_1c7ua_35{max-width:40rem}._purpur-content-block_1c7ua_1 ._purpur-content-block__usp-list_1c7ua_46{margin:0;padding:0;list-style:none}._purpur-content-block_1c7ua_1 ._purpur-content-block__usp-list-item_1c7ua_51{display:flex;align-items:center;justify-content:left}._purpur-content-block_1c7ua_1 ._purpur-content-block__usp-list-item_1c7ua_51:not(:last-child){margin-bottom:var(--purpur-spacing-100)}._purpur-content-block_1c7ua_1 ._purpur-content-block__usp-list-item-icon_1c7ua_59{margin-right:var(--purpur-spacing-50)}._purpur-content-block_1c7ua_1 ._purpur-content-block__links_1c7ua_62{margin-top:var(--purpur-spacing-250);display:flex;flex-direction:column;gap:var(--purpur-spacing-200)}@media (min-width: 600px){._purpur-content-block_1c7ua_1 ._purpur-content-block__links_1c7ua_62{flex-direction:row}}._purpur-content-block--negative_1c7ua_73 ._purpur-content-block__text-spacing_1c7ua_73 p{color:var(--purpur-color-text-default-negative)}._purpur-content-block--negative_1c7ua_73 ._purpur-content-block__usp-list-item-icon_1c7ua_59 svg{fill:var(--purpur-color-text-default-negative)}._purpur-content-block-group_1g4rh_1{display:flex;flex-direction:column;gap:var(--purpur-spacing-1200);padding:var(--purpur-spacing-600) 0}@media (min-width: 600px){._purpur-content-block-group_1g4rh_1{gap:var(--purpur-spacing-1600);padding:var(--purpur-spacing-800) 0}}
package/package.json ADDED
@@ -0,0 +1,65 @@
1
+ {
2
+ "name": "@purpurds/content-block",
3
+ "version": "5.9.0",
4
+ "license": "AGPL-3.0-only",
5
+ "main": "./dist/content-block.cjs.js",
6
+ "types": "./dist/content-block.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "require": "./dist/content-block.cjs.js",
10
+ "types": "./dist/content-block.d.ts",
11
+ "default": "./dist/content-block.es.js"
12
+ },
13
+ "./styles": "./dist/styles.css"
14
+ },
15
+ "source": "src/content-block.tsx",
16
+ "dependencies": {
17
+ "classnames": "~2.5.0",
18
+ "@purpurds/badge": "5.11.2",
19
+ "@purpurds/grid": "5.11.2",
20
+ "@purpurds/cta-link": "5.11.2",
21
+ "@purpurds/icon": "5.11.2",
22
+ "@purpurds/heading": "5.11.2",
23
+ "@purpurds/paragraph": "5.11.2",
24
+ "@purpurds/tokens": "5.11.2"
25
+ },
26
+ "devDependencies": {
27
+ "@rushstack/eslint-patch": "~1.10.0",
28
+ "@storybook/blocks": "^8.2.6",
29
+ "@storybook/react": "^8.2.6",
30
+ "@telia/base-rig": "~8.2.0",
31
+ "@telia/react-rig": "~3.2.0",
32
+ "@testing-library/dom": "~9.3.3",
33
+ "@testing-library/jest-dom": "~6.4.0",
34
+ "@testing-library/react": "~14.3.0",
35
+ "@types/node": "20.12.12",
36
+ "@types/react-dom": "^18.3.0",
37
+ "@types/react": "^18.3.3",
38
+ "eslint-plugin-testing-library": "~6.2.0",
39
+ "eslint": "^8.57.0",
40
+ "jsdom": "~22.1.0",
41
+ "lint-staged": "~10.5.3",
42
+ "prettier": "~2.8.8",
43
+ "react-dom": "^18.3.1",
44
+ "react": "^18.3.1",
45
+ "storybook": "^8.2.6",
46
+ "typescript": "^5.5.4",
47
+ "vite": "5.3.4",
48
+ "vitest": "~1.5.0",
49
+ "@purpurds/component-rig": "1.0.0"
50
+ },
51
+ "scripts": {
52
+ "build:dev": "vite",
53
+ "build:watch": "vite build --watch",
54
+ "build": "vite build",
55
+ "ci:build": "rushx build",
56
+ "coverage": "vitest run --coverage",
57
+ "lint:fix": "eslint . --fix",
58
+ "lint": "lint-staged --no-stash 2>&1",
59
+ "sbdev": "rush sbdev",
60
+ "test:unit": "vitest run --passWithNoTests",
61
+ "test:watch": "vitest --watch",
62
+ "test": "rushx test:unit",
63
+ "typecheck": "tsc -p ./tsconfig.json"
64
+ }
65
+ }
@@ -0,0 +1,13 @@
1
+ @import "@purpurds/tokens/breakpoint/variables";
2
+
3
+ .purpur-content-block-group {
4
+ display: flex;
5
+ flex-direction: column;
6
+ gap: var(--purpur-spacing-1200);
7
+ padding: var(--purpur-spacing-600) 0;
8
+
9
+ @media (min-width: $purpur-breakpoint-md) {
10
+ gap: var(--purpur-spacing-1600);
11
+ padding: var(--purpur-spacing-800) 0;
12
+ }
13
+ }
@@ -0,0 +1,56 @@
1
+ import React from "react";
2
+ import * as matchers from "@testing-library/jest-dom/matchers";
3
+ import { cleanup, render, screen } from "@testing-library/react";
4
+ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
5
+
6
+ import { ContentBlock } from "./content-block";
7
+ import { ContentBlockGroup } from "./content-block-group";
8
+
9
+ expect.extend(matchers);
10
+
11
+ const mockData = {
12
+ title: "Title goes here lorem ipsum",
13
+ usp: ["List item 1", "List item 2"],
14
+ imgUrl: "https://www.telia.se/images",
15
+ imgAltText: "test image",
16
+ ctas: [
17
+ {
18
+ href: "/test",
19
+ text: "CTA link 1",
20
+ },
21
+ {
22
+ href: "/test2",
23
+ text: "CTA link 2",
24
+ },
25
+ ],
26
+ content: "Test text content",
27
+ videoUrl: "https://www.telia.se/video.mp4",
28
+ videoPosterImgUrl: "https://www.telia.se/image.png",
29
+ };
30
+
31
+ const setup = () =>
32
+ render(
33
+ <ContentBlockGroup>
34
+ <ContentBlock title={mockData.title} usp={mockData.usp} ctas={mockData.ctas}>
35
+ {mockData.content}
36
+ </ContentBlock>
37
+ <ContentBlock title="test" headingTag="h1" usp={mockData.usp} ctas={mockData.ctas}>
38
+ {mockData.content}
39
+ </ContentBlock>
40
+ </ContentBlockGroup>
41
+ );
42
+
43
+ describe("ContentBlockGroup", () => {
44
+ beforeEach(() => {
45
+ vi.clearAllMocks();
46
+ });
47
+
48
+ afterEach(cleanup);
49
+
50
+ it("should render both content blocks and its titles", () => {
51
+ setup();
52
+
53
+ expect(screen.getByRole("heading", { level: 2, name: mockData.title }));
54
+ expect(screen.getByRole("heading", { level: 1, name: "test" }));
55
+ });
56
+ });
@@ -0,0 +1,47 @@
1
+ import React, { Children, DetailedHTMLProps, HTMLAttributes, ReactNode } from "react";
2
+ import c from "classnames/bind";
3
+
4
+ import { ContentBlockProps } from "./content-block";
5
+ import styles from "./content-block-group.module.scss";
6
+
7
+ const cx = c.bind(styles);
8
+ const rootClassName = "purpur-content-block-group";
9
+
10
+ export type ContentBlockGroupProps = {
11
+ ["data-testid"]?: string;
12
+ className?: string;
13
+ children: ReactNode;
14
+ negative?: boolean;
15
+ } & DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>;
16
+
17
+ export const ContentBlockGroup = ({
18
+ children,
19
+ className,
20
+ negative,
21
+ ["data-testid"]: dataTestId,
22
+ ...props
23
+ }: ContentBlockGroupProps) => {
24
+ const classes = cx([
25
+ className,
26
+ rootClassName,
27
+ {
28
+ [`${rootClassName}--negative`]: negative,
29
+ },
30
+ ]);
31
+
32
+ const renderChildren = () =>
33
+ Children.map(children, (child) => {
34
+ if (React.isValidElement<ContentBlockProps>(child)) {
35
+ return React.cloneElement(child, { negative });
36
+ }
37
+ return child;
38
+ });
39
+
40
+ return (
41
+ <div className={classes} data-testid={dataTestId} {...props}>
42
+ {renderChildren()}
43
+ </div>
44
+ );
45
+ };
46
+
47
+ ContentBlockGroup.displayName = "ContentBlockGroup";
@@ -0,0 +1,93 @@
1
+ @import "@purpurds/tokens/breakpoint/variables";
2
+
3
+ .purpur-content-block {
4
+ $root: &;
5
+
6
+ display: flex;
7
+ flex-direction: column;
8
+ align-items: flex-start;
9
+ gap: var(--purpur-spacing-400);
10
+
11
+ @media (min-width: $purpur-breakpoint-lg) {
12
+ align-items: center;
13
+ flex-direction: row;
14
+ gap: var(--purpur-spacing-300);
15
+
16
+ &:nth-child(even) {
17
+ flex-direction: row-reverse;
18
+ }
19
+ }
20
+
21
+ #{$root}__section {
22
+ @media (min-width: $purpur-breakpoint-lg) {
23
+ width: 50%;
24
+ }
25
+ }
26
+
27
+ #{$root}__image-wrapper {
28
+ width: 100%;
29
+ }
30
+
31
+ #{$root}__video-wrapper video,
32
+ #{$root}__image-wrapper img {
33
+ border-radius: var(--purpur-border-radius-md);
34
+
35
+ @media (min-width: $purpur-breakpoint-md) {
36
+ border-radius: var(--purpur-border-radius-lg);
37
+ }
38
+ }
39
+
40
+ #{$root}__content-wrapper {
41
+ display: flex;
42
+ flex-direction: column;
43
+ gap: var(--purpur-spacing-150);
44
+ }
45
+
46
+ #{$root}__badge {
47
+ width: fit-content;
48
+ }
49
+
50
+ #{$root}__content {
51
+ max-width: 40rem;
52
+ }
53
+
54
+ #{$root}__usp-list {
55
+ margin: 0;
56
+ padding: 0;
57
+ list-style: none;
58
+ }
59
+
60
+ #{$root}__usp-list-item {
61
+ display: flex;
62
+ align-items: center;
63
+ justify-content: left;
64
+ &:not(:last-child) {
65
+ margin-bottom: var(--purpur-spacing-100);
66
+ }
67
+ }
68
+
69
+ #{$root}__usp-list-item-icon {
70
+ margin-right: var(--purpur-spacing-50);
71
+ }
72
+
73
+ #{$root}__links {
74
+ margin-top: var(--purpur-spacing-250);
75
+ display: flex;
76
+ flex-direction: column;
77
+ gap: var(--purpur-spacing-200);
78
+
79
+ @media (min-width: $purpur-breakpoint-md) {
80
+ flex-direction: row;
81
+ }
82
+ }
83
+
84
+ &--negative {
85
+ #{$root}__text-spacing p {
86
+ color: var(--purpur-color-text-default-negative);
87
+ }
88
+
89
+ #{$root}__usp-list-item-icon svg {
90
+ fill: var(--purpur-color-text-default-negative);
91
+ }
92
+ }
93
+ }
@@ -0,0 +1,219 @@
1
+ /* eslint-disable jsx-a11y/media-has-caption */
2
+
3
+ import React from "react";
4
+ import { HeadingTag, TitleVariant } from "@purpurds/heading";
5
+ import { Paragraph } from "@purpurds/paragraph";
6
+ import type { Meta, StoryObj } from "@storybook/react";
7
+
8
+ import "@purpurds/cta-link/styles";
9
+ import "@purpurds/heading/styles";
10
+ import "@purpurds/badge/styles";
11
+ import "@purpurds/icon/styles";
12
+ import { ContentBlock } from "./content-block";
13
+ import { ContentBlockGroup as ContentBlockGroupComponent } from "./content-block-group";
14
+
15
+ const mockData = [
16
+ {
17
+ id: "1",
18
+ content:
19
+ "Body text lorem ipsum dolor sit amet consectetur. At velit mi ultricies in orci est condimentum. Et venenatis fringilla vel dictum. Diam mattis ut hac dui lacus.",
20
+ title: "Title goes here lorem ipsum",
21
+ tagline: "Badge label",
22
+ usp: ["List item 1", "List item 2", "List item 3"],
23
+ imgUrl:
24
+ "https://www.telia.se/images/i15skfqwpurk/5YYelnwdIJGush05RYsE6A/04d4eeb571bca6d5c72b557f6da92c92/Telia_Company_Reinvention_69.jpg",
25
+ altText: "Familjens unga ser på tv tillsammans mysig stämning men spännande.",
26
+ callToAction: [
27
+ {
28
+ href: "/test",
29
+ text: "CTA link text",
30
+ },
31
+ {
32
+ href: "/test2",
33
+ text: "CTA link text",
34
+ },
35
+ ],
36
+ },
37
+ {
38
+ id: "2",
39
+ content:
40
+ "Body text lorem ipsum dolor sit amet consectetur. At velit mi ultricies in orci est condimentum. Et venenatis fringilla vel dictum. Diam mattis ut hac dui lacus.",
41
+ title: "Title goes here lorem ipsum",
42
+ tagline: undefined,
43
+ imgUrl:
44
+ "https://www.telia.se/images/i15skfqwpurk/6QB5jxWQfeES4NN279kSYY/604e28cbc2fffb5e77bb0f978ec689d4/Telia_Company_071.jpg",
45
+ altText: "Manager i rutig kavaj skriver på laptop med whiteboard i bakgrunden.",
46
+ callToAction: [],
47
+ },
48
+ {
49
+ id: "3",
50
+ content:
51
+ "Body text lorem ipsum dolor sit amet consectetur. At velit mi ultricies in orci est condimentum. Et venenatis fringilla vel dictum. Diam mattis ut hac dui lacus.",
52
+ title: "Title goes here lorem ipsum",
53
+ tagline: undefined,
54
+ videoUrl:
55
+ "https://www.telia.se/videos/i15skfqwpurk/1HSDMQWf6TwfcCgtHCbi5w/f57ba932da3c3587cd1af11697ac265a/TSC_MobilVaxel_16x9_K2-2.mp4",
56
+ videoPosterImgUrl:
57
+ "https://www.telia.se/images/i15skfqwpurk/5p8TxmyWh57hZzgSoKxPmp/7177d8e471a4bef04c2526483fb84372/Telia_Smart_Connect_Video_Poster_Image.png",
58
+ callToAction: [],
59
+ },
60
+ ];
61
+
62
+ const meta = {
63
+ title: "Components/ContentBlock",
64
+ component: ContentBlock,
65
+ parameters: {
66
+ design: [
67
+ {
68
+ name: "ContentBlock",
69
+ type: "figma",
70
+ url: "https://www.figma.com/design/XEaIIFskrrxIBHMZDkIuIg/Purpur-DS---Component-library-%26-guidelines?node-id=33776-10598&t=iXwBPd5zGeNrD5Ou-0",
71
+ },
72
+ ],
73
+ },
74
+ argTypes: {
75
+ headingTag: {
76
+ control: "select",
77
+ options: Object.values(HeadingTag),
78
+ table: {
79
+ type: {
80
+ summary: Object.values(HeadingTag)
81
+ .map((x) => `"${x}"`)
82
+ .join(" | "),
83
+ },
84
+ },
85
+ },
86
+ headingVariant: {
87
+ control: "select",
88
+ options: Object.values(TitleVariant),
89
+ table: {
90
+ type: {
91
+ summary: Object.values(TitleVariant)
92
+ .map((x) => `"${x}"`)
93
+ .join(" | "),
94
+ },
95
+ },
96
+ },
97
+ },
98
+ } satisfies Meta<typeof ContentBlock>;
99
+
100
+ export default meta;
101
+ type Story = StoryObj<typeof ContentBlock>;
102
+
103
+ export const Showcase: Story = {
104
+ args: {
105
+ negative: false,
106
+ ctas: mockData[0].callToAction,
107
+ title: mockData[0].title,
108
+ children: mockData[0].content,
109
+ image: (
110
+ <img
111
+ style={{
112
+ width: "100%",
113
+ objectFit: "cover",
114
+ }}
115
+ src={mockData[0].imgUrl}
116
+ alt={mockData[0].altText || ""}
117
+ />
118
+ ),
119
+ tagline: mockData[0].tagline,
120
+ usp: mockData[0].usp,
121
+ },
122
+ render: ({ children, ...args }) => (
123
+ <div
124
+ style={{
125
+ padding: "var(--purpur-spacing-250)",
126
+ background: args.negative ? "var(--purpur-color-purple-900)" : "transparent",
127
+ }}
128
+ >
129
+ <ContentBlock {...args}>
130
+ <Paragraph negative={args.negative} variant="paragraph-100">
131
+ {children}
132
+ </Paragraph>
133
+ </ContentBlock>
134
+ </div>
135
+ ),
136
+ };
137
+
138
+ export const VideoContent: Story = {
139
+ args: {
140
+ negative: false,
141
+ ctas: mockData[0].callToAction,
142
+ title: mockData[0].title,
143
+ children: mockData[0].content,
144
+ video: (
145
+ <video
146
+ style={{ width: "100%" }}
147
+ controls
148
+ src={mockData[2].videoUrl}
149
+ poster={mockData[2].videoPosterImgUrl}
150
+ />
151
+ ),
152
+ tagline: mockData[0].tagline,
153
+ usp: mockData[0].usp,
154
+ },
155
+ render: ({ children, ...args }) => (
156
+ <div
157
+ style={{
158
+ padding: "var(--purpur-spacing-250)",
159
+ background: args.negative ? "var(--purpur-color-purple-900)" : "transparent",
160
+ }}
161
+ >
162
+ <ContentBlock {...args}>
163
+ <Paragraph negative={args.negative} variant="paragraph-100">
164
+ {children}
165
+ </Paragraph>
166
+ </ContentBlock>
167
+ </div>
168
+ ),
169
+ };
170
+
171
+ export const ContentBlockGroup: Story = {
172
+ render: ({ negative }) => (
173
+ <div
174
+ style={{
175
+ padding: "var(--purpur-spacing-250)",
176
+ background: negative ? "var(--purpur-color-purple-900)" : "transparent",
177
+ }}
178
+ >
179
+ <ContentBlockGroupComponent negative={negative}>
180
+ {mockData.map((item) => (
181
+ <ContentBlock
182
+ key={item.id}
183
+ negative={negative}
184
+ ctas={item.callToAction}
185
+ title={item.title}
186
+ tagline={item.tagline}
187
+ usp={item.usp}
188
+ image={
189
+ item.imgUrl ? (
190
+ <img
191
+ style={{
192
+ width: "100%",
193
+ objectFit: "cover",
194
+ }}
195
+ src={item.imgUrl}
196
+ alt={item.altText}
197
+ />
198
+ ) : undefined
199
+ }
200
+ video={
201
+ item.videoUrl ? (
202
+ <video
203
+ style={{ width: "100%" }}
204
+ controls
205
+ src={item.videoUrl}
206
+ poster={item.videoPosterImgUrl}
207
+ />
208
+ ) : undefined
209
+ }
210
+ >
211
+ <Paragraph negative={negative} variant="paragraph-100">
212
+ {item.content}
213
+ </Paragraph>
214
+ </ContentBlock>
215
+ ))}
216
+ </ContentBlockGroupComponent>
217
+ </div>
218
+ ),
219
+ };
@@ -0,0 +1,135 @@
1
+ /* eslint-disable jsx-a11y/media-has-caption, react/jsx-wrap-multilines */
2
+
3
+ import React from "react";
4
+ import * as matchers from "@testing-library/jest-dom/matchers";
5
+ import { cleanup, render, screen } from "@testing-library/react";
6
+ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
7
+
8
+ import { ContentBlock } from "./content-block";
9
+
10
+ expect.extend(matchers);
11
+
12
+ const mockData = {
13
+ title: "Title goes here lorem ipsum",
14
+ usp: ["List item 1", "List item 2"],
15
+ imgUrl: "https://www.telia.se/images",
16
+ imgAltText: "test image",
17
+ ctas: [
18
+ {
19
+ href: "/test",
20
+ text: "CTA link 1",
21
+ },
22
+ {
23
+ href: "/test2",
24
+ text: "CTA link 2",
25
+ },
26
+ ],
27
+ content: "Test text content",
28
+ videoUrl: "https://www.telia.se/video.mp4",
29
+ videoPosterImgUrl: "https://www.telia.se/image.png",
30
+ };
31
+
32
+ const setup = () =>
33
+ render(
34
+ <ContentBlock
35
+ title={mockData.title}
36
+ usp={mockData.usp}
37
+ image={
38
+ <img
39
+ style={{
40
+ width: "100%",
41
+ objectFit: "cover",
42
+ }}
43
+ src={mockData.imgUrl}
44
+ alt={mockData.imgAltText}
45
+ />
46
+ }
47
+ ctas={mockData.ctas}
48
+ >
49
+ {mockData.content}
50
+ </ContentBlock>
51
+ );
52
+
53
+ describe("ContentBlock", () => {
54
+ beforeEach(() => {
55
+ vi.clearAllMocks();
56
+ });
57
+
58
+ afterEach(cleanup);
59
+
60
+ it("should render title", () => {
61
+ setup();
62
+
63
+ expect(screen.getByRole("heading", { level: 2, name: mockData.title }));
64
+ });
65
+
66
+ it("should render usp list", () => {
67
+ setup();
68
+
69
+ expect(screen.getByRole("list")).toBeInTheDocument();
70
+
71
+ const listItems = screen.getAllByRole("listitem");
72
+ expect(listItems).toHaveLength(mockData.usp.length);
73
+
74
+ listItems.forEach((item, index) => {
75
+ expect(item).toHaveTextContent(mockData.usp[index]);
76
+ });
77
+ });
78
+
79
+ it("should render ctas", () => {
80
+ setup();
81
+
82
+ mockData.ctas.forEach((cta) => {
83
+ const link = screen.getByRole("link", { name: cta.text });
84
+ expect(link).toBeInTheDocument();
85
+ expect(link).toHaveAttribute("href", cta.href);
86
+ });
87
+ });
88
+
89
+ it("should render richText content", () => {
90
+ setup();
91
+
92
+ screen.getByText(mockData.content);
93
+ });
94
+
95
+ it("should render image", () => {
96
+ setup();
97
+
98
+ const img = screen.getByAltText(mockData.imgAltText);
99
+ expect(img).toBeInTheDocument();
100
+
101
+ expect(img).toHaveAttribute("src", mockData.imgUrl);
102
+ });
103
+
104
+ it("should render video", () => {
105
+ render(
106
+ <ContentBlock
107
+ title={mockData.title}
108
+ usp={mockData.usp}
109
+ ctas={mockData.ctas}
110
+ video={
111
+ <video
112
+ data-testid="content-block-video"
113
+ controls
114
+ src={mockData.videoUrl}
115
+ poster={mockData.videoPosterImgUrl}
116
+ />
117
+ }
118
+ data-testid="content-block"
119
+ >
120
+ {mockData.content}
121
+ </ContentBlock>
122
+ );
123
+
124
+ const img = screen.queryByAltText(mockData.imgAltText);
125
+ // img should not exist when video is presented
126
+ expect(img).not.toBeInTheDocument();
127
+
128
+ const video = screen.getByTestId("content-block-video");
129
+ expect(video).toBeInTheDocument();
130
+
131
+ expect(video).toHaveAttribute("src", mockData.videoUrl);
132
+
133
+ expect(video).toHaveAttribute("poster", mockData.videoPosterImgUrl);
134
+ });
135
+ });