Skip to content

Commit 0f35f6a

Browse files
authored
Merge pull request #252 from rebeccaalpert/sources-tests
Get tests up to ~20%
2 parents 64332cd + 4c97fc7 commit 0f35f6a

27 files changed

+1007
-42
lines changed

jest.config.js

+12-9
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ module.exports = {
55
verbose: true,
66
coverageDirectory: './coverage/',
77
collectCoverage: true,
8+
// most of these are to fix https://github.com/remarkjs/react-markdown/issues/635
89
transformIgnorePatterns: [
9-
'node_modules/(?!@patternfly|@data-driven-forms)',
10-
10+
'node_modules/(?!@patternfly|@data-driven-forms|react-syntax-highlighter|remark-gfm|react-markdown|remark-parse|devlop|hast-util-to-jsx-runtime|comma-separated-tokens|estree-util-is-identifier-name|hast-util-whitespace|property-information|space-separated-tokens|unist-util-position|vfile-message|unist-util-stringify-position|html-url-attributes|mdast-util-from-markdown|mdast-util-to-string|micromark|decode-named-character-reference|remark-rehype|mdast-util-to-hast|trim-lines|unist-util-visit|unist-util-is|unified|bail|is-plain-obj|trough|vfile|mdast-util-gfm|ccount|mdast-util-find-and-replace|escape-string-regexp|markdown-table|mdast-util-to-markdown|zwitch|longest-streak|mdast-util-phrasing)'
1111
// Uncomment the below line if you face any errors with jest
1212
// '/node_modules/(?!@redhat-cloud-services)',
1313
],
@@ -17,14 +17,15 @@ module.exports = {
1717
'!<rootDir>/packages/**/index.js',
1818
'!<rootDir>/packages/**/*{c|C}ontext*.js',
1919
'!<rootDir>/packages/components/src/Components/Table/*',
20+
'<rootDir>/packages/**/src/**/*.tsx'
2021
],
21-
setupFilesAfterEnv: [ '<rootDir>/config/setupTests.js', 'jest-canvas-mock' ],
22+
setupFilesAfterEnv: ['<rootDir>/config/setupTests.js', 'jest-canvas-mock'],
2223
testEnvironment: 'jsdom',
2324
testEnvironmentOptions: {
24-
url: 'http://localhost:5000/',
25+
url: 'http://localhost:5000/'
2526
},
26-
setupFiles: [ './jest.setup.js' ],
27-
roots: [ '<rootDir>/packages/' ],
27+
setupFiles: ['./jest.setup.js'],
28+
roots: ['<rootDir>/packages/'],
2829
// modulePathIgnorePatterns: ['<rootDir>/packages/create-crc-app/templates', '<rootDir>/packages/docs/.cache'],
2930
modulePathIgnorePatterns: [
3031
'<rootDir>/packages/*.*/dist/*.*',
@@ -37,11 +38,13 @@ module.exports = {
3738
customReact: 'react',
3839
reactRedux: 'react-redux',
3940
PFReactCore: '@patternfly/react-core',
40-
PFReactTable: '@patternfly/react-table',
41+
PFReactTable: '@patternfly/react-table'
4142
},
4243
globalSetup: '<rootDir>/config/globalSetup.js',
4344
transform: {
4445
'^.+\\.jsx?$': 'babel-jest',
45-
'^.+\\.tsx?$': [ 'ts-jest', { tsconfig: './packages/module/tsconfig.json', } ],
46-
},
46+
'^.+\\.tsx?$': ['ts-jest', { tsconfig: './packages/module/tsconfig.json' }],
47+
// Ensure ES modules are transformed
48+
'^.+\\.js$': 'babel-jest'
49+
}
4750
};

packages/module/patternfly-docs/content/extensions/virtual-assistant/examples/ChatbotMessage/MessageWithAttachment.tsx

