Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: adds a new overview screen based on LeafyGreen components VSCODE-485 #617

Merged
merged 10 commits into from
Dec 1, 2023
Merged
35,920 changes: 21,005 additions & 14,915 deletions package-lock.json

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -979,6 +979,7 @@
"@iconify-icons/codicon": "^1.2.25",
"@iconify/react": "^1.1.4",
"@leafygreen-ui/logo": "^8.0.4",
"@mongodb-js/compass-components": "^1.19.0",
"@mongodb-js/mongodb-constants": "^0.7.1",
"@mongosh/browser-runtime-electron": "^2.0.2",
"@mongosh/i18n": "^2.0.2",
Expand Down Expand Up @@ -1047,6 +1048,7 @@
"chalk": "^4.1.2",
"cli-ux": "^5.6.7",
"cross-env": "^7.0.3",
"crypto-browserify": "^3.12.0",
"css-loader": "^6.8.1",
"depcheck": "^1.4.3",
"download": "^8.0.0",
Expand All @@ -1056,6 +1058,7 @@
"eslint-config-mongodb-js": "^5.0.3",
"eslint-plugin-mocha": "^10.1.0",
"execa": "^1.0.0",
"fork-ts-checker-webpack-plugin": "^9.0.2",
"glob": "^7.2.3",
"jest": "^26.6.3",
"jest-junit": "^12.3.0",
Expand All @@ -1071,6 +1074,7 @@
"node-loader": "^0.6.0",
"npm-run-all": "^4.1.5",
"ora": "^5.4.1",
"path-browserify": "^1.0.1",
"postcss-loader": "^7.3.3",
"pre-commit": "^1.2.2",
"prettier": "^2.8.8",
Expand Down
1 change: 1 addition & 0 deletions src/mdbExtensionController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -696,5 +696,6 @@ export default class MDBExtensionController implements vscode.Disposable {
this._playgroundController.deactivate();
this._telemetryService.deactivate();
this._editorsController.deactivate();
this._webviewController.deactivate();
}
}
2 changes: 1 addition & 1 deletion src/test/suite/views/webview-app/app.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@ describe('App Component Test Suite', () => {
test('it renders the new overview page when useNewConnectionForm is truthy', () => {
sinon.stub(featureFlags, 'getFeatureFlag').returns(true);
render(<App />);
expect(() => screen.getAllByTestId('legacy-app')).to.throw;
expect(screen.queryByTestId('legacy-app')).to.be.null;
});
});
44 changes: 44 additions & 0 deletions src/test/suite/views/webview-app/atlas-cta.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import React from 'react';
import { cleanup, render, screen } from '@testing-library/react';
import AtlasCta from '../../../../views/webview-app/atlas-cta';
import { expect } from 'chai';
import Sinon from 'sinon';
import vscode from '../../../../views/webview-app/vscode-api';
import { MESSAGE_TYPES } from '../../../../views/webview-app/extension-app-message-constants';

describe('AtlasCta test suite', function () {
afterEach(function () {
cleanup();
Sinon.restore();
});

test('it should render Atlas CTA', function () {
render(<AtlasCta />);
expect(screen.getByText('Create free cluster')).to.not.be.null;
expect(screen.getByTestId('link-atlas')).to.not.be.null;
});

test('it should track clicks on MongoDB Atlas link', function () {
const postMessageStub = Sinon.stub(vscode, 'postMessage');
render(<AtlasCta />);
screen.getByTestId('link-atlas').click();
expect(postMessageStub).to.be.calledWithExactly({
command: MESSAGE_TYPES.EXTENSION_LINK_CLICKED,
screen: 'overviewPage',
linkId: 'atlasLanding',
});
});

test('when clicked on "Create free cluster" button, it should open create account page on atlas and also track the link', function () {
const postMessageStub = Sinon.stub(vscode, 'postMessage');
render(<AtlasCta />);
screen.getByText('Create free cluster').click();
expect(postMessageStub).calledTwice;
expect(postMessageStub.firstCall.args[0].command).to.equal(
MESSAGE_TYPES.OPEN_TRUSTED_LINK
);
expect(postMessageStub.secondCall.args[0].command).to.equal(
MESSAGE_TYPES.EXTENSION_LINK_CLICKED
);
});
});
29 changes: 29 additions & 0 deletions src/test/suite/views/webview-app/connect-helper.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import React from 'react';
import { expect } from 'chai';
import { render, screen } from '@testing-library/react';
import ConnectHelper from '../../../../views/webview-app/connect-helper';
import Sinon from 'sinon';
import vscode from '../../../../views/webview-app/vscode-api';
import { MESSAGE_TYPES } from '../../../../views/webview-app/extension-app-message-constants';

