Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

93 changes: 77 additions & 16 deletions packages/compass-collection/src/stores/context.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,11 @@ type ContextProps = {
connectionString?: string;
};

type ContextWithAppRegistry = ContextProps & {
globalAppRegistry: AppRegistry;
localAppRegistry: AppRegistry;
};

/**
* Setup a scoped store to the collection.
*
Expand Down Expand Up @@ -115,7 +120,7 @@ const setupStore = ({
query,
aggregation,
connectionString,
}: ContextProps) => {
}: ContextWithAppRegistry) => {
const store = role.configureStore({
localAppRegistry,
globalAppRegistry,
Expand All @@ -138,7 +143,7 @@ const setupStore = ({
aggregation,
connectionString,
});
localAppRegistry?.registerStore(role.storeName, store);
localAppRegistry.registerStore(role.storeName, store);

return store;
};
Expand Down Expand Up @@ -176,7 +181,7 @@ const setupPlugin = ({
sourceName,
connectionString,
key,
}: ContextProps) => {
}: ContextWithAppRegistry) => {
const actions = role.configureActions();
const store = setupStore({
role,
Expand Down Expand Up @@ -232,7 +237,7 @@ const setupScopedModals = ({
isFLE,
sourceName,
connectionString,
}: ContextProps) => {
}: ContextWithAppRegistry) => {
const roles = globalAppRegistry?.getRole('Collection.ScopedModal');
if (roles) {
return roles.map((role: any, i: number) => {
Expand All @@ -257,6 +262,71 @@ const setupScopedModals = ({
return [];
};

/**
* Setup the query bar plugins. Need to instantiate the store and actions
* and put them in the app registry for use by all the plugins. This way
* there is only 1 query bar store per collection tab instead of one per
* plugin that uses it.
*/
const setupQueryPlugins = ({
globalAppRegistry,
localAppRegistry,
serverVersion,
state,
namespace,
isReadonly,
isTimeSeries,
isClustered,
isFLE,
query,
aggregation,
}: ContextWithAppRegistry): void => {
const queryBarRole = globalAppRegistry.getRole('Query.QueryBar')?.[0];
if (queryBarRole) {
localAppRegistry.registerRole('Query.QueryBar', queryBarRole);
const queryBarActions = setupActions(queryBarRole, localAppRegistry);
setupStore({
role: queryBarRole,
globalAppRegistry,
localAppRegistry,
dataService: state.dataService,
namespace,
serverVersion,
isReadonly,
isTimeSeries,
isClustered,
isFLE,
actions: queryBarActions,
query,
aggregation,
});
}

const queryHistoryRole = globalAppRegistry.getRole('Query.QueryHistory')?.[0];
if (process?.env?.COMPASS_SHOW_NEW_TOOLBARS === 'true' && queryHistoryRole) {
localAppRegistry.registerRole('Query.QueryHistory', queryHistoryRole);
const queryHistoryActions = setupActions(
queryHistoryRole,
localAppRegistry
);
setupStore({
role: queryHistoryRole,
globalAppRegistry,
localAppRegistry,
dataService: state.dataService,
namespace,
serverVersion,
isReadonly,
isTimeSeries,
isClustered,
isFLE,
actions: queryHistoryActions,
query,
aggregation,
});
}
};

/**
* Create the context in which a tab is created.
*
Expand Down Expand Up @@ -306,25 +376,16 @@ const createContext = ({
const views: JSX.Element[] = [];
const queryHistoryIndexes: number[] = [];

// Setup the query bar plugin. Need to instantiate the store and actions
// and put them in the app registry for use by all the plugins. This way
// there is only 1 query bar store per collection tab instead of one per
// plugin that uses it.
const queryBarRole = globalAppRegistry.getRole('Query.QueryBar')[0];
localAppRegistry.registerRole('Query.QueryBar', queryBarRole);
const queryBarActions = setupActions(queryBarRole, localAppRegistry);
setupStore({
role: queryBarRole,
setupQueryPlugins({
globalAppRegistry,
localAppRegistry,
dataService: state.dataService,
namespace,
serverVersion,
state,
namespace,
isReadonly,
isTimeSeries,
isClustered,
isFLE,
actions: queryBarActions,
query,
aggregation,
});
Expand Down
1 change: 1 addition & 0 deletions packages/compass-components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@
"@react-stately/tooltip": "^3.0.5",
"@types/lodash": "^4.14.172",
"bson": "^4.6.1",
"focus-trap-react": "^8.4.2",
"hadron-document": "^8.0.0",
"hadron-type-checker": "^7.0.0",
"lodash": "^4.17.21",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import React from 'react';
import { render, screen, cleanup } from '@testing-library/react';
import { expect } from 'chai';
import sinon from 'sinon';

import { InteractivePopover } from './interactive-popover';

const innerContentTestId = 'testing-inner-content';

function renderPopover(
props?: Partial<React.ComponentProps<typeof InteractivePopover>>
) {
const openSpy = sinon.spy();

const popoverContent = ({ onClose }) => (
<>
<button onClick={() => {}} data-testid={innerContentTestId}>
Action Button
</button>
<div>inner content</div>
<button onClick={onClose}>Close Button</button>
</>
);

return render(
<InteractivePopover
className=""
open={false}
setOpen={openSpy}
trigger={({ onClick, ref, children }) => (
<>
<button onClick={onClick} ref={ref}>
Trigger Button Text
</button>
{children}
</>
)}
{...props}
>
{popoverContent}
</InteractivePopover>
);
}

describe('InteractivePopover Component', function () {
afterEach(function () {
cleanup();
});

it('when open it should show the popover content', function () {
renderPopover({
open: true,
});
expect(screen.getByTestId(innerContentTestId)).to.be.visible;
});

it('when closed it should not show the popover content', function () {
renderPopover({
open: false,
});
expect(screen.queryByTestId(innerContentTestId)).to.not.exist;
});

it('should render the trigger', function () {
renderPopover({
open: false,
});
const button = screen.getByRole('button');
expect(button).to.be.visible;
expect(screen.getByText('Trigger Button Text')).to.be.visible;
});

it('when closed and the trigger is clicked it should call to open', function () {
const openSpy = sinon.fake();

renderPopover({
open: false,
setOpen: openSpy,
});
expect(openSpy.calledOnce).to.be.false;

const button = screen.getByText('Trigger Button Text');
button.click();
expect(openSpy.calledOnce).to.be.true;
expect(openSpy.firstCall.firstArg).to.equal(true);
});

it('when open and the trigger is clicked it should call to close', function () {
const openSpy = sinon.fake();

renderPopover({
open: true,
setOpen: openSpy,
});
expect(openSpy.calledOnce).to.be.false;

const button = screen.getByText('Trigger Button Text');
button.click();
expect(openSpy.calledOnce).to.be.true;
expect(openSpy.firstCall.firstArg).to.equal(false);
});
});
Loading