Skip to content
Merged
Show file tree
Hide file tree
Changes from 16 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.

1 change: 1 addition & 0 deletions packages/compass-global-writes/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
"@mongodb-js/compass-logging": "^1.4.8",
"@mongodb-js/compass-telemetry": "^1.2.0",
"hadron-app-registry": "^9.2.7",
"lodash": "^4.17.21",
"@mongodb-js/compass-field-store": "^9.18.1",
"mongodb-ns": "^2.4.2",
"react": "^17.0.2",
Expand Down
16 changes: 8 additions & 8 deletions packages/compass-global-writes/src/components/index.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,25 @@ import { GlobalWrites } from './index';
import { renderWithStore } from './../../tests/create-store';

describe('Compass GlobalWrites Plugin', function () {
it('renders plugin in NOT_READY state', function () {
renderWithStore(<GlobalWrites shardingStatus={'NOT_READY'} />);
it('renders plugin in NOT_READY state', async function () {
await renderWithStore(<GlobalWrites shardingStatus={'NOT_READY'} />);
expect(screen.getByText(/loading/i)).to.exist;
});

it('renders plugin in UNSHARDED state', function () {
renderWithStore(<GlobalWrites shardingStatus={'UNSHARDED'} />);
it('renders plugin in UNSHARDED state', async function () {
await renderWithStore(<GlobalWrites shardingStatus={'UNSHARDED'} />);
expect(screen.getByTestId('shard-collection-button')).to.exist;
});

it('renders plugin in SUBMITTING_FOR_SHARDING state', function () {
renderWithStore(
it('renders plugin in SUBMITTING_FOR_SHARDING state', async function () {
await renderWithStore(
<GlobalWrites shardingStatus={'SUBMITTING_FOR_SHARDING'} />
);
expect(screen.getByTestId('shard-collection-button')).to.exist;
});

it('renders plugin in SHARDING state', function () {
renderWithStore(<GlobalWrites shardingStatus={'SHARDING'} />);
it('renders plugin in SHARDING state', async function () {
await renderWithStore(<GlobalWrites shardingStatus={'SHARDING'} />);
expect(screen.getByText(/sharding your collection/i)).to.exist;
});
});
8 changes: 8 additions & 0 deletions packages/compass-global-writes/src/components/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import type { RootState, ShardingStatus } from '../store/reducer';
import { ShardingStatuses } from '../store/reducer';
import UnshardedState from './states/unsharded';
import ShardingState from './states/sharding';
import ShardKeyCorrect from './states/shard-key-correct';

const containerStyles = css({
paddingLeft: spacing[400],
Expand Down Expand Up @@ -58,6 +59,13 @@ function ShardingStateView({
return <ShardingState />;
}

if (
shardingStatus === ShardingStatuses.SHARD_KEY_CORRECT ||
shardingStatus === ShardingStatuses.UNMANAGING_NAMESPACE
) {
return <ShardKeyCorrect />;
}

return null;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import React from 'react';
import { expect } from 'chai';
import { render, screen, within } from '@mongodb-js/testing-library-compass';
import { ShardZonesTable } from './shard-zones-table';
import { type ShardZoneData } from '../store/reducer';

describe('Compass GlobalWrites Plugin', function () {
const shardZones: ShardZoneData[] = [
{
zoneId: '45893084',
country: 'Germany',
readableName: 'Germany',
isoCode: 'DE',
typeOneIsoCode: 'DE',
zoneName: 'EMEA',
zoneLocations: ['Frankfurt'],
},
{
zoneId: '43829408',
country: 'Germany',
readableName: 'Germany - Berlin',
isoCode: 'DE-BE',
typeOneIsoCode: 'DE',
zoneName: 'EMEA',
zoneLocations: ['Frankfurt'],
},
];

it('renders the Location name & Zone for all items', function () {
render(<ShardZonesTable shardZones={shardZones} />);

const rows = screen.getAllByRole('row');
expect(rows).to.have.lengthOf(3); // 1 header, 2 items
expect(within(rows[1]).getByText('Germany (DE)')).to.be.visible;
expect(within(rows[1]).getByText('EMEA (Frankfurt)')).to.be.visible;
expect(within(rows[2]).getByText('Germany - Berlin (DE-BE)')).to.be.visible;
expect(within(rows[2]).getByText('EMEA (Frankfurt)')).to.be.visible;
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import React from 'react';
import {
Table,
TableBody,
TableHead,
HeaderRow,
HeaderCell,
Row,
Cell,
css,
} from '@mongodb-js/compass-components';
import type { ShardZoneData } from '../store/reducer';

const containerStyles = css({
maxWidth: '700px',
height: '400px',
});

export function ShardZonesTable({
shardZones,
}: {
shardZones: ShardZoneData[];
}) {
return (
// TODO(COMPASS-8336):
// Add search
// group zones by ShardZoneData.typeOneIsoCode
// and display them in a single row that can be expanded
<Table className={containerStyles} title="Zone Mapping">
<TableHead isSticky>
<HeaderRow>
<HeaderCell>Location Name</HeaderCell>
<HeaderCell>Zone</HeaderCell>
</HeaderRow>
</TableHead>
<TableBody>
{shardZones.map(
({ readableName, zoneName, zoneLocations, isoCode }, index) => {
return (
<Row key={index}>
<Cell>
{readableName} ({isoCode})
</Cell>
<Cell>
{zoneName} ({zoneLocations.join(', ')})
</Cell>
</Row>
);
}
)}
</TableBody>
</Table>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
import React from 'react';
import { expect } from 'chai';
import { screen, userEvent } from '@mongodb-js/testing-library-compass';
import {
ShardKeyCorrect,
type ShardKeyCorrectProps,
} from './shard-key-correct';
import { type ShardZoneData } from '../../store/reducer';
import Sinon from 'sinon';
import { renderWithStore } from '../../../tests/create-store';
import { type ConnectionInfo } from '@mongodb-js/compass-connections/provider';

describe('Compass GlobalWrites Plugin', function () {
const shardZones: ShardZoneData[] = [
{
zoneId: '45893084',
country: 'Germany',
readableName: 'Germany',
isoCode: 'DE',
typeOneIsoCode: 'DE',
zoneName: 'EMEA',
zoneLocations: ['Frankfurt'],
},
];

const baseProps: ShardKeyCorrectProps = {
shardZones,
namespace: 'db1.coll1',
shardKey: {
fields: [
{ type: 'HASHED', name: 'location' },
{ type: 'RANGE', name: 'secondary' },
],
isUnique: false,
},
isUnmanagingNamespace: false,
onUnmanageNamespace: () => {},
};

function renderWithProps(
props?: Partial<ShardKeyCorrectProps>,
options?: Parameters<typeof renderWithStore>[1]
) {
return renderWithStore(
<ShardKeyCorrect {...baseProps} {...props} />,
options
);
}

it('Provides button to unmanage', async function () {
const onUnmanageNamespace = Sinon.spy();
await renderWithProps({ onUnmanageNamespace });

const btn = await screen.findByRole<HTMLButtonElement>('button', {
name: /Unmanage collection/,
});
expect(btn).to.be.visible;

userEvent.click(btn);

expect(onUnmanageNamespace).to.have.been.calledOnce;
});

it('Unmanage btn is disabled when the action is in progress', async function () {
const onUnmanageNamespace = Sinon.spy();
await renderWithProps({ onUnmanageNamespace, isUnmanagingNamespace: true });

const btn = await screen.findByTestId<HTMLButtonElement>(
'shard-collection-button'
);
expect(btn).to.be.visible;
expect(btn.getAttribute('aria-disabled')).to.equal('true');

userEvent.click(btn);

expect(onUnmanageNamespace).not.to.have.been.called;
});

it('Provides link to Edit Configuration', async function () {
const connectionInfo = {
id: 'testConnection',
connectionOptions: {
connectionString: 'mongodb://test',
},
atlasMetadata: {
projectId: 'project1',
clusterName: 'myCluster',
} as ConnectionInfo['atlasMetadata'],
};
await renderWithProps(undefined, {
connectionInfo,
});

const link = await screen.findByRole('link', {
name: /Edit Configuration/,
});
const expectedHref = `/v2/${connectionInfo.atlasMetadata?.projectId}/clusters/edit/${connectionInfo.atlasMetadata?.clusterName}`;

expect(link).to.be.visible;
expect(link).to.have.attribute('href', expectedHref);
});

it('Describes the shardKey', async function () {
await renderWithProps();

const title = await screen.findByTestId('shardkey-description-title');
expect(title).to.be.visible;
expect(title.textContent).to.equal(
`${baseProps.namespace} is configured with the following shard key:`
);
const list = await screen.findByTestId('shardkey-description-content');
expect(list).to.be.visible;
expect(list.textContent).to.contain(`"location", "secondary"`);
});

it('Contains sample codes', async function () {
await renderWithProps();

const findingDocumentsSample = await screen.findByTestId(
'sample-finding-documents'
);
expect(findingDocumentsSample).to.be.visible;
expect(findingDocumentsSample.textContent).to.contain(
`use db1db["coll1"].find({"location": "US-NY", "secondary": "<id_value>"})`
);

const insertingDocumentsSample = await screen.findByTestId(
'sample-inserting-documents'
);
expect(insertingDocumentsSample).to.be.visible;
expect(insertingDocumentsSample.textContent).to.contain(
`use db1db["coll1"].insertOne({"location": "US-NY", "secondary": "<id_value>",...<other fields>})`
);
});
});
Loading