Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(boxai-sidebar): BoxAISidebar header added #3698

Merged
merged 11 commits into from
Oct 16, 2024
2 changes: 2 additions & 0 deletions i18n/en-US.properties
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,8 @@ be.contentSidebar.addTask.general = General Task
be.contentSidebar.addTask.general.description = Assignees will be responsible for marking tasks as complete
# title for general task popup
be.contentSidebar.addTask.general.title = Create General Task
# Default message for Box AI expand button in sidebar header
be.contentSidebar.boxAI.expand = Expand
# body for first-time user experience tooltip shown to new users of Box Sign
be.contentSidebar.boxSignFtuxBody = Sign documents or send signature requests, right from where your content lives
# title for first-time user experience tooltip shown to new users of Box Sign
Expand Down
17 changes: 14 additions & 3 deletions src/elements/content-sidebar/BoxAISidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import * as React from 'react';
import flow from 'lodash/flow';
import { useIntl } from 'react-intl';

import { ArrowsExpand } from '@box/blueprint-web-assets/icons/Fill';
import { IconButton } from '@box/blueprint-web';
import SidebarContent from './SidebarContent';
import { withAPIContext } from '../common/api-context';
import { withErrorBoundary } from '../common/error-boundary';
Expand All @@ -15,21 +17,30 @@ import { EVENT_JS_READY } from '../common/logger/constants';
import { mark } from '../../utils/performance';

import messages from '../common/messages';
import sidebarMessages from './messages';

const MARK_NAME_JS_READY: string = `${ORIGIN_BOXAI_SIDEBAR}_${EVENT_JS_READY}`;

mark(MARK_NAME_JS_READY);

export interface BoxAISidebarProps {
onExpandPressed: () => void;
onExpandClick: () => void;
}

function BoxAISidebar() {
function BoxAISidebar({ onExpandClick }: BoxAISidebarProps) {
const { formatMessage } = useIntl();

return (
<SidebarContent
className={'bcs-BoxAISidebar'}
actions={
<IconButton
aria-label={formatMessage(sidebarMessages.boxAISidebarExpand)}
icon={ArrowsExpand}
onClick={onExpandClick}
size="x-small"
/>
}
className="bcs-BoxAISidebar"
sidebarView={SIDEBAR_VIEW_BOXAI}
title={formatMessage(messages.sidebarBoxAITitle)}
>
Expand Down
24 changes: 23 additions & 1 deletion src/elements/content-sidebar/__tests__/BoxAISidebar.test.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,41 @@
import React from 'react';
import { userEvent } from '@testing-library/user-event';
import { screen, render } from '../../../test-utils/testing-library';
import BoxAISidebarComponent, { BoxAISidebarProps } from '../BoxAISidebar';

const mockOnExpandClick = jest.fn();

describe('elements/content-sidebar/BoxAISidebar', () => {
const renderComponent = (props = {}) => {
const defaultProps = {
onExpandPressed: jest.fn(),
onExpandClick: mockOnExpandClick,
} satisfies BoxAISidebarProps;

render(<BoxAISidebarComponent {...defaultProps} {...props} />);
};

afterEach(() => {
jest.clearAllMocks();
});

test('should render title', () => {
renderComponent();

expect(screen.getByRole('heading', { level: 3, name: 'Box AI' })).toBeInTheDocument();
});

test('should have accessible "Expand" button', () => {
renderComponent();

expect(screen.getByRole('button', { name: 'Expand' })).toBeInTheDocument();
DanilaRubleuski marked this conversation as resolved.
Show resolved Hide resolved
});

test('should call onExpandClick when click "Expand" button', async () => {
renderComponent();

const expandButton = screen.getByRole('button', { name: 'Expand' });
await userEvent.click(expandButton);

expect(mockOnExpandClick).toHaveBeenCalled();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there can be issues and unexpected behavior if we forget to clear/reset the mock calls between tests. i think we handle this in a global configuration but just in case, it's better to not use reuse the fn mock for the expect so it's more intentional about what should happen

e.g. check for a separate prop (defined in the local scope) and/or explicitly add an afterEach

afterEach(() => {
    jest.clearAllMocks();
});

// or

const onExpandClick = jest.fn();
renderComponent({ onExpandClick });

...

expect(onExpandClick).toHaveBeenCalled();

});
});
5 changes: 5 additions & 0 deletions src/elements/content-sidebar/messages.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ const messages = defineMessages({
defaultMessage: 'Tasks',
description: 'Dropdown option for filtering tasks from activity list',
},
boxAISidebarExpand: {
id: 'be.contentSidebar.boxAI.expand',
description: 'Default message for Box AI expand button in sidebar header',
defaultMessage: 'Expand',
},
boxSignFtuxBody: {
id: 'be.contentSidebar.boxSignFtuxBody',
defaultMessage: 'Sign documents or send signature requests, right from where your content lives',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { expect, within } from '@storybook/test';
import { expect, userEvent, within } from '@storybook/test';
import { type StoryObj } from '@storybook/react';
import ContentSidebar from '../../ContentSidebar';
import BoxAISidebar from '../../BoxAISidebar';
Expand All @@ -24,3 +24,12 @@ export const BoxAIInSidebar: StoryObj<typeof BoxAISidebar> = {
expect(sidebar).toBeInTheDocument();
},
};

export const BoxAIWithExpandedView: StoryObj<typeof BoxAISidebar> = {
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);

const expandButton = await canvas.findByRole('button', { name: 'Expand' }, { timeout: 5000 });
await userEvent.click(expandButton);
},
DanilaRubleuski marked this conversation as resolved.
Show resolved Hide resolved
};
Loading