describe('ConnectHelper test suite', function () {
test('when rendered it should show both connection options', function () {
render(<ConnectHelper />);
expect(screen.getByLabelText('Connect with connection string')).to.not.be
.null;
expect(screen.getByLabelText('Open connection form')).to.not.be.null;
});

test('when connecting with string, it should call vscode to open connection string input', function () {
const postMessageStub = Sinon.stub(vscode, 'postMessage');
render(<ConnectHelper />);
screen.getByLabelText('Connect with connection string').click();
expect(postMessageStub).to.have.been.calledWithExactly({
command: MESSAGE_TYPES.OPEN_CONNECTION_STRING_INPUT,
});
});

test.skip('when clicked on open connection form, it should open connection form', function () {
// TODO(VSCODE-488)
});
});
124 changes: 124 additions & 0 deletions src/test/suite/views/webview-app/connection-status.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
import Sinon from 'sinon';
import { expect } from 'chai';
import * as React from 'react';
import { act, cleanup, render, screen } from '@testing-library/react';
import ConnectionStatus from '../../../../views/webview-app/connection-status';
import {
CONNECTION_STATUS,
MESSAGE_TYPES,
} from '../../../../views/webview-app/extension-app-message-constants';
import vscode from '../../../../views/webview-app/vscode-api';

describe('ConnectionStatus test suite', function () {
afterEach(function () {
cleanup();
Sinon.restore();
});

test('it should show a loading status by default', function () {
render(<ConnectionStatus />);
expect(screen.getByText('Loading...')).to.not.be.null;
});

test('it should periodically request connection status', function () {
const postMessageStub = Sinon.stub(vscode, 'postMessage');
render(<ConnectionStatus />);
expect(postMessageStub).to.have.been.calledWithExactly({
command: MESSAGE_TYPES.GET_CONNECTION_STATUS,
});
});

describe('when GET_CONNECTION_STATUS gets responded with a disconnecting state', function () {
test('it should show a disconnecting status', function () {
render(<ConnectionStatus />);
act(() => {
window.dispatchEvent(
new MessageEvent('message', {
data: {
command: MESSAGE_TYPES.CONNECTION_STATUS_MESSAGE,
connectionStatus: CONNECTION_STATUS.DISCONNECTING,
activeConnectionName: '',
},
})
);
});
expect(screen.getByText('Disconnecting...')).to.not.be.null;
});
});

describe('when GET_CONNECTION_STATUS gets responded with a disconnected state', function () {
test('it should show a disconnected status', function () {
render(<ConnectionStatus />);
act(() => {
window.dispatchEvent(
new MessageEvent('message', {
data: {
command: MESSAGE_TYPES.CONNECTION_STATUS_MESSAGE,
connectionStatus: CONNECTION_STATUS.DISCONNECTED,
activeConnectionName: '',
},
})
);
});
expect(screen.getByText('Not connected.')).to.not.be.null;
});
});

describe('when GET_CONNECTION_STATUS gets responded with a connecting state', function () {
test('it should show a connecting status', function () {
render(<ConnectionStatus />);
act(() => {
window.dispatchEvent(
new MessageEvent('message', {
data: {
command: MESSAGE_TYPES.CONNECTION_STATUS_MESSAGE,
connectionStatus: CONNECTION_STATUS.CONNECTING,
activeConnectionName: '',
},
})
);
});
expect(screen.getByText('Connecting...')).to.not.be.null;
});
});

describe('when GET_CONNECTION_STATUS gets responded with a connected state', function () {
beforeEach(function () {
render(<ConnectionStatus />);
act(() => {
window.dispatchEvent(
new MessageEvent('message', {
data: {
command: MESSAGE_TYPES.CONNECTION_STATUS_MESSAGE,
connectionStatus: CONNECTION_STATUS.CONNECTED,
activeConnectionName: 'vscode-connection',
},
})
);
});
});

test('it should show a connected status', function () {
expect(screen.getByText('Connected to:')).to.not.be.null;
expect(screen.getByText('vscode-connection')).to.not.be.null;
});

test('it should allow editing the name of the connection', function () {
const postMessageStub = Sinon.stub(vscode, 'postMessage');
screen.getByLabelText('Rename connection').click();

expect(postMessageStub).to.be.calledWithExactly({
command: MESSAGE_TYPES.RENAME_ACTIVE_CONNECTION,
});
});

test('it should allow creating new playground', function () {
const postMessageStub = Sinon.stub(vscode, 'postMessage');
screen.getByLabelText('Create playground').click();

expect(postMessageStub).to.be.calledWithExactly({
command: MESSAGE_TYPES.CREATE_NEW_PLAYGROUND,
});
});
});
});
2 changes: 2 additions & 0 deletions src/test/suite/views/webview-app/jest-setup.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

