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
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import React from 'react';
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import {
render,
screen,
fireEvent,
waitFor,
cleanup,
} from '@testing-library/react';
import { expect } from 'chai';
import sinon from 'sinon';
import type { ConnectionInfo } from 'mongodb-data-service';
Expand All @@ -13,10 +19,11 @@ for (let i = 0; i < 5; i++) {
connectionOptions: {
connectionString: `mongodb://localhost:2${5000 + i}`,
},
lastUsed: new Date(Date.now() - (Date.now() / 2) * Math.random()),
lastUsed: new Date(1647022100487 - i),
});
}
const mockConnections = [

const mockFavorites = [
{
id: 'mock-connection-atlas',
connectionOptions: {
Expand Down Expand Up @@ -58,7 +65,6 @@ const mockConnections = [
},
lastUsed: new Date(),
},
...mockRecents,
];

describe('ConnectionList Component', function () {
Expand All @@ -68,12 +74,14 @@ describe('ConnectionList Component', function () {
setActiveConnectionIdSpy = sinon.spy();
createNewConnectionSpy = sinon.spy();
});
afterEach(cleanup);
describe('when rendered', function () {
beforeEach(function () {
render(
<ConnectionList
activeConnectionId={mockConnections[2].id}
connections={mockConnections}
activeConnectionId={mockFavorites[2].id}
favoriteConnections={mockFavorites}
recentConnections={mockRecents}
createNewConnection={createNewConnectionSpy}
setActiveConnectionId={setActiveConnectionIdSpy}
removeAllRecentsConnections={() => true}
Expand All @@ -89,48 +97,31 @@ describe('ConnectionList Component', function () {

it('renders all of the connections in the lists', function () {
const listItems = screen.getAllByRole('listitem');
expect(listItems.length).to.equal(mockConnections.length);
});

it('favorites are alphabetically sorted', function () {
const listItems = screen.getAllByTestId('favorite-connection');
expect(listItems.length).to.equal(3);
expect(listItems.length).to.equal(
mockFavorites.length + mockRecents.length
);
});

it('renders the favorite connections in a list', function () {
const listItems = screen.getAllByTestId('favorite-connection-title');
expect(listItems[0].textContent).to.equal('Atlas test');
expect(listItems[1].textContent).to.equal('favorite');
expect(listItems[2].textContent).to.equal(
'super long favorite name - super long favorite name - super long favorite name - super long favorite name'
);
expect(listItems[0].textContent).to.equal(mockFavorites[0].favorite.name);
expect(listItems[1].textContent).to.equal(mockFavorites[1].favorite.name);
expect(listItems[2].textContent).to.equal(mockFavorites[2].favorite.name);
});

it('renders the recent connections in a list', function () {
const listItems = screen.getAllByTestId('recent-connection');
expect(listItems.length).to.equal(6);
});

it('renders the recent connections in most recent first order', function () {
const listItems = screen.getAllByTestId('recent-connection-description');
expect(
new Date(listItems[0].textContent).getTime()
).to.be.greaterThanOrEqual(new Date(listItems[1].textContent).getTime());
expect(
new Date(listItems[1].textContent).getTime()
).to.be.greaterThanOrEqual(new Date(listItems[2].textContent).getTime());
expect(
new Date(listItems[2].textContent).getTime()
).to.be.greaterThanOrEqual(new Date(listItems[3].textContent).getTime());
expect(listItems.length).to.equal(mockRecents.length);
});
});

describe('when new connection is clicked', function () {
beforeEach(function () {
render(
<ConnectionList
activeConnectionId={mockConnections[2].id}
connections={mockConnections}
activeConnectionId={mockFavorites[2].id}
favoriteConnections={mockFavorites}
recentConnections={mockRecents}
createNewConnection={createNewConnectionSpy}
setActiveConnectionId={setActiveConnectionIdSpy}
removeAllRecentsConnections={() => true}
Expand Down Expand Up @@ -160,8 +151,9 @@ describe('ConnectionList Component', function () {
beforeEach(function () {
render(
<ConnectionList
activeConnectionId={mockConnections[2].id}
connections={mockConnections}
activeConnectionId={mockFavorites[2].id}
favoriteConnections={mockFavorites}
recentConnections={mockRecents}
createNewConnection={createNewConnectionSpy}
setActiveConnectionId={setActiveConnectionIdSpy}
removeAllRecentsConnections={() => true}
Expand All @@ -172,7 +164,7 @@ describe('ConnectionList Component', function () {
expect(setActiveConnectionIdSpy.called).to.equal(false);

const button = screen
.getByText(mockConnections[1].favorite.name)
.getByText(mockFavorites[1].favorite.name)
.closest('button');
fireEvent(
button,
Expand All @@ -195,8 +187,9 @@ describe('ConnectionList Component', function () {
beforeEach(function () {
render(
<ConnectionList
activeConnectionId={mockConnections[2].id}
connections={mockConnections}
activeConnectionId={mockFavorites[2].id}
favoriteConnections={mockFavorites}
recentConnections={mockRecents}
createNewConnection={createNewConnectionSpy}
setActiveConnectionId={setActiveConnectionIdSpy}
removeAllRecentsConnections={() => true}
Expand All @@ -207,9 +200,7 @@ describe('ConnectionList Component', function () {
expect(setActiveConnectionIdSpy.called).to.equal(false);

const button = screen
.getByText(
mockConnections[7].connectionOptions.connectionString.substr(10)
)
.getByText(mockRecents[3].connectionOptions.connectionString.substr(10))
.closest('button');
fireEvent(
button,
Expand All @@ -233,8 +224,9 @@ describe('ConnectionList Component', function () {
removeAllRecentsConnectionsSpy = sinon.spy();
render(
<ConnectionList
activeConnectionId={mockConnections[2].id}
connections={mockConnections}
activeConnectionId={mockFavorites[2].id}
favoriteConnections={mockFavorites}
recentConnections={mockRecents}
createNewConnection={createNewConnectionSpy}
setActiveConnectionId={() => true}
removeAllRecentsConnections={removeAllRecentsConnectionsSpy}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,8 @@ export type ConnectionInfoFavorite = ConnectionInfo &

function ConnectionList({
activeConnectionId,
connections,
recentConnections,
favoriteConnections,
createNewConnection,
setActiveConnectionId,
onDoubleClick,
Expand All @@ -115,7 +116,8 @@ function ConnectionList({
removeConnection,
}: {
activeConnectionId?: string;
connections: ConnectionInfo[];
recentConnections: ConnectionInfo[];
favoriteConnections: ConnectionInfo[];
createNewConnection: () => void;
setActiveConnectionId: (connectionId: string) => void;
onDoubleClick: (connectionInfo: ConnectionInfo) => void;
Expand All @@ -124,27 +126,6 @@ function ConnectionList({
removeConnection: (connectionInfo: ConnectionInfo) => void;
}): React.ReactElement {
const [recentHeaderHover, setRecentHover] = useState(false);
const favoriteConnections = connections
.filter(
(connectionInfo): connectionInfo is ConnectionInfoFavorite =>
!!connectionInfo.favorite
)
.sort((a: ConnectionInfoFavorite, b: ConnectionInfoFavorite) => {
return b.favorite.name.toLocaleLowerCase() <
a.favorite.name.toLocaleLowerCase()
? 1
: -1;
});

const recentConnections = connections
.filter((connectionInfo) => !connectionInfo.favorite)
.sort((a, b) => {
// The `lastUsed` value hasn't always existed, so we assign
// them a date in 2016 for sorting if it isn't there.
const aLastUsed = a.lastUsed ? a.lastUsed.getTime() : 1463658247465;
const bLastUsed = b.lastUsed ? b.lastUsed.getTime() : 1463658247465;
return bLastUsed - aLastUsed;
});

return (
<Fragment>
Expand Down
31 changes: 21 additions & 10 deletions packages/compass-connections/src/components/connections.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import FormHelp from './form-help/form-help';
import Connecting from './connecting/connecting';
import { useConnections } from '../stores/connections-store';
import { cloneDeep } from 'lodash';
import ConnectionList from './connection-list/connection-list';

const { debug } = createLoggerAndTelemetry(
'mongodb-compass:connections:connections'
Expand Down Expand Up @@ -46,6 +47,9 @@ const formContainerStyles = css({
gap: spacing[4],
});

const initialSidebarWidth = spacing[4] * 10 + spacing[2]; // 248px
const minSidebarWidth = spacing[4] * 9; // 216px

function Connections({
onConnected,
connectionStorage = new ConnectionStorage(),
Expand All @@ -70,14 +74,15 @@ function Connections({
removeAllRecentsConnections,
removeConnection,
saveConnection,
favoriteConnections,
recentConnections,
} = useConnections({ onConnected, connectionStorage, connectFn, appName });
const {
activeConnectionId,
activeConnectionInfo,
connectionAttempt,
connectionErrorMessage,
connectingStatusText,
connections,
isConnected,
} = state;

Expand All @@ -89,15 +94,21 @@ function Connections({
className={connectStyles}
>
<ResizableSidebar
activeConnectionId={activeConnectionId}
connections={connections}
createNewConnection={createNewConnection}
setActiveConnectionId={setActiveConnectionById}
onConnectionDoubleClicked={connect}
removeAllRecentsConnections={removeAllRecentsConnections}
removeConnection={removeConnection}
duplicateConnection={duplicateConnection}
/>
minWidth={minSidebarWidth}
initialWidth={initialSidebarWidth}
>
<ConnectionList
activeConnectionId={activeConnectionId}
favoriteConnections={favoriteConnections}
recentConnections={recentConnections}
createNewConnection={createNewConnection}
setActiveConnectionId={setActiveConnectionById}
onDoubleClick={connect}
removeAllRecentsConnections={removeAllRecentsConnections}
removeConnection={removeConnection}
duplicateConnection={duplicateConnection}
/>
</ResizableSidebar>
<WorkspaceContainer>
<div className={formContainerStyles}>
<ErrorBoundary
Expand Down
Original file line number Diff line number Diff line change
@@ -1,84 +1,58 @@
import React, { useState } from 'react';
import React, { useCallback, useState } from 'react';
import {
ResizeHandle,
ResizeDirection,
uiColors,
css,
spacing,
} from '@mongodb-js/compass-components';
import type { ConnectionInfo } from 'mongodb-data-service';

import ConnectionList from './connection-list/connection-list';

const initialSidebarWidth = spacing[4] * 10 + spacing[2]; // 248px
const minSidebarWidth = spacing[4] * 7; // 168px

const listContainerStyles = css({
const containerStyles = css({
display: 'flex',
flexDirection: 'column',
margin: 0,
padding: 0,
maxWidth: '80%',
minWidth: minSidebarWidth,
height: '100%',
position: 'relative',
background: uiColors.gray.dark3,
color: 'white',
});

function getMaxSidebarWidth() {
return Math.max(minSidebarWidth, window.innerWidth - 100);
}

function ResizableSidebar({
activeConnectionId,
connections,
createNewConnection,
setActiveConnectionId,
onConnectionDoubleClicked,
removeAllRecentsConnections,
duplicateConnection,
removeConnection,
const ResizableSidebar = ({
initialWidth,
minWidth,
children,
}: {
activeConnectionId?: string;
connections: ConnectionInfo[];
createNewConnection: () => void;
setActiveConnectionId: (newConnectionId: string) => void;
onConnectionDoubleClicked: (connectionInfo: ConnectionInfo) => void;
removeAllRecentsConnections: () => void;
duplicateConnection: (connectionInfo: ConnectionInfo) => void;
removeConnection: (connectionInfo: ConnectionInfo) => void;
}): React.ReactElement {
const [width, setWidth] = useState(initialSidebarWidth);
initialWidth: number;
minWidth: number;
children: JSX.Element;
}): JSX.Element => {
const [width, setWidth] = useState(initialWidth);

const getMaxSidebarWidth = useCallback(() => {
return Math.max(minWidth, window.innerWidth - 100);
}, [minWidth]);

return (
<div
className={listContainerStyles}
className={containerStyles}
style={{
minWidth: width,
minWidth: minWidth,
width: width,
flex: 'none',
}}
>
<ConnectionList
activeConnectionId={activeConnectionId}
connections={connections}
createNewConnection={createNewConnection}
setActiveConnectionId={setActiveConnectionId}
onDoubleClick={onConnectionDoubleClicked}
removeAllRecentsConnections={removeAllRecentsConnections}
removeConnection={removeConnection}
duplicateConnection={duplicateConnection}
/>
{children}
<ResizeHandle
onChange={(newWidth) => setWidth(newWidth)}
direction={ResizeDirection.RIGHT}
value={width}
minValue={minSidebarWidth}
minValue={minWidth}
maxValue={getMaxSidebarWidth()}
title="sidebar"
/>
</div>
);
}
};

export default ResizableSidebar;
Loading