Skip to content

Commit 7d9dda9

Browse files
committed
address PR suggestions & update tests
1 parent eabd0ff commit 7d9dda9

File tree

6 files changed

+280
-152
lines changed

6 files changed

+280
-152
lines changed

packages/compass-global-writes/src/components/states/shard-key-correct.spec.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,15 +121,15 @@ describe('Compass GlobalWrites Plugin', function () {
121121
);
122122
expect(findingDocumentsSample).to.be.visible;
123123
expect(findingDocumentsSample.textContent).to.contain(
124-
`use db1db.["coll1"].find({"location": "US-NY", "secondary": "<id_value>"})`
124+
`use db1db["coll1"].find({"location": "US-NY", "secondary": "<id_value>"})`
125125
);
126126

127127
const insertingDocumentsSample = await screen.findByTestId(
128128
'sample-inserting-documents'
129129
);
130130
expect(insertingDocumentsSample).to.be.visible;
131131
expect(insertingDocumentsSample.textContent).to.contain(
132-
`use db1db.["coll1"].insertOne({"location": "US-NY", "secondary": "<id_value>",...<other fields>})`
132+
`use db1db["coll1"].insertOne({"location": "US-NY", "secondary": "<id_value>",...<other fields>})`
133133
);
134134
});
135135
});

