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

Icon refactoring and Summary spacing fix #6951

Merged
merged 5 commits into from
Dec 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
16 changes: 9 additions & 7 deletions frontend/cypress/integration/common/graph_display.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ Before(() => {
When('user graphs {string} namespaces', namespaces => {
// Forcing "Pause" to not cause unhandled promises from the browser when cypress is testing
cy.intercept(`**/api/namespaces/graph*`).as('graphNamespaces');
cy.visit(url + `/graph/namespaces?refresh=0&namespaces=${namespaces}`);
cy.visit(`${url}/graph/namespaces?refresh=0&namespaces=${namespaces}`);
if (namespaces !== '') {
cy.wait('@graphNamespaces');
}
Expand Down Expand Up @@ -111,7 +111,7 @@ Then(`user sees empty graph`, () => {
});

Then(`user sees the {string} namespace`, ns => {
cy.get('div#summary-panel-graph').find('div#summary-panel-graph-heading').find(`span#ns-${ns}`).should('be.visible');
cy.get('div#summary-panel-graph').find('div#summary-panel-graph-heading').find(`div#ns-${ns}`).should('be.visible');
});

Then('the display menu opens', () => {
Expand Down Expand Up @@ -321,7 +321,7 @@ Then('{string} option {string} in the graph', (option: string, action: string) =
validateInput(option, action);
});

And('the {string} option should {string} and {string}', (option:string, optionState:string, checkState:string) => {
And('the {string} option should {string} and {string}', (option: string, optionState: string, checkState: string) => {
switch (option) {
case 'operation nodes':
option = 'filterOperationNodes';
Expand All @@ -332,11 +332,13 @@ And('the {string} option should {string} and {string}', (option:string, optionSt
default:
option = 'xxx';
}
cy.get('div#graph-display-menu').find(`input#${option}`).should(optionState.replaceAll(' ','.')).and(`be.${checkState}`);
cy.get('div#graph-display-menu')
.find(`input#${option}`)
.should(optionState.replaceAll(' ', '.'))
.and(`be.${checkState}`);
});


And('only a single cluster box should be visible',() =>{
And('only a single cluster box should be visible', () => {
cy.waitForReact();
cy.getReact('CytoscapeGraph')
.should('have.length', '1')
Expand All @@ -349,7 +351,7 @@ And('only a single cluster box should be visible',() =>{
});
});

function validateInput(option: string, action: string) {
function validateInput(option: string, action: string): void {
if (action.startsWith('appear')) {
cy.get('div#graph-display-menu')
.find(`input#${option}`)
Expand Down
80 changes: 40 additions & 40 deletions frontend/cypress/integration/common/istio_config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { After, And, Given, Then, When } from '@badeball/cypress-cucumber-prepro
import { colExists, getColWithRowText } from './table';
import { ensureKialiFinishedLoading } from './transition';

function labelsStringToJson(labelsString: string) {
const labelsStringToJson = (labelsString: string): string => {
let labelsJson = '';

if (labelsString.length !== 0) {
Expand All @@ -19,12 +19,12 @@ function labelsStringToJson(labelsString: string) {
}

return `{${labelsJson}}`;
}
};

// I included this, because the URL parameter is in plural, but the the Type itself in Kiali is singular
// This works for all of the types currently present in Kiali (Feb 8 2023), but may break in the future, because
// it does not support all of the english words
function singularize(word: string) {
const singularize = (word: string): string => {
const endings = {
ves: 'fe',
ies: 'y',
Expand All @@ -34,10 +34,11 @@ function singularize(word: string) {
es: 'e',
s: ''
};

return word.replace(new RegExp(`(${Object.keys(endings).join('|')})$`), r => endings[r]);
}
};

function minimalAuthorizationPolicy(name: string, namespace: string): string {
const minimalAuthorizationPolicy = (name: string, namespace: string): string => {
return `{
"apiVersion": "security.istio.io/v1beta1",
"kind": "AuthorizationPolicy",
Expand All @@ -46,9 +47,9 @@ function minimalAuthorizationPolicy(name: string, namespace: string): string {
"namespace": "${namespace}"
}
}`;
}
};

function minimalDestinationRule(name: string, namespace: string, host: string): string {
const minimalDestinationRule = (name: string, namespace: string, host: string): string => {
return `{
"apiVersion": "networking.istio.io/v1alpha3",
"kind": "DestinationRule",
Expand All @@ -60,9 +61,9 @@ function minimalDestinationRule(name: string, namespace: string, host: string):
"host": "${host}"
}
}`;
}
};

function minimalVirtualService(name: string, namespace: string, routeName: string, routeHost: string): string {
const minimalVirtualService = (name: string, namespace: string, routeName: string, routeHost: string): string => {
return `{
"apiVersion": "networking.istio.io/v1alpha3",
"kind": "VirtualService",
Expand All @@ -85,9 +86,9 @@ function minimalVirtualService(name: string, namespace: string, routeName: strin
]
}
}`;
}
};

function minimalPeerAuthentication(name: string, namespace: string) {
const minimalPeerAuthentication = (name: string, namespace: string): string => {
return `{
"apiVersion": "security.istio.io/v1beta1",
"kind": "PeerAuthentication",
Expand All @@ -96,9 +97,9 @@ function minimalPeerAuthentication(name: string, namespace: string) {
"namespace": "${namespace}"
}
}`;
}
};

function minimalGateway(name: string, namespace: string, hosts: string, port: number, labelsString: string) {
const minimalGateway = (name: string, namespace: string, hosts: string, port: number, labelsString: string): string => {
return `{
"apiVersion": "networking.istio.io/v1alpha3",
"kind": "Gateway",
Expand All @@ -123,9 +124,9 @@ function minimalGateway(name: string, namespace: string, hosts: string, port: nu
]
}
}`;
}
};

function minimalSidecar(name: string, namespace: string, hosts: string) {
const minimalSidecar = (name: string, namespace: string, hosts: string): string => {
return `{
"apiVersion": "networking.istio.io/v1alpha3",
"kind": "Sidecar",
Expand All @@ -142,7 +143,7 @@ function minimalSidecar(name: string, namespace: string, hosts: string) {
]
}
}`;
}
};

Given('a {string} AuthorizationPolicy in the {string} namespace', function (name: string, namespace: string) {
cy.exec(`kubectl delete AuthorizationPolicy ${name} -n ${namespace}`, { failOnNonZeroExit: false });
Expand Down Expand Up @@ -217,7 +218,7 @@ Given(
}
);

Given('there is not a {string} VirtualService in the {string} namespace', function (vsName: string, namespace: string) {
Given('there is not a {string} VirtualService in the {string} namespace', (vsName: string, namespace: string) => {
cy.exec(`kubectl delete VirtualService ${vsName} -n ${namespace}`, { failOnNonZeroExit: false });
});

Expand Down Expand Up @@ -306,7 +307,7 @@ Given(
}
);

When('the user refreshes the list page', function () {
When('the user refreshes the list page', () => {
cy.get('[data-test="refresh-button"]').click();
ensureKialiFinishedLoading();
});
Expand Down Expand Up @@ -466,29 +467,28 @@ Then('the user can create a {string} K8s Istio object', (object: string) => {
});

Then('the AuthorizationPolicy should have a {string}', function (healthStatus: string) {
cy.get(`[data-test=VirtualItem_Ns${this.targetNamespace}_authorizationpolicy_${this.targetAuthorizationPolicy}] svg`)
.invoke('attr', 'style')
.should('have.string', `${healthStatus}-color`);
});

Then('the {string} {string} of the {string} namespace should have a {string}', function (
crdInstanceName: string,
crdName: string,
namespace: string,
healthStatus: string
) {
it('loading config list', { retries: 3 }, () => {
cy.request('GET', Cypress.config('baseUrl') + `/api/istio/config?refresh=0`);
cy.get('[data-test="refresh-button"]').click();
ensureKialiFinishedLoading();
cy.get(`[data-test=VirtualItem_Ns${namespace}_${crdName.toLowerCase()}_${crdInstanceName}] svg`, { timeout: 40000 })
.should('be.visible')
.invoke('attr', 'style')
.should('have.string', `${healthStatus}-color`);
});
});
cy.get(
`[data-test=VirtualItem_Ns${this.targetNamespace}_authorizationpolicy_${this.targetAuthorizationPolicy}] span.pf-v5-c-icon`
).hasCssVar('color', `--pf-v5-global--${healthStatus}-color--100`);
});

Then(
'the {string} {string} of the {string} namespace should have a {string}',
(crdInstanceName: string, crdName: string, namespace: string, healthStatus: string) => {
it('loading config list', { retries: 3 }, () => {
cy.request('GET', `${Cypress.config('baseUrl')}/api/istio/config?refresh=0`);
cy.get('[data-test="refresh-button"]').click();
ensureKialiFinishedLoading();
cy.get(`[data-test=VirtualItem_Ns${namespace}_${crdName.toLowerCase()}_${crdInstanceName}] span.pf-v5-c-icon`, {
timeout: 40000
})
.should('be.visible')
.hasCssVar('color', `--pf-v5-global--${healthStatus}-color--100`);
});
}
);

After({ tags: '@istio-page and @crd-validation' }, function () {
After({ tags: '@istio-page and @crd-validation' }, () => {
cy.exec('kubectl delete PeerAuthentications,DestinationRules,AuthorizationPolicies,Sidecars --all --all-namespaces', {
failOnNonZeroExit: false
});
Expand Down
36 changes: 32 additions & 4 deletions frontend/cypress/support/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,14 @@ declare namespace Cypress {
*/
getBySel(selector: string, ...args: any): Chainable<Subject>;

/**
* Custom command to check if a DOM element has specific CSS variable
* @param styleName the style name (e.g., color, margin, padding)
* @param cssVarName the css variable name
* @example cy.get(...).hasCssVar('color','--my-color')
*/
hasCssVar(styleName: string, cssVarName: string): void;

/**
* Custom command to check text validation for inputs.
* @param id the input identifier
Expand All @@ -54,6 +62,9 @@ declare namespace Cypress {
*/
login(username: string, password: string): Chainable<Subject>;

/**
* Logout from Kiali
*/
logout(): Chainable<Subject>;
}
}
Expand All @@ -64,16 +75,17 @@ let haveCookie = Cypress.env('cookie');
// 302: https://localhost:8080/login?redirect=%2F
// to:
// https://localhost:8080/login?redirect=%2F
function parseRedirect(redirect: string) {
const parseRedirect = (redirect: string): string => {
return redirect.replace('302: ', '');
}
};

// finishLogin is only separated because we need to chain off .then
// and this same block is repeated.
function finishLogin(authEndpoint: string, username: string, password: string) {
const finishLogin = (authEndpoint: string, username: string, password: string): void => {
const openshiftLoginEndpointURL = new URL(authEndpoint);
const openshiftLoginEndpoint = openshiftLoginEndpointURL.origin + openshiftLoginEndpointURL.pathname;
const loginParams = new URLSearchParams(openshiftLoginEndpointURL.search);

cy.getCookie('csrf').then(cookie => {
cy.request({
url: openshiftLoginEndpoint,
Expand All @@ -88,6 +100,7 @@ function finishLogin(authEndpoint: string, username: string, password: string) {
}).then(resp => {
const kialiURLWithToken = new URL(resp.redirects[1].replace('302: ', ''));
const kialiParams = new URLSearchParams(kialiURLWithToken.hash.slice(1));

cy.request({
url: 'api/authenticate',
body: {
Expand All @@ -101,7 +114,7 @@ function finishLogin(authEndpoint: string, username: string, password: string) {
});
});
});
}
};

Cypress.Commands.add('login', (username: string, password: string) => {
cy.log(`auth cookie is: ${haveCookie}`);
Expand Down Expand Up @@ -220,3 +233,18 @@ Cypress.Commands.add('inputValidation', (id: string, text: string, valid = true)
cy.get(`input[id="${id}"]`).should('have.attr', 'aria-invalid', `${!valid}`);
cy.get(`input[id="${id}"]`).clear();
});

Cypress.Commands.add('hasCssVar', { prevSubject: true }, (subject, styleName, cssVarName) => {
cy.document().then(doc => {
const dummy = doc.createElement('span');
dummy.style.setProperty(styleName, `var(${cssVarName})`);
doc.body.appendChild(dummy);

const evaluatedStyle = window.getComputedStyle(dummy).getPropertyValue(styleName).trim();
dummy.remove();

cy.wrap(subject)
.then($el => window.getComputedStyle($el[0]).getPropertyValue(styleName).trim())
.should('eq', evaluatedStyle);
});
});
2 changes: 1 addition & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
"cypress:delete:reports": "rm cypress/results/* || true",
"cypress:combine:reports": "jrm cypress/results/combined-report.xml \"cypress/results/*.xml\"",
"lint": "eslint --ext js,ts,tsx src",
"lint:precommit": "eslint -c .eslintrc_precommit $(git diff --staged --name-only HEAD | grep -E '\\.tsx?$' | cut -d'/' -f2-)",
"lint:precommit": "eslint -c .eslintrc_precommit $(git diff --staged --name-only HEAD --diff-filter=AM | grep -E '\\.tsx?$' | cut -d'/' -f2-)",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Filter added to apply precommit lint only to added and modified files (it was throwing lint error because of deleted file)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like these author-written review comments, it's helpful without having to add comments in the code.

"lint:fix": "eslint --ext js,ts,tsx --fix src",
"start": "if [ \"${KIALI_ENV}\" = \"production\" ]; then npm run start:prod; else npm run start:dev; fi",
"start:dev": "sh -ac '. ./.env.upstream; npm run start:kiali'",
Expand Down