+4
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ export const AttachmentMenuExample: React.FunctionComponent = () => {
2424
setIsEditModalOpen(false);
2525
setIsPreviewModalOpen(true);
2626
}}
27+
onAttachmentClose={(id: string) => {
28+
// eslint-disable-next-line no-console
29+
console.log(`Closed attachment id ${id}`);
30+
}}
2731
/>
2832
{currentModalData && (
2933
<PreviewAttachment

packages/module/src/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ export const ChatbotConversationHistoryNav: React.FunctionComponent<ChatbotConve
184184
const onEscape = (event: React.KeyboardEvent) => {
185185
if (event.key === 'Escape') {
186186
// prevents using escape key on menu buttons from closing the panel, but I'm not sure if this is allowed
187-
if ('type' in event.target && event.target.type !== 'button') {
187+
if (event.target instanceof HTMLInputElement && event.target.type !== 'button') {
188188
setIsDrawerOpen(false);
189189
}
190190
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import React from 'react';
2+
import { render, screen } from '@testing-library/react';
3+
import '@testing-library/jest-dom';
4+
import ChatbotWelcomePrompt from './ChatbotWelcomePrompt';
5+
import userEvent from '@testing-library/user-event';
6+
7+
describe('ChatbotWelcomePrompt', () => {
8+
it('should render welcome prompt', () => {
9+
const { container } = render(
10+
<ChatbotWelcomePrompt title="Hello, Chatbot User" description="How may I help you today?" />
11+
);
12+
expect(container).toMatchSnapshot();
13+
});
14+
15+
it('should render correctly', () => {
16+
render(<ChatbotWelcomePrompt title="Hello, Chatbot User" description="How may I help you today?" />);
17+
expect(screen.getByText('Hello, Chatbot User')).toBeTruthy();
18+
expect(screen.getByText('How may I help you today?')).toBeTruthy();
19+
});
20+
it('should render prompts with titles correctly', () => {
21+
render(
22+
<ChatbotWelcomePrompt
23+
title="Hello, Chatbot User"
24+
description="How may I help you today?"
25+
prompts={[{ title: 'Topic 1' }]}
26+
/>
27+
);
28+
expect(screen.getByText('Topic 1')).toBeTruthy();
29+
});
30+
it('should render prompts with messages correctly', () => {
31+
render(
32+
<ChatbotWelcomePrompt
33+
title="Hello, Chatbot User"
34+
description="How may I help you today?"
35+
prompts={[{ title: 'Topic 1', message: 'Helpful prompt for Topic 1' }]}
36+
/>
37+
);
38+
expect(screen.getByText('Helpful prompt for Topic 1')).toBeTruthy();
39+
});
40+
it('should render prompts with onClick correctly', async () => {
41+
const spy = jest.fn();
42+
render(
43+
<ChatbotWelcomePrompt
44+
title="Hello, Chatbot User"
45+
description="How may I help you today?"
46+
prompts={[{ title: 'Topic 1', message: 'Helpful prompt for Topic 1', onClick: spy }]}
47+
/>
48+
);
49+
await userEvent.click(screen.getByRole('button', { name: /Topic 1/i }));
50+
expect(spy).toHaveBeenCalled();
51+
});
52+
it('should apply className appropriately', () => {
53+
render(
54+
<ChatbotWelcomePrompt
55+
title="Hello, Chatbot User"
56+
description="How may I help you today?"
57+
className="test"
58+
testId="welcome-prompt"
59+
/>
60+
);
61+
const element = screen.getByTestId('welcome-prompt');
62+
expect(element).toHaveClass('test');
63+
});
64+
});

packages/module/src/ChatbotWelcomePrompt/ChatbotWelcomePrompt.tsx

+7-4
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,15 @@ export interface ChatbotWelcomePromptProps extends React.HTMLProps<HTMLDivElemen
1414
prompts?: WelcomePrompt[];
1515
/** Custom classname for the WelcomePrompt component */
1616
className?: string;
17+
/** Custom test id for the WelcomePrompt component */
18+
testId?: string;
1719
}
1820

1921
export interface WelcomePrompt {
2022
/** Message for the welcome prompt */
21-
message: string;
23+
message?: string;
2224
/** Title for the welcome prompt */
23-
title?: string;
25+
title: string;
2426
/** Callback handler for the onClick event for welcome prompt */
2527
onClick?: () => void;
2628
}
@@ -30,9 +32,10 @@ export const ChatbotWelcomePrompt: React.FunctionComponent<ChatbotWelcomePromptP
3032
description,
3133
prompts,
3234
className,
35+
testId,
3336
...props
3437
}: ChatbotWelcomePromptProps) => (
35-
<div className={`pf-chatbot--layout--welcome ${className ?? ''}`} {...props}>
38+
<div data-testid={testId} className={`pf-chatbot--layout--welcome ${className ?? ''}`} {...props}>
3639
<Content component={ContentVariants.h1}>
3740
<span className="pf-chatbot__hello">{title}</span>
3841
<br />
@@ -51,7 +54,7 @@ export const ChatbotWelcomePrompt: React.FunctionComponent<ChatbotWelcomePromptP
5154
>
5255
<CardTitle id={`welcome-prompt-title-${index}`}>{prompt.title}</CardTitle>
5356
</CardHeader>
54-
<CardBody>{prompt.message}</CardBody>
57+
{prompt.message && <CardBody>{prompt.message}</CardBody>}
5558
</Card>
5659
))}
5760
</div>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`ChatbotWelcomePrompt should render welcome prompt 1`] = `
4+
<div>
5+
<div
6+
class="pf-chatbot--layout--welcome "
7+
>
8+
<h1
9+
class="pf-v6-c-content--h1"
10+
data-ouia-component-id="OUIA-Generated-Content-1"
11+
data-ouia-component-type="PF6/Content"
12+
data-ouia-safe="true"
13+
data-pf-content="true"
14+
>
15+
<span
16+
class="pf-chatbot__hello"
17+
>
18+
Hello, Chatbot User
19+
</span>
20+
<br />
21+
<span
22+
class="pf-chatbot__question"
23+
>
24+
How may I help you today?
25+
</span>
26+
</h1>
27+
<div
28+
class="pf-chatbot__prompt-suggestions"
29+
/>
30+
</div>
31+
</div>
32+
`;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import React from 'react';
2+
import { render, screen } from '@testing-library/react';
3+
import '@testing-library/jest-dom';
4+
import FileDetails from './FileDetails';
5+
6+
describe('FileDetails', () => {
7+
it('should render file details', () => {
8+
const { container } = render(<FileDetails fileName="test.txt" />);
9+
expect(container).toMatchSnapshot();
10+
});
11+
12+
it('should render file details correctly if an extension we support is passed in', () => {
13+
render(<FileDetails fileName="test.txt" languageTestId="language" />);
14+
expect(screen.getByText('test')).toBeTruthy();
15+
expect(screen.getByText('TEXT')).toBeTruthy();
16+
expect(screen.getByTestId('language')).toBeTruthy();
17+
});
18+
it('should skip language if we do not support an extension', () => {
19+
render(<FileDetails fileName="test.joke" languageTestId="language" />);
20+
expect(screen.getByText('test')).toBeTruthy();
21+
expect(screen.queryByTestId('language')).toBeFalsy();
22+
});
23+
});

