Skip to content
This repository has been archived by the owner on Dec 21, 2023. It is now read-only.

Commit

Permalink
fix(bridge): Fix broken UI if connection was lost (#8050)
Browse files Browse the repository at this point in the history
* fix(bridge): Fix broken UI if connection was lost

Signed-off-by: Klaus Strießnig <k.striessnig@gmail.com>

* added UI test

Signed-off-by: Klaus Strießnig <k.striessnig@gmail.com>
  • Loading branch information
Kirdock authored Jun 13, 2022
1 parent aa4bcf0 commit 746be23
Show file tree
Hide file tree
Showing 10 changed files with 56 additions and 11 deletions.
2 changes: 0 additions & 2 deletions bridge/client/app/_services/data.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -341,8 +341,6 @@ export class DataService {
projects?.splice(projectIdx, 1);
this._projects.next(projects);
}
} else {
this._projects.error(err);
}
}
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
</ng-container>
</div>
<ng-template #loading>
<div fxFlexFill fxLayout="row" fxLayoutAlign="center center">
<div fxFlexFill fxLayout="row" fxLayoutAlign="center center" uitestid="ktb-environment-is-loading">
<ktb-loading-distractor>Loading …</ktb-loading-distractor>
</div>
</ng-template>
9 changes: 9 additions & 0 deletions bridge/cypress/fixtures/projects.mock.json
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,15 @@
"parentStages": ["staging"]
}
]
},
{
"creationDate": "1631870924824247750",
"gitRemoteURI": "https://github.com/laneli/my-error-project",
"gitUser": "laneli",
"projectName": "my-error-project",
"shipyard": "apiVersion: spec.keptn.sh/0.2.2\nkind: Shipyard\nmetadata:\n name: shipyard-sockshop\nspec:\n stages:\n - name: dev\n sequences:\n - name: delivery\n tasks:\n - name: deployment\n properties:\n deploymentstrategy: direct\n - name: test\n properties:\n teststrategy: functional\n - name: evaluation\n properties: null\n - name: release\n properties: null\n - name: delivery-direct\n tasks:\n - name: deployment\n properties:\n deploymentstrategy: direct\n - name: release\n properties: null\n - name: staging\n sequences:\n - name: delivery\n triggeredOn:\n - event: dev.delivery.finished\n tasks:\n - name: deployment\n properties:\n deploymentstrategy: blue_green_service\n - name: test\n properties:\n teststrategy: performance\n - name: evaluation\n properties: null\n - name: release\n properties: null\n - name: rollback\n triggeredOn:\n - event: staging.delivery.finished\n selector:\n match:\n result: fail\n tasks:\n - name: rollback\n properties: null\n - name: delivery-direct\n triggeredOn:\n - event: dev.delivery-direct.finished\n tasks:\n - name: deployment\n properties:\n deploymentstrategy: direct\n - name: release\n properties: null\n - name: production\n sequences:\n - name: delivery\n triggeredOn:\n - event: staging.delivery.finished\n tasks:\n - name: deployment\n properties:\n deploymentstrategy: blue_green_service\n - name: release\n properties: null\n - name: rollback\n triggeredOn:\n - event: production.delivery.finished\n selector:\n match:\n result: fail\n tasks:\n - name: rollback\n properties: null\n - name: delivery-direct\n triggeredOn:\n - event: staging.delivery-direct.finished\n tasks:\n - name: deployment\n properties:\n deploymentstrategy: direct\n - name: release\n properties: null\n - name: remediation\n triggeredOn:\n - event: production.remediation.finished\n selector:\n match:\n evaluation.result: fail\n tasks:\n - name: get-action\n properties: null\n - name: action\n properties: null\n - name: evaluation\n triggeredAfter: 15m\n properties:\n timeframe: 15m\n",
"shipyardVersion": "spec.keptn.sh/0.2.2",
"stages": []
}
],
"totalCount": 1
Expand Down
2 changes: 1 addition & 1 deletion bridge/cypress/integration/evaluations.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ describe('evaluations', () => {
beforeEach(() => {
cy.intercept('/api/v1/metadata', { fixture: 'metadata.mock' });
cy.intercept('/api/bridgeInfo', { fixture: 'bridgeInfo.mock' });
cy.intercept('/api/project/sockshop?approval=true&remediation=true', { fixture: 'project.mock' });
cy.intercept('/api/project/sockshop?approval=true&remediation=true', { fixture: 'project.mock' }).as('project');
cy.intercept('/api/hasUnreadUniformRegistrationLogs', { body: false });
cy.intercept('/api/controlPlane/v1/project?disableUpstreamSync=true&pageSize=50', { fixture: 'projects.mock' });
});
Expand Down
18 changes: 18 additions & 0 deletions bridge/cypress/integration/navigation-project-error.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { ProjectBoardPage } from '../support/pageobjects/ProjectBoardPage';
import EnvironmentPage from '../support/pageobjects/EnvironmentPage';
import BasePage from '../support/pageobjects/BasePage';

describe('Navigation on project error', () => {
it('should still navigate and load data if one project request failed', () => {
const projectBoardPage = new ProjectBoardPage();
const environmentPage = new EnvironmentPage();
const basePage = new BasePage();
const project = 'my-error-project';
environmentPage.intercept();
projectBoardPage.interceptError(project);

environmentPage.visit(project).assertIsLoaded(false);
basePage.selectProjectThroughHeader('sockshop');
environmentPage.assertIsLoaded(true);
});
});
11 changes: 7 additions & 4 deletions bridge/cypress/support/intercept.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
export function interceptEmptyEnvironmentScreen(): void {
interceptProjectBoard();
cy.intercept('/api/project/dynatrace?approval=true&remediation=true', { fixture: 'project.empty.mock' });
cy.intercept('/api/project/dynatrace?approval=true&remediation=true', { fixture: 'project.empty.mock' }).as(
'project'
);
cy.intercept('/api/controlPlane/v1/project?disableUpstreamSync=true&pageSize=50', {
fixture: 'get.projects.empty.mock',
}).as('projects');
Expand Down Expand Up @@ -113,14 +115,15 @@ export function interceptProjectSettings(): void {
export function interceptDashboard(): void {
interceptMain();
cy.intercept('/api/controlPlane/v1/sequence/sockshop?pageSize=5', { fixture: 'sequences.sockshop' }).as('sequences');
cy.intercept('/api/controlPlane/v1/sequence/my-error-project?pageSize=5', { body: { states: [] } });
cy.intercept('/api/controlPlane/v1/project?disableUpstreamSync=true&pageSize=50', { fixture: 'projects.mock' }).as(
'projects'
);
}

export function interceptProjectBoard(): void {
interceptMain();
cy.intercept('/api/project/sockshop?approval=true&remediation=true', { fixture: 'project.mock' });
cy.intercept('/api/project/sockshop?approval=true&remediation=true', { fixture: 'project.mock' }).as('project');
cy.intercept('/api/hasUnreadUniformRegistrationLogs', { body: false });
}

Expand Down Expand Up @@ -209,7 +212,7 @@ export function interceptSequencesPageWithSequenceThatIsNotLoaded(): void {

export function interceptIntegrations(): void {
interceptMain();
cy.intercept('/api/project/sockshop?approval=true&remediation=true', { fixture: 'project.mock' });
cy.intercept('/api/project/sockshop?approval=true&remediation=true', { fixture: 'project.mock' }).as('project');
cy.intercept('/api/hasUnreadUniformRegistrationLogs', { body: false });
cy.intercept('/api/controlPlane/v1/project?disableUpstreamSync=true&pageSize=50', { fixture: 'projects.mock' }).as(
'projects'
Expand Down Expand Up @@ -389,7 +392,7 @@ export function interceptEvaluationBoardWithoutDeployment(): void {
export function interceptHeatmapComponent(): void {
cy.intercept('/api/v1/metadata', { fixture: 'metadata.mock' });
cy.intercept('/api/bridgeInfo', { fixture: 'bridgeInfoEnableD3Heatmap.mock.json' });
cy.intercept('/api/project/sockshop?approval=true&remediation=true', { fixture: 'project.mock' });
cy.intercept('/api/project/sockshop?approval=true&remediation=true', { fixture: 'project.mock' }).as('project');
cy.intercept('/api/hasUnreadUniformRegistrationLogs', { body: false });
cy.intercept('/api/controlPlane/v1/project?disableUpstreamSync=true&pageSize=50', { fixture: 'projects.mock' });
cy.intercept('GET', '/api/project/sockshop/serviceStates', {
Expand Down
5 changes: 4 additions & 1 deletion bridge/cypress/support/pageobjects/DashboardPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,10 @@ class DashboardPage {
cy.get('ktb-project-tile')
.eq(index)
.byTestId('keptn-project-tile-numStagesServices')
.should('contain.text', `${project.stages.length} Stages, ${project.stages[0].services.length} Services `);
.should(
'contain.text',
`${project.stages.length} Stages, ${project.stages[0]?.services.length ?? 0} Services `
);
});
return this;
}
Expand Down
7 changes: 6 additions & 1 deletion bridge/cypress/support/pageobjects/EnvironmentPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class EnvironmentPage {
}

public visit(project: string): this {
cy.visit(`/project/${project}`).wait('@metadata');
cy.visit(`/project/${project}`).wait('@metadata').wait('@project');
return this;
}

Expand Down Expand Up @@ -68,6 +68,11 @@ class EnvironmentPage {
private getServiceDetailsContainer(service: string): Cypress.Chainable<JQuery<HTMLElement>> {
return cy.get('ktb-stage-details ktb-expandable-tile h2').contains(service).parentsUntil('ktb-expandable-tile');
}

public assertIsLoaded(status: boolean): this {
cy.byTestId('ktb-environment-is-loading').should(status ? 'not.exist' : 'exist');
return this;
}
}

export default EnvironmentPage;
9 changes: 9 additions & 0 deletions bridge/cypress/support/pageobjects/ProjectBoardPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import SettingsPage from './SettingsPage';
import ServicesPage from './ServicesPage';
import { interceptProjectBoard } from '../intercept';

enum View {
SERVICE_VIEW = 'service-view',
Expand All @@ -21,6 +22,14 @@ export class ProjectBoardPage {
return this;
}

public interceptError(projectName: string): this {
interceptProjectBoard();
cy.intercept(`/api/project/${projectName}?approval=true&remediation=true`, { forceNetworkError: true }).as(
'project'
);
return this;
}

public login(username: string, password: string): void {
cy.get('#email_verify').type(username);
cy.get('#next_button').click();
Expand Down
2 changes: 1 addition & 1 deletion bridge/cypress/support/pageobjects/SequencesPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export class SequencesPage {
interceptMain();
cy.intercept('/api/project/sockshop?approval=true&remediation=true', {
fixture: 'get.project.sockshop.remediation.mock',
});
}).as('project');
cy.intercept('/api/hasUnreadUniformRegistrationLogs', { body: false });

cy.intercept('/api/controlPlane/v1/project?disableUpstreamSync=true&pageSize=50', { fixture: 'projects.mock' });
Expand Down

0 comments on commit 746be23

Please sign in to comment.