Skip to content

Commit 21f35ff

Browse files
gagikkraenhansen
andauthored
feat(compass-crud): add right click menus for the CRUD toolbar COMPASS-9388 (#6996)
--------- Co-authored-by: Kræn Hansen <[email protected]>
1 parent f26d89a commit 21f35ff

File tree

2 files changed

+358
-11
lines changed

2 files changed

+358
-11
lines changed

packages/compass-crud/src/components/crud-toolbar.spec.tsx

Lines changed: 267 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import React from 'react';
22
import { expect } from 'chai';
33
import sinon from 'sinon';
44
import {
5-
fireEvent,
65
render,
76
screen,
87
cleanup,
@@ -128,7 +127,7 @@ describe('CrudToolbar Component', function () {
128127
});
129128

130129
expect(getPageSpy.called).to.be.false;
131-
fireEvent.click(screen.getByTestId('docs-toolbar-next-page-btn'));
130+
userEvent.click(screen.getByTestId('docs-toolbar-next-page-btn'));
132131

133132
expect(getPageSpy.calledOnce).to.be.true;
134133
expect(getPageSpy.firstCall.args[0]).to.equal(1);
@@ -141,7 +140,7 @@ describe('CrudToolbar Component', function () {
141140
});
142141

143142
expect(getPageSpy.called).to.be.false;
144-
fireEvent.click(screen.getByTestId('docs-toolbar-prev-page-btn'));
143+
userEvent.click(screen.getByTestId('docs-toolbar-prev-page-btn'));
145144

146145
expect(screen.getByTestId('docs-toolbar-prev-page-btn')).to.have.attribute(
147146
'aria-disabled',
@@ -164,7 +163,7 @@ describe('CrudToolbar Component', function () {
164163
end: 50,
165164
});
166165
expect(getPageSpy.called).to.be.false;
167-
fireEvent.click(screen.getByTestId('docs-toolbar-next-page-btn'));
166+
userEvent.click(screen.getByTestId('docs-toolbar-next-page-btn'));
168167

169168
expect(
170169
screen.getByTestId('docs-toolbar-next-page-btn')
@@ -184,7 +183,7 @@ describe('CrudToolbar Component', function () {
184183
end: 25,
185184
});
186185
expect(getPageSpy.called).to.be.false;
187-
fireEvent.click(screen.getByTestId('docs-toolbar-next-page-btn'));
186+
userEvent.click(screen.getByTestId('docs-toolbar-next-page-btn'));
188187

189188
expect(
190189
screen.getByTestId('docs-toolbar-next-page-btn')
@@ -209,7 +208,7 @@ describe('CrudToolbar Component', function () {
209208
);
210209

211210
expect(getPageSpy.called).to.be.false;
212-
fireEvent.click(screen.getByTestId('docs-toolbar-prev-page-btn'));
211+
userEvent.click(screen.getByTestId('docs-toolbar-prev-page-btn'));
213212

214213
expect(getPageSpy.calledOnce).to.be.true;
215214
expect(getPageSpy.firstCall.args[0]).to.equal(0);
@@ -226,7 +225,7 @@ describe('CrudToolbar Component', function () {
226225
});
227226

228227
expect(getPageSpy.called).to.be.false;
229-
fireEvent.click(screen.getByTestId('docs-toolbar-next-page-btn'));
228+
userEvent.click(screen.getByTestId('docs-toolbar-next-page-btn'));
230229

231230
expect(screen.getByTestId('docs-toolbar-next-page-btn')).to.have.attribute(
232231
'aria-disabled',
@@ -248,7 +247,7 @@ describe('CrudToolbar Component', function () {
248247
expect(nextButton).to.have.attribute('aria-disabled', 'false');
249248

250249
expect(getPageSpy.called).to.be.false;
251-
fireEvent.click(nextButton);
250+
userEvent.click(nextButton);
252251

253252
expect(getPageSpy.calledOnce).to.be.true;
254253
expect(getPageSpy.firstCall.args[0]).to.equal(3);
@@ -295,8 +294,8 @@ describe('CrudToolbar Component', function () {
295294
});
296295

297296
expect(exportSpy.called).to.be.false;
298-
fireEvent.click(screen.getByText('Export Data'));
299-
fireEvent.click(screen.getByText('Export the full collection'));
297+
userEvent.click(screen.getByText('Export Data'));
298+
userEvent.click(screen.getByText('Export the full collection'));
300299

301300
expect(exportSpy.calledOnce).to.be.true;
302301
expect(exportSpy.firstCall.args[0]).to.be.true;
@@ -527,4 +526,262 @@ describe('CrudToolbar Component', function () {
527526
expect(stub).to.be.calledWithExactly(75);
528527
});
529528
});
529+
530+
describe('context menu', function () {
531+
beforeEach(async function () {
532+
await preferences.savePreferences({ enableImportExport: true });
533+
});
534+
535+
it('should open context menu on right click', function () {
536+
renderCrudToolbar();
537+
538+
const toolbar = screen.getByTestId('query-bar').closest('div');
539+
userEvent.click(toolbar!, { button: 2 });
540+
541+
const contextMenu = screen.getByTestId('context-menu');
542+
expect(within(contextMenu).getByText('Expand all documents')).to.be
543+
.visible;
544+
expect(within(contextMenu).getByText('Refresh')).to.be.visible;
545+
});
546+
547+
it('should call onExpandAllClicked when "Expand all documents" is clicked', function () {
548+
const onExpandAllClicked = sinon.spy();
549+
renderCrudToolbar({ onExpandAllClicked });
550+
551+
const toolbar = screen.getByTestId('query-bar').closest('div');
552+
userEvent.click(toolbar!, { button: 2 });
553+
554+
const contextMenu = screen.getByTestId('context-menu');
555+
const expandMenuItem = within(contextMenu).getByText(
556+
'Expand all documents'
557+
);
558+
userEvent.click(expandMenuItem);
559+
560+
expect(onExpandAllClicked).to.have.been.calledOnce;
561+
});
562+
563+
it('should call onCollapseAllClicked when "Collapse all documents" is clicked', function () {
564+
const onCollapseAllClicked = sinon.spy();
565+
renderCrudToolbar({ onCollapseAllClicked });
566+
567+
const toolbar = screen.getByTestId('query-bar').closest('div');
568+
userEvent.click(toolbar!, { button: 2 });
569+
570+
const contextMenu = screen.getByTestId('context-menu');
571+
const collapseMenuItem = within(contextMenu).getByText(
572+
'Collapse all documents'
573+
);
574+
userEvent.click(collapseMenuItem);
575+
576+
expect(onCollapseAllClicked).to.have.been.called;
577+
});
578+
579+
it('should call insertDataHandler with "import-file" when "Import JSON or CSV file" is clicked', function () {
580+
const insertDataHandler = sinon.spy();
581+
renderCrudToolbar({ insertDataHandler });
582+
583+
const toolbar = screen.getByTestId('query-bar').closest('div');
584+
userEvent.click(toolbar!, { button: 2 });
585+
586+
const contextMenu = screen.getByTestId('context-menu');
587+
const importMenuItem = within(contextMenu).getByText(
588+
'Import JSON or CSV file'
589+
);
590+
userEvent.click(importMenuItem);
591+
592+
expect(insertDataHandler).to.have.been.calledOnceWithExactly(
593+
'import-file'
594+
);
595+
});
596+
597+
it('should call insertDataHandler with "insert-document" when "Insert document..." is clicked', function () {
598+
const insertDataHandler = sinon.spy();
599+
renderCrudToolbar({ insertDataHandler });
600+
601+
const toolbar = screen.getByTestId('query-bar').closest('div');
602+
userEvent.click(toolbar!, { button: 2 });
603+
604+
const contextMenu = screen.getByTestId('context-menu');
605+
const insertMenuItem =
606+
within(contextMenu).getByText('Insert document...');
607+
userEvent.click(insertMenuItem);
608+
609+
expect(insertDataHandler).to.have.been.calledOnceWithExactly(
610+
'insert-document'
611+
);
612+
});
613+
614+
it('should call openExportFileDialog with false when "Export query results..." is clicked', function () {
615+
const openExportFileDialog = sinon.spy();
616+
renderCrudToolbar({ openExportFileDialog });
617+
618+
const toolbar = screen.getByTestId('query-bar').closest('div');
619+
userEvent.click(toolbar!, { button: 2 });
620+
621+
const contextMenu = screen.getByTestId('context-menu');
622+
const exportQueryMenuItem = within(contextMenu).getByText(
623+
'Export query results...'
624+
);
625+
userEvent.click(exportQueryMenuItem);
626+
627+
expect(openExportFileDialog).to.have.been.calledOnceWithExactly(false);
628+
});
629+
630+
it('should call openExportFileDialog with true when "Export full collection..." is clicked', function () {
631+
const openExportFileDialog = sinon.spy();
632+
renderCrudToolbar({ openExportFileDialog });
633+
634+
const toolbar = screen.getByTestId('query-bar').closest('div');
635+
userEvent.click(toolbar!, { button: 2 });
636+
637+
const contextMenu = screen.getByTestId('context-menu');
638+
const exportCollectionMenuItem = within(contextMenu).getByText(
639+
'Export full collection...'
640+
);
641+
userEvent.click(exportCollectionMenuItem);
642+
643+
expect(openExportFileDialog).to.have.been.calledOnceWithExactly(true);
644+
});
645+
646+
it('should call onUpdateButtonClicked when "Bulk update" is clicked', function () {
647+
const onUpdateButtonClicked = sinon.spy();
648+
renderCrudToolbar({ onUpdateButtonClicked });
649+
650+
const toolbar = screen.getByTestId('query-bar').closest('div');
651+
userEvent.click(toolbar!, { button: 2 });
652+
653+
const contextMenu = screen.getByTestId('context-menu');
654+
const updateMenuItem = within(contextMenu).getByText('Bulk update');
655+
userEvent.click(updateMenuItem);
656+
657+
expect(onUpdateButtonClicked).to.have.been.calledOnce;
658+
});
659+
660+
it('should call onDeleteButtonClicked when "Bulk delete" is clicked', function () {
661+
const onDeleteButtonClicked = sinon.spy();
662+
renderCrudToolbar({ onDeleteButtonClicked });
663+
664+
const toolbar = screen.getByTestId('query-bar').closest('div');
665+
userEvent.click(toolbar!, { button: 2 });
666+
667+
const contextMenu = screen.getByTestId('context-menu');
668+
const deleteMenuItem = within(contextMenu).getByText('Bulk delete');
669+
userEvent.click(deleteMenuItem);
670+
671+
expect(onDeleteButtonClicked).to.have.been.calledOnce;
672+
});
673+
674+
it('should call refreshDocuments when "Refresh" is clicked', function () {
675+
const refreshDocuments = sinon.spy();
676+
renderCrudToolbar({ refreshDocuments });
677+
678+
const toolbar = screen.getByTestId('query-bar').closest('div');
679+
userEvent.click(toolbar!, { button: 2 });
680+
681+
const contextMenu = screen.getByTestId('context-menu');
682+
const refreshMenuItem = within(contextMenu).getByText('Refresh');
683+
userEvent.click(refreshMenuItem);
684+
685+
expect(refreshDocuments).to.have.been.calledOnce;
686+
});
687+
688+
describe('conditional menu items', function () {
689+
it('should not show import/export items when enableImportExport is false', async function () {
690+
await preferences.savePreferences({ enableImportExport: false });
691+
renderCrudToolbar();
692+
693+
const toolbar = screen.getByTestId('query-bar').closest('div');
694+
userEvent.click(toolbar!, { button: 2 });
695+
696+
const contextMenu = screen.getByTestId('context-menu');
697+
expect(within(contextMenu).queryByText('Import JSON or CSV file')).to
698+
.not.exist;
699+
expect(within(contextMenu).queryByText('Export query results...')).to
700+
.not.exist;
701+
expect(within(contextMenu).queryByText('Export full collection...')).to
702+
.not.exist;
703+
});
704+
705+
it('should not show insert document item when readonly is true', function () {
706+
renderCrudToolbar({ readonly: true });
707+
708+
const toolbar = screen.getByTestId('query-bar').closest('div');
709+
userEvent.click(toolbar!, { button: 2 });
710+
711+
const contextMenu = screen.getByTestId('context-menu');
712+
expect(within(contextMenu).queryByText('Insert document...')).to.not
713+
.exist;
714+
});
715+
716+
it('should not show bulk operations when readonly is true', function () {
717+
renderCrudToolbar({ readonly: true });
718+
719+
const toolbar = screen.getByTestId('query-bar').closest('div');
720+
userEvent.click(toolbar!, { button: 2 });
721+
722+
const contextMenu = screen.getByTestId('context-menu');
723+
expect(within(contextMenu).queryByText('Bulk update')).to.not.exist;
724+
expect(within(contextMenu).queryByText('Bulk delete')).to.not.exist;
725+
});
726+
727+
it('should not show bulk operations when isWritable is false', function () {
728+
renderCrudToolbar({ isWritable: false });
729+
730+
const toolbar = screen.getByTestId('query-bar').closest('div');
731+
userEvent.click(toolbar!, { button: 2 });
732+
733+
const contextMenu = screen.getByTestId('context-menu');
734+
expect(within(contextMenu).queryByText('Bulk update')).to.not.exist;
735+
expect(within(contextMenu).queryByText('Bulk delete')).to.not.exist;
736+
});
737+
738+
it('should not show bulk operations when query has skip', function () {
739+
renderCrudToolbar({ querySkip: 10 });
740+
741+
const toolbar = screen.getByTestId('query-bar').closest('div');
742+
userEvent.click(toolbar!, { button: 2 });
743+
744+
const contextMenu = screen.getByTestId('context-menu');
745+
expect(within(contextMenu).queryByText('Bulk update')).to.not.exist;
746+
});
747+
748+
it('should not show bulk operations when query has limit', function () {
749+
renderCrudToolbar({ queryLimit: 10 });
750+
751+
const toolbar = screen.getByTestId('query-bar').closest('div');
752+
userEvent.click(toolbar!, { button: 2 });
753+
754+
const contextMenu = screen.getByTestId('context-menu');
755+
expect(within(contextMenu).queryByText('Bulk update')).to.not.exist;
756+
expect(within(contextMenu).queryByText('Bulk delete')).to.not.exist;
757+
});
758+
759+
it('should show all applicable items when conditions are met', function () {
760+
renderCrudToolbar({
761+
readonly: false,
762+
isWritable: true,
763+
querySkip: 0,
764+
queryLimit: 0,
765+
});
766+
767+
const toolbar = screen.getByTestId('query-bar').closest('div');
768+
userEvent.click(toolbar!, { button: 2 });
769+
770+
const contextMenu = screen.getByTestId('context-menu');
771+
expect(within(contextMenu).getByText('Expand all documents')).to.be
772+
.visible;
773+
expect(within(contextMenu).getByText('Import JSON or CSV file')).to.be
774+
.visible;
775+
expect(within(contextMenu).getByText('Insert document...')).to.be
776+
.visible;
777+
expect(within(contextMenu).getByText('Export query results...')).to.be
778+
.visible;
779+
expect(within(contextMenu).getByText('Export full collection...')).to.be
780+
.visible;
781+
expect(within(contextMenu).getByText('Bulk update')).to.be.visible;
782+
expect(within(contextMenu).getByText('Bulk delete')).to.be.visible;
783+
expect(within(contextMenu).getByText('Refresh')).to.be.visible;
784+
});
785+
});
786+
});
530787
});

0 commit comments

Comments
 (0)