packages/module/src/FileDetails/FileDetails.tsx

+8-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import path from 'path-browserify';
44
interface FileDetailsProps {
55
/** Name of file, including extension */
66
fileName: string;
7+
/** Custom test id for the component-generated language */
8+
languageTestId?: string;
79
}
810

911
// source https://gist.github.com/ppisarczyk/43962d06686722d26d176fad46879d41
@@ -932,7 +934,7 @@ export const extensionToLanguage = {
932934
pdf: 'PDF'
933935
};
934936

935-
export const FileDetails = ({ fileName }: PropsWithChildren<FileDetailsProps>) => {
937+
export const FileDetails = ({ fileName, languageTestId }: PropsWithChildren<FileDetailsProps>) => {
936938
const language = extensionToLanguage[path.extname(fileName).slice(1)]?.toUpperCase();
937939
return (
938940
<Flex gap={{ default: 'gapSm' }}>
@@ -964,7 +966,11 @@ export const FileDetails = ({ fileName }: PropsWithChildren<FileDetailsProps>) =
964966
<StackItem>
965967
<span className="pf-chatbot__code-fileName">{path.parse(fileName).name}</span>
966968
</StackItem>
967-
{language && <StackItem className="pf-chatbot__code-language">{language}</StackItem>}
969+
{language && (
970+
<StackItem data-testid={languageTestId} className="pf-chatbot__code-language">
971+
{language}
972+
</StackItem>
973+
)}
968974
</Stack>
969975
</Flex>
970976
);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`FileDetails should render file details 1`] = `
4+
<div>
5+
<div
6+
class="pf-v6-l-flex pf-m-gap-sm"
7+
>
8+
<div
9+
class="pf-v6-l-flex pf-m-align-items-center pf-m-align-self-center pf-m-justify-content-center pf-chatbot__code-icon"
10+
>
11+
<svg
12+
fill="currentColor"
13+
height="24"
14+
viewBox="0 0 24 24"
15+
width="24"
16+
xmlns="http://www.w3.org/2000/svg"
17+
>
18+
<path
19+
d="M0 4C0 1.79086 1.79086 0 4 0H20C22.2091 0 24 1.79086 24 4V20C24 22.2091 22.2091 24 20 24H4C1.79086 24 0 22.2091 0 20V4Z"
20+
fill="currentColor"
21+
/>
22+
<g
23+
clip-path="url(#clip0_3280_27505)"
24+
>
25+
<path
26+
d="M13.8204 5.63002C13.3954 5.50752 12.9529 5.75502 12.8304 6.18002L9.63035 17.38C9.50785 17.805 9.75535 18.2475 10.1804 18.37C10.6054 18.4925 11.0479 18.245 11.1704 17.82L14.3704 6.62002C14.4929 6.19502 14.2454 5.75252 13.8204 5.63002ZM15.8354 8.63252C15.5229 8.94502 15.5229 9.45252 15.8354 9.76502L18.0679 12L15.8329 14.235C15.5204 14.5475 15.5204 15.055 15.8329 15.3675C16.1454 15.68 16.6529 15.68 16.9654 15.3675L19.7654 12.5675C20.0779 12.255 20.0779 11.7475 19.7654 11.435L16.9654 8.63502C16.6529 8.32252 16.1454 8.32252 15.8329 8.63502L15.8354 8.63252ZM8.16785 8.63252C7.85535 8.32002 7.34785 8.32002 7.03535 8.63252L4.23535 11.4325C3.92285 11.745 3.92285 12.2525 4.23535 12.565L7.03535 15.365C7.34785 15.6775 7.85535 15.6775 8.16785 15.365C8.48035 15.0525 8.48035 14.545 8.16785 14.2325L5.93285 12L8.16785 9.76502C8.48035 9.45252 8.48035 8.94502 8.16785 8.63252Z"
27+
fill="white"
28+
/>
29+
</g>
30+
<defs>
31+
<clippath>
32+
<rect
33+
fill="white"
34+
height="12.8"
35+
transform="translate(4 5.60001)"
36+
width="16"
37+
/>
38+
</clippath>
39+
</defs>
40+
</svg>
41+
</div>
42+
<div
43+
class="pf-v6-l-stack"
44+
>
45+
<div
46+
class="pf-v6-l-stack__item"
47+
>
48+
<span
49+
class="pf-chatbot__code-fileName"
50+
>
51+
test
52+
</span>
53+
</div>
54+
<div
55+
class="pf-v6-l-stack__item pf-chatbot__code-language"
56+
>
57+
TEXT
58+
</div>
59+
</div>
60+
</div>
61+
</div>
62+
`;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import React from 'react';
2+
import { render, screen } from '@testing-library/react';
3+
import '@testing-library/jest-dom';
4+
import FileDetailsLabel from './FileDetailsLabel';
5+
import userEvent from '@testing-library/user-event';
6+
7+
describe('FileDetailsLabel', () => {
8+
it('should render file details label', () => {
9+
const { container } = render(<FileDetailsLabel fileName="test.txt" />);
10+
expect(container).toMatchSnapshot();
11+
});
12+
it('should render file details correctly if an extension we support is passed in', () => {
13+
render(<FileDetailsLabel fileName="test.txt" />);
14+
expect(screen.getByText('test')).toBeTruthy();
15+
expect(screen.getByText('TEXT')).toBeTruthy();
16+
});
17+
it('should skip language if we do not support an extension', () => {
18+
render(<FileDetailsLabel fileName="test.joke" languageTestId="language" />);
19+
expect(screen.getByText('test')).toBeTruthy();
20+
expect(screen.queryByTestId('language')).toBeFalsy();
21+
});
22+
it('should not show spinner by default', () => {
23+
render(<FileDetailsLabel fileName="test.txt" spinnerTestId="spinner" />);
24+
expect(screen.queryByTestId('spinner')).toBeFalsy();
25+
});
26+
it('should show spinner if loading', () => {
27+
render(<FileDetailsLabel fileName="test.txt" isLoading spinnerTestId="spinner" />);
28+
expect(screen.getByText('test')).toBeTruthy();
29+
expect(screen.getByText('TEXT')).toBeTruthy();
30+
expect(screen.queryByTestId('spinner')).toBeTruthy();
31+
});
32+
it('should call onClick prop', async () => {
33+
const spy = jest.fn();
34+
render(<FileDetailsLabel fileName="test.txt" onClick={spy} />);
35+
await userEvent.click(screen.getByRole('button'));
36+
expect(spy).toHaveBeenCalledTimes(1);
37+
});
38+
it('should call onClose prop', async () => {
39+
const spy = jest.fn();
40+
render(<FileDetailsLabel fileName="test.txt" onClose={spy} />);
41+
await userEvent.click(screen.getByRole('button', { name: /Close test.txt/i }));
42+
expect(spy).toHaveBeenCalledTimes(1);
43+
});
44+
it('should use closeButtonAriaLabel prop appropriately', () => {
45+
render(<FileDetailsLabel fileName="test.txt" onClose={jest.fn()} closeButtonAriaLabel="Delete file" />);
46+
screen.getByRole('button', { name: /Delete file/i });
47+
});
48+
});

0 commit comments

Comments
 (0)