Skip to content

Commit 452b78b

Browse files
committed
test: [DBAAS1-1403] Add negative cypress test for synchronous replication advanced config
1 parent 04a3d8f commit 452b78b

File tree

4 files changed

+122
-51
lines changed

4 files changed

+122
-51
lines changed

packages/manager/cypress/e2e/core/databases/advanced-configuration.spec.ts

Lines changed: 85 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
mockGetDatabaseEngineConfigs,
1414
mockGetDatabaseTypes,
1515
mockUpdateDatabase,
16+
mockUpdateDatabaseError,
1617
} from 'support/intercepts/databases';
1718
import { mockAppendFeatureFlags } from 'support/intercepts/feature-flags';
1819
import { ui } from 'support/ui';
@@ -190,11 +191,11 @@ const addConfigsToUI = (
190191
cy.get(`[name="${flatKey}"]`).should('be.visible').clear();
191192
cy.get(`[name="${flatKey}"]`).type(additionalConfigs[flatKey]);
192193
} else {
193-
// Fallback: Material-UI Autocomplete (like synchronous_replication)
194+
// Fallback
195+
ui.autocomplete.find().first().scrollIntoView();
194196
ui.autocomplete
195197
.find()
196198
.first()
197-
.scrollIntoView()
198199
.should('be.visible')
199200
.clear()
200201
.type(`${additionalConfigs[flatKey]}`);
@@ -272,6 +273,7 @@ describe('Update database clusters', () => {
272273
});
273274

274275
// Confirms all the buttons are in the initial state - enabled/disabled
276+
ui.cdsButton.findButtonByTitle('Configure').scrollIntoView();
275277
ui.cdsButton
276278
.findButtonByTitle('Configure')
277279
.should('be.visible')
@@ -283,26 +285,23 @@ describe('Update database clusters', () => {
283285
.findButtonByTitle('Add')
284286
.should('exist')
285287
.should('be.disabled');
286-
ui.button
287-
.findByTitle('Save')
288-
.scrollIntoView()
289-
.should('be.visible')
290-
.should('be.disabled');
288+
ui.button.findByTitle('Save').should('exist').should('be.disabled');
291289

292290
ui.button
293291
.findByTitle('Cancel')
294-
.scrollIntoView()
295-
.should('be.visible')
292+
.should('exist')
296293
.should('be.enabled')
297294
.click();
298295

296+
ui.cdsButton.findButtonByTitle('Configure').scrollIntoView();
299297
ui.cdsButton
300298
.findButtonByTitle('Configure')
301299
.should('be.visible')
302300
.should('be.enabled')
303301
.click();
304302

305303
ui.drawer.findByTitle('Advanced Configuration').should('be.visible');
304+
cy.get('[aria-label="Close drawer"]').scrollIntoView();
306305
cy.get('[aria-label="Close drawer"]')
307306
.should('be.visible')
308307
.should('be.enabled')
@@ -353,6 +352,7 @@ describe('Update database clusters', () => {
353352
cy.wait(['@getDatabase', '@getDatabaseTypes']);
354353

355354
// Expand configure drawer to add configs
355+
ui.cdsButton.findButtonByTitle('Configure').scrollIntoView();
356356
ui.cdsButton
357357
.findButtonByTitle('Configure')
358358
.should('be.visible')
@@ -370,31 +370,50 @@ describe('Update database clusters', () => {
370370
true
371371
);
372372

373+
const isSyncReplicationQuorum =
374+
singleConfig['synchronous_replication'] === 'quorum';
375+
const isInvaliClusterSize =
376+
database.cluster_size < 3 && isSyncReplicationQuorum;
377+
373378
// Update advanced configurations with the newly added config
374-
mockUpdateDatabase(database.id, database.engine, {
375-
...database,
376-
engine_config: {
377-
...(database.engine_config as ConfigCategoryValues),
378-
[engineType]: {
379-
...(existingConfig as ConfigCategoryValues),
380-
...singleConfig,
379+
if (isInvaliClusterSize) {
380+
mockUpdateDatabaseError(
381+
database.id,
382+
database.engine,
383+
'engine_config.synchronous_replication',
384+
'synchronous_replication is only supported for clusters with 3 nodes'
385+
).as('updateAdvancedConfiguration');
386+
} else {
387+
mockUpdateDatabase(database.id, database.engine, {
388+
...database,
389+
engine_config: {
390+
...(database.engine_config as ConfigCategoryValues),
391+
[engineType]: {
392+
...(existingConfig as ConfigCategoryValues),
393+
...singleConfig,
394+
},
381395
},
382-
},
383-
}).as('updateAdvancedConfiguration');
384-
396+
}).as('updateAdvancedConfiguration');
397+
}
385398
// Save or Save and Restart Services as per the config added
386399
ui.button
387400
.findByTitle(saveRestartButton)
388-
.scrollIntoView()
389-
.should('be.visible')
401+
.should('exist')
390402
.should('be.enabled')
391403
.click();
392404
cy.wait('@updateAdvancedConfiguration');
393405

394-
// Confirms newly added advacned Config on the Configuration tab tableview
395-
cy.findByText(`${engineType}.${Object.keys(singleConfig)[0]}`).should(
396-
'be.visible'
397-
);
406+
if (isInvaliClusterSize) {
407+
// Verify error message is displayed for invalid synchronous replication
408+
cy.findByText(
409+
/synchronous_replication is only supported for clusters with 3 nodes/i
410+
).should('be.visible');
411+
} else {
412+
// Confirms newly added advanced Config on the Configuration tab tableview
413+
cy.findByText(
414+
`${engineType}.${Object.keys(singleConfig)[0]}`
415+
).should('be.visible');
416+
}
398417
});
399418

400419
/*
@@ -441,6 +460,7 @@ describe('Update database clusters', () => {
441460
cy.wait(['@getDatabase', '@getDatabaseTypes']);
442461

443462
// Expand configure drawer to add configs
463+
ui.cdsButton.findButtonByTitle('Configure').scrollIntoView();
444464
ui.cdsButton
445465
.findButtonByTitle('Configure')
446466
.should('be.visible')
@@ -466,35 +486,55 @@ describe('Update database clusters', () => {
466486
}
467487
});
468488

489+
const isSyncReplicationQuorum =
490+
allConfig['synchronous_replication'] === 'quorum';
491+
const isInvalidClusterSize =
492+
database.cluster_size < 3 && isSyncReplicationQuorum;
493+
469494
// Update advanced configurations with the newly added config
470-
mockUpdateDatabase(database.id, database.engine, {
471-
...database,
472-
engine_config: {
473-
...(database.engine_config as ConfigCategoryValues),
474-
[engineType]: {
475-
...(existingConfig as ConfigCategoryValues),
476-
...nestedConfig,
495+
if (isInvalidClusterSize) {
496+
mockUpdateDatabaseError(
497+
database.id,
498+
database.engine,
499+
'engine_config.synchronous_replication',
500+
'synchronous_replication is only supported for clusters with 3 nodes'
501+
).as('updateAdvancedConfiguration');
502+
} else {
503+
mockUpdateDatabase(database.id, database.engine, {
504+
...database,
505+
engine_config: {
506+
...(database.engine_config as ConfigCategoryValues),
507+
[engineType]: {
508+
...(existingConfig as ConfigCategoryValues),
509+
...nestedConfig,
510+
},
511+
...topLevelConfig,
477512
},
478-
...topLevelConfig,
479-
},
480-
}).as('updateAdvancedConfiguration');
513+
}).as('updateAdvancedConfiguration');
514+
}
481515

482516
// Save or Save and Restart Services as per the config added
483517
ui.button
484518
.findByTitle(saveRestartButton)
485-
.scrollIntoView()
486-
.should('be.visible')
519+
.should('exist')
487520
.should('be.enabled')
488521
.click();
489522
cy.wait('@updateAdvancedConfiguration');
490523

491-
// Confirms newly added advacned Config on the Configuration tab tableview
492-
Object.keys(nestedConfig).forEach((key) => {
493-
cy.findByText(`${engineType}.${key}`).should('be.visible');
494-
});
495-
Object.keys(topLevelConfig).forEach((key) => {
496-
cy.findByText(`${key}`).should('be.visible');
497-
});
524+
if (isInvalidClusterSize) {
525+
// Verify error message is displayed for invalid synchronous replication
526+
cy.findByText(
527+
/synchronous_replication is only supported for clusters with 3 nodes/i
528+
).should('be.visible');
529+
} else {
530+
// Confirms newly added advanced Config on the Configuration tab tableview
531+
Object.keys(nestedConfig).forEach((key) => {
532+
cy.findByText(`${engineType}.${key}`).should('be.visible');
533+
});
534+
Object.keys(topLevelConfig).forEach((key) => {
535+
cy.findByText(`${key}`).should('be.visible');
536+
});
537+
}
498538
});
499539

500540
/*
@@ -538,6 +578,7 @@ describe('Update database clusters', () => {
538578
cy.wait(['@getDatabase', '@getDatabaseTypes']);
539579

540580
// Expand configure drawer to add configs
581+
ui.cdsButton.findButtonByTitle('Configure').scrollIntoView();
541582
ui.cdsButton
542583
.findButtonByTitle('Configure')
543584
.should('be.visible')

packages/manager/cypress/support/constants/databases.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -564,6 +564,16 @@ export const databaseConfigurationsAdvConfig: DatabaseClusterConfiguration[] = [
564564
version: '8',
565565
ip: randomIp(),
566566
},
567+
{
568+
clusterSize: 2,
569+
dbType: 'postgresql',
570+
engine: 'PostgreSQL',
571+
label: randomLabel(),
572+
linodeType: 'g6-nanode-1',
573+
region: chooseRegion({ capabilities: ['Managed Databases'] }),
574+
version: '13',
575+
ip: randomIp(),
576+
},
567577
{
568578
clusterSize: 3,
569579
dbType: 'postgresql',

packages/manager/cypress/support/intercepts/databases.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,33 @@ export const mockUpdateSuspendResumeDatabase = (
240240
);
241241
};
242242

243+
/**
244+
* Intercepts PUT request to update database and mocks error with custom field and reason.
245+
*
246+
* @param id - Database ID.
247+
* @param engine - Database engine type.
248+
* @param field - Error field name.
249+
* @param reason - Error reason message.
250+
*
251+
* @returns Cypress chainable.
252+
*/
253+
export const mockUpdateDatabaseError = (
254+
id: number,
255+
engine: string,
256+
field: string,
257+
reason: string
258+
): Cypress.Chainable<null> => {
259+
const error = makeErrorResponse({
260+
field,
261+
reason,
262+
});
263+
return cy.intercept(
264+
'PUT',
265+
apiMatcher(`databases/${engine}/instances/${id}`),
266+
error
267+
);
268+
};
269+
243270
/**
244271
* Intercepts POST request to reset an active database's password and mocks response.
245272
*

packages/manager/src/factories/databases.ts

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -490,13 +490,6 @@ export const postgresConfigResponse = {
490490
enum: ['quorum', 'off'],
491491
example: 'quorum',
492492
requires_restart: false,
493-
type: 'string',
494-
},
495-
synchronous_replication: {
496-
description:
497-
'Synchronous replication type. Note that the service plan also needs to support synchronous replication.',
498-
enum: ['quorum', 'off'],
499-
requires_restart: false,
500493
default: 'off',
501494
type: 'string',
502495
},

0 commit comments

Comments
 (0)