/* eslint-disable @typescript-eslint/no-empty-function */
import React from 'react';
import {
render,
screen,
cleanup,
within,
waitFor,
} from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { expect } from 'chai';
import Sinon from 'sinon';
import { DatabasesNavigationTree } from './databases-navigation-tree';
import preferencesAccess from 'compass-preferences-model';
const databases = [
{
_id: 'foo',
name: 'foo',
collectionsStatus: 'initial',
collectionsLength: 5,
collections: [],
},
{
_id: 'bar',
name: 'bar',
collectionsStatus: 'ready',
collectionsLength: 3,
collections: [
{ _id: 'bar.meow', name: 'meow', type: 'collection' },
{ _id: 'bar.woof', name: 'woof', type: 'timeseries' },
{ _id: 'bar.bwok', name: 'bwok', type: 'view' },
],
},
];
const TEST_VIRTUAL_PROPS = {
__TEST_REACT_AUTOSIZER_DEFAULT_WIDTH: 1024,
__TEST_REACT_AUTOSIZER_DEFAULT_HEIGHT: 768,
__TEST_REACT_WINDOW_OVERSCAN: Infinity,
};
describe('DatabasesNavigationTree', function () {
afterEach(cleanup);
context('when the rename collection feature flag is enabled', () => {
const sandbox = Sinon.createSandbox();
before(() => {
sandbox.stub(preferencesAccess, 'getPreferences').returns({
enableRenameCollectionModal: true,
} as any);
});
after(() => sandbox.restore());
it('shows the Rename Collection action', function () {
render(
{}}
onNamespaceAction={() => {}}
{...TEST_VIRTUAL_PROPS}
>
);
const collection = screen.getByTestId('sidebar-collection-bar.meow');
const showActionsButton = within(collection).getByTitle('Show actions');
expect(within(collection).getByTitle('Show actions')).to.exist;
userEvent.click(showActionsButton);
expect(screen.getByText('Rename collection')).to.exist;
});
it('should activate callback with `rename-collection` when corresponding action is clicked', function () {
const spy = Sinon.spy();
render(
{}}
{...TEST_VIRTUAL_PROPS}
>
);
const collection = screen.getByTestId('sidebar-collection-bar.meow');
userEvent.click(within(collection).getByTitle('Show actions'));
userEvent.click(screen.getByText('Rename collection'));
expect(spy).to.be.calledOnceWithExactly('bar.meow', 'rename-collection');
});
});
it('should render databases', function () {
render(
{}}
onNamespaceAction={() => {}}
{...TEST_VIRTUAL_PROPS}
>
);
expect(screen.getByText('foo')).to.exist;
expect(screen.getByText('bar')).to.exist;
});
it('should render collections when database is expanded', function () {
render(
{}}
onNamespaceAction={() => {}}
{...TEST_VIRTUAL_PROPS}
>
);
expect(screen.getByText('meow')).to.exist;
expect(screen.getByText('woof')).to.exist;
expect(screen.getByText('bwok')).to.exist;
});
it('should render collection placeholders when database is expanded but collections are not ready', function () {
render(
{}}
onNamespaceAction={() => {}}
{...TEST_VIRTUAL_PROPS}
>
);
expect(screen.getAllByTestId('placeholder')).to.have.lengthOf(5);
});
it('should make current active namespace tabbable', async function () {
render(
{}}
onNamespaceAction={() => {}}
{...TEST_VIRTUAL_PROPS}
>
);
userEvent.tab();
await waitFor(() => {
// Virtual list will be the one to grab the focus first, but will
// immediately forward it to the element and mocking raf here breaks
// virtual list implementatin, waitFor is to accomodate for that
expect(document.querySelector('[data-id="bar"]')).to.eq(
document.activeElement
);
return true;
});
});
describe('when isReadOnly is false or undefined', function () {
it('should show all database actions on hover', function () {
render(
{}}
onNamespaceAction={() => {}}
{...TEST_VIRTUAL_PROPS}
>
);
userEvent.hover(screen.getByText('foo'));
const database = screen.getByTestId('sidebar-database-foo');
expect(within(database).getByTitle('Create collection')).to.exist;
expect(within(database).getByTitle('Drop database')).to.exist;
});
it('should show all database actions for active namespace', function () {
render(
{}}
onNamespaceAction={() => {}}
{...TEST_VIRTUAL_PROPS}
>
);
const database = screen.getByTestId('sidebar-database-bar');
expect(within(database).getByTitle('Create collection')).to.exist;
expect(within(database).getByTitle('Drop database')).to.exist;
});
it('should show all collection actions', function () {
render(
{}}
onNamespaceAction={() => {}}
{...TEST_VIRTUAL_PROPS}
>
);
const collection = screen.getByTestId('sidebar-collection-bar.meow');
const showActionsButton = within(collection).getByTitle('Show actions');
expect(within(collection).getByTitle('Show actions')).to.exist;
userEvent.click(showActionsButton);
expect(screen.getByText('Open in new tab')).to.exist;
expect(() => screen.getByText('Rename collection')).to.throw;
expect(screen.getByText('Drop collection')).to.exist;
});
it('should show all view actions', function () {
render(
{}}
onNamespaceAction={() => {}}
{...TEST_VIRTUAL_PROPS}
>
);
const collection = screen.getByTestId('sidebar-collection-bar.bwok');
const showActionsButton = within(collection).getByTitle('Show actions');
expect(within(collection).getByTitle('Show actions')).to.exist;
userEvent.click(showActionsButton);
expect(screen.getByText('Open in new tab')).to.exist;
expect(screen.getByText('Drop view')).to.exist;
expect(screen.getByText('Duplicate view')).to.exist;
expect(screen.getByText('Modify view')).to.exist;
// views cannot be renamed
expect(() => screen.getByText('Rename collection')).to.throw;
});
});
describe('when isReadOnly is true', function () {
it('should not show database actions', function () {
render(
{}}
onNamespaceAction={() => {}}
isReadOnly
{...TEST_VIRTUAL_PROPS}
>
);
const database = screen.getByTestId('sidebar-database-bar');
expect(() => within(database).getByTitle('Create collection')).to.throw;
expect(() => within(database).getByTitle('Drop database')).to.throw;
});
it('should show only one collection action', function () {
render(
{}}
onNamespaceAction={() => {}}
isReadOnly
{...TEST_VIRTUAL_PROPS}
>
);
const collection = screen.getByTestId('sidebar-collection-bar.bwok');
expect(within(collection).getByTitle('Open in new tab')).to.exist;
});
});
describe('onNamespaceAction', function () {
it('should activate callback with `select-database` when database is clicked', function () {
const spy = Sinon.spy();
render(
{}}
{...TEST_VIRTUAL_PROPS}
>
);
userEvent.click(screen.getByText('foo'));
expect(spy).to.be.calledOnceWithExactly('foo', 'select-database');
});
it('should activate callback with `select-collection` when collection is clicked', function () {
const spy = Sinon.spy();
render(
{}}
{...TEST_VIRTUAL_PROPS}
>
);
userEvent.click(screen.getByText('meow'));
expect(spy).to.be.calledOnceWithExactly('bar.meow', 'select-collection');
});
describe('database actions', function () {
it('should activate callback with `drop-database` when corresponding action is clicked', function () {
const spy = Sinon.spy();
render(
{}}
{...TEST_VIRTUAL_PROPS}
>
);
userEvent.click(screen.getByTitle('Drop database'));
expect(spy).to.be.calledOnceWithExactly('foo', 'drop-database');
});
it('should activate callback with `create-collection` when corresponding action is clicked', function () {
const spy = Sinon.spy();
render(
{}}
{...TEST_VIRTUAL_PROPS}
>
);
userEvent.click(screen.getByTitle('Create collection'));
expect(spy).to.be.calledOnceWithExactly('foo', 'create-collection');
});
});
describe('collection actions', function () {
it('should activate callback with `open-in-new-tab` when corresponding action is clicked', function () {
const spy = Sinon.spy();
render(
{}}
{...TEST_VIRTUAL_PROPS}
>
);
const collection = screen.getByTestId('sidebar-collection-bar.meow');
userEvent.click(within(collection).getByTitle('Show actions'));
userEvent.click(screen.getByText('Open in new tab'));
expect(spy).to.be.calledOnceWithExactly('bar.meow', 'open-in-new-tab');
});
it('should activate callback with `drop-collection` when corresponding action is clicked', function () {
const spy = Sinon.spy();
render(
{}}
{...TEST_VIRTUAL_PROPS}
>
);
const collection = screen.getByTestId('sidebar-collection-bar.meow');
userEvent.click(within(collection).getByTitle('Show actions'));
userEvent.click(screen.getByText('Drop collection'));
expect(spy).to.be.calledOnceWithExactly('bar.meow', 'drop-collection');
});
});
describe('view actions', function () {
it('should activate callback with `duplicate-view` when corresponding action is clicked', function () {
const spy = Sinon.spy();
render(
{}}
{...TEST_VIRTUAL_PROPS}
>
);
const view = screen.getByTestId('sidebar-collection-bar.bwok');
userEvent.click(within(view).getByTitle('Show actions'));
userEvent.click(screen.getByText('Duplicate view'));
expect(spy).to.be.calledOnceWithExactly('bar.bwok', 'duplicate-view');
});
it('should activate callback with `modify-view` when corresponding action is clicked', function () {
const spy = Sinon.spy();
render(
{}}
{...TEST_VIRTUAL_PROPS}
>
);
const view = screen.getByTestId('sidebar-collection-bar.bwok');
userEvent.click(within(view).getByTitle('Show actions'));
userEvent.click(screen.getByText('Modify view'));
expect(spy).to.be.calledOnceWithExactly('bar.bwok', 'modify-view');
});
});
});
});