Skip to content

Commit

Permalink
Extract ExportAnnotations component
Browse files Browse the repository at this point in the history
- Add basic tests
  • Loading branch information
lyzadanger committed Jul 26, 2023
1 parent c5e8702 commit b1ddafb
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 65 deletions.
34 changes: 34 additions & 0 deletions src/sidebar/components/ShareDialog/ExportAnnotations.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { Button, CardActions, Input } from '@hypothesis/frontend-shared';

import { useSidebarStore } from '../../store';
import LoadingSpinner from './LoadingSpinner';

/**
* Render content for "export" tab panel
*/
export default function ExportAnnotations() {
const store = useSidebarStore();
const group = store.focusedGroup();
const exportReady = group && !store.isLoading();
const annotations = store.allAnnotations();

if (!exportReady) {
return <LoadingSpinner />;
}

// TODO: Handle 0 annotations
return (
<>
<p>
Export <strong>{annotations.length} annotations</strong> in a file
named:
</p>
<Input id="export-filename" value="filename-tbd-export.json" />
<CardActions>
<Button variant="primary" disabled>
Export
</Button>
</CardActions>
</>
);
}
42 changes: 2 additions & 40 deletions src/sidebar/components/ShareDialog/ShareDialog.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import {
Button,
Card,
CardActions,
CopyIcon,
IconButton,
Input,
Expand All @@ -18,6 +16,7 @@ import { useSidebarStore } from '../../store';
import { copyText } from '../../util/copy-to-clipboard';
import ShareLinks from '../ShareLinks';
import SidebarPanel from '../SidebarPanel';
import ExportAnnotations from './ExportAnnotations';
import LoadingSpinner from './LoadingSpinner';
import TabHeader from './TabHeader';
import TabPanel from './TabPanel';
Expand Down Expand Up @@ -110,38 +109,6 @@ function SharePanelContent({
);
}

type ExportPanelContentProps = {
loading: boolean;
annotationCount: number;
};

/**
* Render content for "export" tab panel
*/
function ExportPanelContent({
loading,
annotationCount,
}: ExportPanelContentProps) {
if (loading) {
return <LoadingSpinner />;
}

// TODO: Handle 0 annotations
return (
<>
<p>
Export <strong>{annotationCount} annotations</strong> in a file named:
</p>
<Input id="export-filename" value="filename-tbd-export.json" />
<CardActions>
<Button variant="primary" disabled>
Export
</Button>
</CardActions>
</>
);
}

export type ShareDialogProps = {
// injected
toastMessenger: ToastMessengerService;
Expand All @@ -160,7 +127,6 @@ function ShareDialog({ toastMessenger }: ShareDialogProps) {
const focusedGroup = store.focusedGroup();
const groupName = (focusedGroup && focusedGroup.name) || '...';
const panelTitle = `Share Annotations in ${groupName}`;
const allAnnotations = store.allAnnotations();

const tabbedDialog = store.isFeatureEnabled('export_annotations');
const [selectedTab, setSelectedTab] = useState<'share' | 'export'>('share');
Expand All @@ -169,7 +135,6 @@ function ShareDialog({ toastMessenger }: ShareDialogProps) {
// be available
const sharingReady = focusedGroup && mainFrame;
// Show a loading spinner in the export tab if annotations are loading
const exportReady = focusedGroup && !store.isLoading();

const shareURI =
sharingReady && pageSharingLink(mainFrame.uri, focusedGroup.id);
Expand Down Expand Up @@ -237,10 +202,7 @@ function ShareDialog({ toastMessenger }: ShareDialogProps) {
aria-labelledby="export-panel-tab"
title={`Export from ${focusedGroup?.name ?? '...'}`}
>
<ExportPanelContent
annotationCount={allAnnotations.length}
loading={!exportReady}
/>
<ExportAnnotations />
</TabPanel>
</Card>
</>
Expand Down
68 changes: 68 additions & 0 deletions src/sidebar/components/ShareDialog/test/ExportAnnotations-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { mount } from 'enzyme';

import { checkAccessibility } from '../../../../test-util/accessibility';
import { mockImportedComponents } from '../../../../test-util/mock-imported-components';
import ExportAnnotations from '../ExportAnnotations';
import { $imports } from '../ExportAnnotations';

describe('ExportAnnotations', () => {
let fakeStore;

const fakePrivateGroup = {
type: 'private',
name: 'Test Private Group',
id: 'testprivate',
};

const createComponent = props => mount(<ExportAnnotations {...props} />);

beforeEach(() => {
fakeStore = {
allAnnotations: sinon.stub().returns(0),
focusedGroup: sinon.stub().returns(fakePrivateGroup),
isLoading: sinon.stub().returns(false),
};

$imports.$mock(mockImportedComponents());

$imports.$mock({
'../../store': { useSidebarStore: () => fakeStore },
});
});

afterEach(() => {
$imports.$restore();
});

context('export annotations not ready', () => {
it('renders a loading spinner if there is no focused group', () => {
fakeStore.focusedGroup.returns(null);

const wrapper = createComponent();

assert.isTrue(wrapper.find('LoadingSpinner').exists());
});

it('renders a loading spinner if annotations are loading', () => {
fakeStore.isLoading.returns(true);

const wrapper = createComponent();

assert.isTrue(wrapper.find('LoadingSpinner').exists());
});
});

it('provides a filename field', () => {
// TODO expand as component logic is implemented
const wrapper = createComponent();

assert.isTrue(wrapper.find('Input').exists());
});

it(
'should pass a11y checks',
checkAccessibility({
content: () => createComponent(),
})
);
});
26 changes: 1 addition & 25 deletions src/sidebar/components/ShareDialog/test/ShareDialog-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ describe('ShareDialog', () => {
};

$imports.$mock(mockImportedComponents());
// Don't mock these simple components for now
// Don't mock these related components for now
$imports.$restore({
'./LoadingSpinner': true,
'./TabHeader': true,
Expand Down Expand Up @@ -246,7 +246,6 @@ describe('ShareDialog', () => {
.find('TabPanel')
.filter({ active: true });
assert.equal(activeTabPanel.props().id, 'export-panel');
assert.isTrue(activeTabPanel.find('Input').exists());

// Now, reselect share tab
act(() => {
Expand All @@ -260,29 +259,6 @@ describe('ShareDialog', () => {
const shareTabPanel = wrapper.find('TabPanel').filter({ active: true });
assert.equal(shareTabPanel.props().id, 'share-panel');
});

it('shows a loading indicator on the export tab if not ready', () => {
const wrapper = createComponent();
const exportTabSelector = 'Tab[aria-controls="export-panel"]';
fakeStore.isLoading.returns(true);

act(() => {
wrapper
.find(exportTabSelector)
.getDOMNode()
.dispatchEvent(new Event('click'));
});
wrapper.update();

const activeTabPanel = wrapper
.find('TabPanel')
.filter({ active: true });
assert.equal(activeTabPanel.props().id, 'export-panel');
assert.isFalse(activeTabPanel.find('Input').exists());
assert.isTrue(
activeTabPanel.find('[data-testid="loading-spinner"]').exists()
);
});
});
});

Expand Down

0 comments on commit b1ddafb

Please sign in to comment.