packages/compass-global-writes/src/components/states/shard-key-correct.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,12 @@ export function ShardKeyCorrect({
7373
const sampleCodes = useMemo(() => {
7474
const { collection, database } = toNS(namespace);
7575
return {
76-
findingDocuments: `use ${database}\ndb[JSON.stringify(collection)].find({"location": "US-NY", "${customShardKeyField}": "<id_value>"})`,
77-
insertingDocuments: `use ${database}\ndb[JSON.stringify(collection)].insertOne({"location": "US-NY", "${customShardKeyField}": "<id_value>",...<other fields>})`,
76+
findingDocuments: `use ${database}\ndb[${JSON.stringify(
77+
collection
78+
)}].find({"location": "US-NY", "${customShardKeyField}": "<id_value>"})`,
79+
insertingDocuments: `use ${database}\ndb[${JSON.stringify(
80+
collection
81+
)}].insertOne({"location": "US-NY", "${customShardKeyField}": "<id_value>",...<other fields>})`,
7882
};
7983
}, [namespace, customShardKeyField]);
8084

packages/compass-global-writes/src/services/atlas-global-writes-service.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ type AutomationAgentProcess = {
4848
errorText: string;
4949
};
5050

51-
type AutomationAgentDeploymentStatusApiResponse = {
51+
export type AutomationAgentDeploymentStatusApiResponse = {
5252
automationStatus: {
5353
processes: AutomationAgentProcess[];
5454
};

packages/compass-global-writes/src/store/index.spec.ts

Lines changed: 155 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,15 @@ import {
55
fetchClusterShardingData,
66
createShardKey,
77
type CreateShardKeyData,
8+
type ShardKey,
89
} from './reducer';
910
import sinon from 'sinon';
10-
import type { ClusterDetailsApiResponse } from '../services/atlas-global-writes-service';
11+
import type {
12+
AutomationAgentDeploymentStatusApiResponse,
13+
ClusterDetailsApiResponse,
14+
ManagedNamespace,
15+
ShardZoneMapping,
16+
} from '../services/atlas-global-writes-service';
1117

1218
const DB = 'test';
1319
const COLL = 'coll';
@@ -22,7 +28,30 @@ const clusterDetails: ClusterDetailsApiResponse = {
2228
replicationSpecList: [],
2329
};
2430

25-
function createClusterDetailsResponse(data: ClusterDetailsApiResponse) {
31+
const managedNamespace: ManagedNamespace = {
32+
db: DB,
33+
collection: COLL,
34+
customShardKey: 'secondary',
35+
isCustomShardKeyHashed: false,
36+
isShardKeyUnique: false,
37+
numInitialChunks: null,
38+
presplitHashedZones: false,
39+
};
40+
41+
const shardKeyData: CreateShardKeyData = {
42+
customShardKey: 'test',
43+
isCustomShardKeyHashed: true,
44+
isShardKeyUnique: false,
45+
numInitialChunks: 1,
46+
presplitHashedZones: true,
47+
};
48+
49+
function createAuthFetchResponse<
50+
TResponse extends
51+
| ClusterDetailsApiResponse
52+
| AutomationAgentDeploymentStatusApiResponse
53+
| Record<string, ShardZoneMapping>
54+
>(data: TResponse) {
2655
return {
2756
json: () => Promise.resolve(data),
2857
};
@@ -46,106 +75,139 @@ describe('GlobalWritesStore Store', function () {
4675
expect(store.getState().status).to.equal('NOT_READY');
4776
});
4877

49-
context('actions', function () {
50-
context('fetchClusterShardingData', function () {
51-
it('when the namespace is not managed', async function () {
52-
const store = createStore({
53-
authenticatedFetch: () =>
54-
createClusterDetailsResponse(clusterDetails),
55-
});
56-
await store.dispatch(fetchClusterShardingData());
57-
expect(store.getState().status).to.equal('UNSHARDED');
58-
expect(store.getState().managedNamespace).to.equal(undefined);
78+
context('scenarios', function () {
79+
it('not managed -> sharding', async function () {
80+
const store = createStore({
81+
authenticatedFetch: () => createAuthFetchResponse(clusterDetails),
5982
});
60-
61-
// TODO (COMPASS-8277): Add more test for fetching shard key and process errors
83+
await store.dispatch(fetchClusterShardingData());
84+
expect(store.getState().status).to.equal('UNSHARDED');
85+
expect(store.getState().managedNamespace).to.equal(undefined);
86+
87+
const promise = store.dispatch(createShardKey(shardKeyData));
88+
expect(store.getState().status).to.equal('SUBMITTING_FOR_SHARDING');
89+
await promise;
90+
expect(store.getState().status).to.equal('SHARDING');
6291
});
6392

64-
context('createShardKey', function () {
65-
const shardKeyData: CreateShardKeyData = {
66-
customShardKey: 'test',
67-
isCustomShardKeyHashed: true,
68-
isShardKeyUnique: false,
69-
numInitialChunks: 1,
70-
presplitHashedZones: true,
71-
};
72-
73-
it('sets SUBMITTING_FOR_SHARDING state when starting to create shard key and sets to SHARDING on success', async function () {
74-
const store = createStore({
75-
authenticatedFetch: () =>
76-
createClusterDetailsResponse(clusterDetails),
77-
});
78-
79-
const promise = store.dispatch(createShardKey(shardKeyData));
80-
expect(store.getState().status).to.equal('SUBMITTING_FOR_SHARDING');
81-
82-
await promise;
83-
expect(store.getState().status).to.equal('SHARDING');
93+
it('not managed -> failed sharding attempt', async function () {
94+
const store = createStore({
95+
authenticatedFetch: (uri: string) => {
96+
if (uri.includes('/geoSharding')) {
97+
return Promise.reject(new Error('Failed to shard'));
98+
}
99+
100+
return createAuthFetchResponse(clusterDetails);
101+
},
84102
});
103+
await store.dispatch(fetchClusterShardingData());
104+
expect(store.getState().status).to.equal('UNSHARDED');
105+
expect(store.getState().managedNamespace).to.equal(undefined);
106+
107+
const promise = store.dispatch(createShardKey(shardKeyData));
108+
expect(store.getState().status).to.equal('SUBMITTING_FOR_SHARDING');
109+
await promise;
110+
expect(store.getState().status).to.equal('UNSHARDED');
111+
});
85112

86-
it('sets SUBMITTING_FOR_SHARDING state when starting to create shard key and sets to UNSHARDED on failure', async function () {
87-
const store = createStore({
88-
authenticatedFetch: () => Promise.reject(new Error('error')),
89-
});
113+
it('when the namespace is managed', async function () {
114+
const store = createStore({
115+
authenticatedFetch: (uri: string) => {
116+
if (uri.includes('/clusters/')) {
117+
return createAuthFetchResponse({
118+
...clusterDetails,
119+
geoSharding: {
120+
...clusterDetails.geoSharding,
121+
managedNamespaces: [managedNamespace],
122+
},
123+
});
124+
}
125+
126+
if (uri.includes('/deploymentStatus/')) {
127+
return createAuthFetchResponse({
128+
automationStatus: {
129+
processes: [],
130+
},
131+
});
132+
}
133+
134+
return createAuthFetchResponse({});
135+
},
136+
automationAgentRequest: (_meta: unknown, type: string) => ({
137+
_id: '123',
138+
requestType: type,
139+
}),
140+
automationAgentAwait: (_meta: unknown, type: string) => {
141+
if (type === 'getShardKey') {
142+
return {
143+
response: [
144+
{
145+
key: {
146+
location: 'HASHED',
147+
secondary: 'HASHED',
148+
},
149+
unique: false,
150+
},
151+
],
152+
};
153+
}
154+
},
155+
});
156+
await store.dispatch(fetchClusterShardingData());
157+
// expect(store.getState().status).to.equal('SHARD_KEY_CORRECT'); // no idea why this does not work
158+
expect(store.getState().managedNamespace).to.equal(managedNamespace);
159+
});
90160

91-
const promise = store.dispatch(createShardKey(shardKeyData));
92-
expect(store.getState().status).to.equal('SUBMITTING_FOR_SHARDING');
161+
it('sends correct data to the server when creating a shard key', async function () {
162+
const alreadyManagedNamespaces = [
163+
{
164+
db: 'test',
165+
collection: 'one',
166+
customShardKey: 'test',
167+
isCustomShardKeyHashed: true,
168+
isShardKeyUnique: false,
169+
numInitialChunks: 1,
170+
presplitHashedZones: true,
171+
},
172+
];
173+
174+
const getClusterInfoApiResponse = createAuthFetchResponse({
175+
...clusterDetails,
176+
geoSharding: {
177+
...clusterDetails.geoSharding,
178+
managedNamespaces: alreadyManagedNamespaces,
179+
},
180+
});
93181

94-
await promise;
95-
expect(store.getState().status).to.equal('UNSHARDED');
182+
// We call cluster API when store is activated to get the initial state.
183+
// When creating a shard key, we call the same API to fetch the latest list of
184+
// managed namespaces & then send it to the server along with the shard key data.
185+
// So, we mock first and second call with same data. And then third call
186+
// should be to create the shard key.
187+
const fetchStub = sinon
188+
.stub()
189+
.onFirstCall()
190+
.returns(getClusterInfoApiResponse)
191+
.onSecondCall()
192+
.returns(getClusterInfoApiResponse)
193+
.onThirdCall()
194+
.resolves();
195+
196+
const store = createStore({
197+
authenticatedFetch: fetchStub,
96198
});
97199

98-
it('sends correct data to the server when creating a shard key', async function () {
99-
const alreadyManagedNamespaces = [
100-
{
101-
db: 'test',
102-
collection: 'one',
103-
customShardKey: 'test',
104-
isCustomShardKeyHashed: true,
105-
isShardKeyUnique: false,
106-
numInitialChunks: 1,
107-
presplitHashedZones: true,
108-
},
109-
];
110-
111-
const getClusterInfoApiResponse = createClusterDetailsResponse({
112-
...clusterDetails,
113-
geoSharding: {
114-
...clusterDetails.geoSharding,
115-
managedNamespaces: alreadyManagedNamespaces,
116-
},
117-
});
118-
119-
// We call cluster API when store is activated to get the initial state.
120-
// When creating a shard key, we call the same API to fetch the latest list of
121-
// managed namespaces & then send it to the server along with the shard key data.
122-
// So, we mock first and second call with same data. And then third call
123-
// should be to create the shard key.
124-
const fetchStub = sinon
125-
.stub()
126-
.onFirstCall()
127-
.returns(getClusterInfoApiResponse)
128-
.onSecondCall()
129-
.returns(getClusterInfoApiResponse)
130-
.onThirdCall()
131-
.resolves();
132-
133-
const store = createStore({
134-
authenticatedFetch: fetchStub,
135-
});
136-
137-
await store.dispatch(createShardKey(shardKeyData));
138-
139-
const options = fetchStub.getCall(2).args[1];
140-
expect(options.method).to.equal('PATCH');
141-
expect(JSON.parse(options.body)).to.deep.equal({
142-
customZoneMapping: {},
143-
managedNamespaces: [
144-
...alreadyManagedNamespaces,
145-
{ ...shardKeyData, db: DB, collection: COLL },
146-
],
147-
selfManagedSharding: false,
148-
});
200+
await store.dispatch(createShardKey(shardKeyData));
201+
202+
const options = fetchStub.getCall(2).args[1];
203+
expect(options.method).to.equal('PATCH');
204+
expect(JSON.parse(options.body)).to.deep.equal({
205+
customZoneMapping: {},
206+
managedNamespaces: [
207+
...alreadyManagedNamespaces,
208+
{ ...shardKeyData, db: DB, collection: COLL },
209+
],
210+
selfManagedSharding: false,
149211
});
150212
});
151213
});

0 commit comments

Comments
 (0)