const Enzyme = require('enzyme');
const Adapter = require('@wojtekmaj/enzyme-adapter-react-17');
const chai = require('chai');
chai.use(require('sinon-chai'));
Enzyme.configure({ adapter: new Adapter() });

// eslint-disable-next-line no-undef
Expand Down
29 changes: 29 additions & 0 deletions src/test/suite/views/webview-app/overview-page.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import React from 'react';
import { expect } from 'chai';
import { cleanup, render, screen } from '@testing-library/react';
import OverviewPage from '../../../../views/webview-app/overview-page';

describe('OverviewPage test suite', function () {
afterEach(cleanup);
test('it should render OverviewPage', function () {
render(<OverviewPage />);
expect(
screen.getByText(
'Navigate your databases and collections, use playgrounds for exploring and transforming your data'
)
).to.exist;
});

test('on click of resources, it should open resources panel', function () {
render(<OverviewPage />);
screen.getByText('Resources').click();
expect(screen.getByText('Product overview')).to.exist;
});

test('on click of close button on resources panel, it should close resources panel', function () {
render(<OverviewPage />);
screen.getByText('Resources').click();
screen.getByLabelText('Close').click();
expect(screen.queryByText('Product overview')).to.be.null;
});
});
67 changes: 67 additions & 0 deletions src/test/suite/views/webview-app/resources-panel.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import Sinon from 'sinon';
import { expect } from 'chai';
import * as React from 'react';
import { cleanup, render, screen } from '@testing-library/react';
import ResourcesPanel, {
TELEMETRY_SCREEN_ID,
} from '../../../../views/webview-app/resources-panel/panel';
import { MESSAGE_TYPES } from '../../../../views/webview-app/extension-app-message-constants';
import vscode from '../../../../views/webview-app/vscode-api';

describe('Resources panel test suite', function () {
afterEach(function () {
cleanup();
});

test('it should render resources panel', function () {
render(<ResourcesPanel onClose={() => {}} />);
expect(() => screen.getByLabelText('Close')).to.not.throw;
expect(screen.getAllByTestId(/link-\w+/)).to.have.length.greaterThan(0);
expect(
screen.getAllByTestId(/footer-feature-\w+/)
).to.have.length.greaterThan(0);
expect(screen.getAllByTestId(/footer-link-\w+/)).to.have.length.greaterThan(
0
);
});

test('it should call onClose on close btn click', function () {
const onCloseFake = Sinon.fake();
render(<ResourcesPanel onClose={onCloseFake} />);
screen.getByLabelText('Close').click();
expect(onCloseFake).to.have.been.calledOnce;
});

test('it should track link clicked event on click of any link', function () {
const postMessageStub = Sinon.stub(vscode, 'postMessage');
render(<ResourcesPanel onClose={() => {}} />);
screen.getAllByTestId(/^link-\w+/).forEach((link) => {
link.click();
expect(postMessageStub).to.have.been.calledWithExactly({
command: MESSAGE_TYPES.EXTENSION_LINK_CLICKED,
screen: TELEMETRY_SCREEN_ID,
linkId: link.getAttribute('data-testid')?.replace('link-', ''),
});
});

screen.getAllByTestId(/^footer-feature-\w+/).forEach((link) => {
link.click();
expect(postMessageStub).to.have.been.calledWithExactly({
command: MESSAGE_TYPES.EXTENSION_LINK_CLICKED,
screen: TELEMETRY_SCREEN_ID,
linkId: link
.getAttribute('data-testid')
?.replace('footer-feature-', ''),
});
});

screen.getAllByTestId(/^footer-link-\w+/).forEach((link) => {
link.click();
expect(postMessageStub).to.have.been.calledWithExactly({
command: MESSAGE_TYPES.EXTENSION_LINK_CLICKED,
screen: TELEMETRY_SCREEN_ID,
linkId: link.getAttribute('data-testid')?.replace('footer-link-', ''),
});
});
});
});
Loading
Loading