Skip to content

Commit 6765079

Browse files
authored
fix(compass-schema-validation): prevent losing changes in validation editor COMPASS-9003 (#6736)
1 parent d79e761 commit 6765079

File tree

6 files changed

+66
-19
lines changed

6 files changed

+66
-19
lines changed

package-lock.json

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/compass-schema-validation/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@
7878
"@mongodb-js/compass-field-store": "^9.25.2",
7979
"@mongodb-js/compass-logging": "^1.6.2",
8080
"@mongodb-js/compass-telemetry": "^1.4.2",
81+
"@mongodb-js/compass-workspaces": "^0.31.2",
8182
"bson": "^6.10.1",
8283
"compass-preferences-model": "^2.33.2",
8384
"hadron-app-registry": "^9.4.2",

packages/compass-schema-validation/src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { preferencesLocator } from 'compass-preferences-model/provider';
1212
import { createLoggerLocator } from '@mongodb-js/compass-logging/provider';
1313
import { telemetryLocator } from '@mongodb-js/compass-telemetry/provider';
1414
import { SchemaValidationTabTitle } from './plugin-title';
15+
import { workspacesServiceLocator } from '@mongodb-js/compass-workspaces/provider';
1516

1617
const CompassSchemaValidationHadronPlugin = registerHadronPlugin(
1718
{
@@ -30,6 +31,7 @@ const CompassSchemaValidationHadronPlugin = registerHadronPlugin(
3031
preferences: preferencesLocator,
3132
logger: createLoggerLocator('COMPASS-SCHEMA-VALIDATION-UI'),
3233
track: telemetryLocator,
34+
workspaces: workspacesServiceLocator,
3335
}
3436
);
3537
export const CompassSchemaValidationPlugin = {

packages/compass-schema-validation/src/modules/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import type {
3030
import type AppRegistry from 'hadron-app-registry';
3131
import type { Logger } from '@mongodb-js/compass-logging/provider';
3232
import type { TrackFunction } from '@mongodb-js/compass-telemetry';
33+
import { type WorkspacesService } from '@mongodb-js/compass-workspaces/provider';
3334

3435
/**
3536
* Reset action constant.
@@ -67,6 +68,7 @@ export type SchemaValidationExtraArgs = {
6768
connectionInfoRef: ConnectionInfoRef;
6869
preferences: PreferencesAccess;
6970
globalAppRegistry: AppRegistry;
71+
workspaces: WorkspacesService;
7072
logger: Logger;
7173
track: TrackFunction;
7274
};

packages/compass-schema-validation/src/stores/store.spec.ts

Lines changed: 44 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ import { createSandboxFromDefaultPreferences } from 'compass-preferences-model';
2121
import { createNoopLogger } from '@mongodb-js/compass-logging/provider';
2222
import { createNoopTrack } from '@mongodb-js/compass-telemetry/provider';
2323
import type { ConnectionInfoRef } from '@mongodb-js/compass-connections/provider';
24+
import { type WorkspacesService } from '@mongodb-js/compass-workspaces/provider';
25+
import Sinon from 'sinon';
2426

2527
const topologyDescription = {
2628
type: 'Unknown',
@@ -42,34 +44,49 @@ const fakeDataService = {
4244
}),
4345
} as any;
4446

45-
describe('Schema Validation Store', function () {
46-
let store: Store<RootState, RootAction>;
47-
let deactivate: null | (() => void) = null;
47+
const fakeWorkspaces = {
48+
onTabReplace: () => {},
49+
onTabClose: () => {},
50+
} as unknown as WorkspacesService;
51+
52+
const getMockedStore = async () => {
4853
const globalAppRegistry = new AppRegistry();
4954
const connectionInfoRef = {
5055
current: {},
5156
} as ConnectionInfoRef;
57+
const activateResult = onActivated(
58+
{ namespace: 'test.test' } as any,
59+
{
60+
globalAppRegistry: globalAppRegistry,
61+
dataService: fakeDataService,
62+
instance: fakeInstance,
63+
workspaces: fakeWorkspaces,
64+
preferences: await createSandboxFromDefaultPreferences(),
65+
logger: createNoopLogger(),
66+
track: createNoopTrack(),
67+
connectionInfoRef,
68+
},
69+
createActivateHelpers()
70+
);
71+
return activateResult;
72+
};
73+
74+
describe('Schema Validation Store', function () {
75+
let store: Store<RootState, RootAction>;
76+
let deactivate: null | (() => void) = null;
77+
let sandbox: Sinon.SinonSandbox;
5278

5379
beforeEach(async function () {
54-
const activateResult = onActivated(
55-
{ namespace: 'test.test' } as any,
56-
{
57-
globalAppRegistry: globalAppRegistry,
58-
dataService: fakeDataService,
59-
instance: fakeInstance,
60-
preferences: await createSandboxFromDefaultPreferences(),
61-
logger: createNoopLogger(),
62-
track: createNoopTrack(),
63-
connectionInfoRef,
64-
},
65-
createActivateHelpers()
66-
);
80+
sandbox = Sinon.createSandbox();
81+
fakeWorkspaces.onTabClose = sandbox.stub();
82+
fakeWorkspaces.onTabReplace = sandbox.stub();
83+
const activateResult = await getMockedStore();
6784
store = activateResult.store;
68-
// eslint-disable-next-line @typescript-eslint/unbound-method
6985
deactivate = activateResult.deactivate;
7086
});
7187

7288
afterEach(function () {
89+
sandbox.reset();
7390
deactivate?.();
7491
deactivate = null;
7592
});
@@ -128,6 +145,16 @@ describe('Schema Validation Store', function () {
128145
});
129146
store.dispatch(validatorChanged(validator));
130147
});
148+
149+
it('prevents closing the tab', function () {
150+
store.dispatch(validatorChanged(validator));
151+
expect(store.getState().validation.isChanged).to.be.true;
152+
deactivate?.();
153+
const fnProvidedToOnTabClose = (
154+
fakeWorkspaces.onTabClose as Sinon.SinonStub
155+
).args[0][0];
156+
expect(fnProvidedToOnTabClose()).to.be.false;
157+
});
131158
});
132159

133160
context('when the action is fetch valid sample documents', function () {

packages/compass-schema-validation/src/stores/store.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,14 @@ import type { MongoDBInstance } from '@mongodb-js/compass-app-stores/provider';
1616
import type { PreferencesAccess } from 'compass-preferences-model';
1717
import type { Logger } from '@mongodb-js/compass-logging/provider';
1818
import type { TrackFunction } from '@mongodb-js/compass-telemetry';
19+
import { type WorkspacesService } from '@mongodb-js/compass-workspaces/provider';
1920

2021
/**
2122
* The lowest supported version.
2223
*/
2324
const MIN_VERSION = '3.2.0';
2425

25-
type SchemaValidationServices = {
26+
export type SchemaValidationServices = {
2627
globalAppRegistry: AppRegistry;
2728
dataService: Pick<
2829
DataService,
@@ -32,6 +33,7 @@ type SchemaValidationServices = {
3233
preferences: PreferencesAccess;
3334
instance: MongoDBInstance;
3435
logger: Logger;
36+
workspaces: WorkspacesService;
3537
track: TrackFunction;
3638
};
3739

@@ -41,6 +43,7 @@ export function configureStore(
4143
services: Pick<
4244
SchemaValidationServices,
4345
| 'globalAppRegistry'
46+
| 'workspaces'
4447
| 'dataService'
4548
| 'preferences'
4649
| 'logger'
@@ -70,9 +73,10 @@ export function onActivated(
7073
preferences,
7174
instance,
7275
logger,
76+
workspaces,
7377
track,
7478
}: SchemaValidationServices,
75-
{ on, cleanup }: ActivateHelpers
79+
{ on, cleanup, addCleanup }: ActivateHelpers
7680
) {
7781
const store = configureStore(
7882
{
@@ -90,6 +94,7 @@ export function onActivated(
9094
connectionInfoRef,
9195
preferences,
9296
globalAppRegistry,
97+
workspaces,
9398
logger,
9499
track,
95100
}
@@ -107,6 +112,14 @@ export function onActivated(
107112
// Activate validation when this plugin is first rendered
108113
store.dispatch(activateValidation());
109114

115+
const onCloseOrReplace = () => {
116+
return !store.getState().validation.isChanged;
117+
};
118+
119+
addCleanup(workspaces.onTabReplace?.(onCloseOrReplace));
120+
121+
addCleanup(workspaces.onTabClose?.(onCloseOrReplace));
122+
110123
return {
111124
store,
112125
deactivate: cleanup,

0 commit comments

Comments
 (0)