mirror of
https://github.com/kubeshark/kubeshark.git
synced 2025-08-12 13:53:30 +00:00
* #run_acceptance_tests * Wait 4 seconds after filter submission #run_acceptance_tests * Revert "Wait 4 seconds after filter submission #run_acceptance_tests" This reverts commit3c20ccfcec
. * Upgrade Basenine version to `v0.8.2` #run_acceptance_tests * #run_acceptance_tests * Revert "Revert "Wait 4 seconds after filter submission #run_acceptance_tests"" This reverts commitf0c595150d
. * Reduce the delay to 2 seconds #run_acceptance_tests * Use `cy.wait()` instead of `setTimeout` * #run_acceptance_tests * Increase it to 4 seconds #run_acceptance_tests * #run_acceptance_tests * Wait for a second and pause the stream to preserve the DOM #run_acceptance_tests * Wait in a better place #run_acceptance_tests * Wait `pause-icon` to disappear #run_acceptance_tests * Wait one more second #run_acceptance_tests * Fix `setup.sh` * #run_acceptance_tests * Fix the place of `npm i` call * #run_acceptance_tests * Fix the other workflow as well #run_acceptance_tests * Fix the workflows once more * #run_acceptance_tests * Don't ignore `*/cypress/support` #run_acceptance_tests * Do `npm i` in `setup.sh` #run_acceptance_tests * Wait for at least 4 seconds #run_acceptance_tests * #run_acceptance_tests * Fix #run_acceptance_tests * Comment #run_acceptance_tests * Fix `{alt+enter}` to `{ctrl+enter}` and update the `checkFilter` and `deeperCheck` method signatures #run_acceptance_tests * #run_acceptance_tests * #run_acceptance_tests * Extract it to a function #run_acceptance_tests * Remove `cypress-wait-until` * Revert `.gitignore` #run_acceptance_tests
387 lines
15 KiB
JavaScript
387 lines
15 KiB
JavaScript
import {findLineAndCheck, getExpectedDetailsDict} from "../testHelpers/StatusBarHelper";
|
|
import {
|
|
getEntryId,
|
|
leftOnHoverCheck,
|
|
leftTextCheck,
|
|
resizeToHugeMizu,
|
|
resizeToNormalMizu,
|
|
rightOnHoverCheck,
|
|
rightTextCheck,
|
|
verifyMinimumEntries
|
|
} from "../testHelpers/TrafficHelper";
|
|
|
|
const refreshWaitTimeout = 10000;
|
|
|
|
|
|
const fullParam = Cypress.env('arrayDict'); // "Name:fooNamespace:barName:foo1Namespace:bar1"
|
|
const podsArray = fullParam.split('Name:').slice(1); // ["fooNamespace:bar", "foo1Namespace:bar1"]
|
|
podsArray.forEach((podStr, index) => {
|
|
const podAndNamespaceArr = podStr.split('Namespace:'); // [foo, bar] / [foo1, bar1]
|
|
podsArray[index] = getExpectedDetailsDict(podAndNamespaceArr[0], podAndNamespaceArr[1]);
|
|
});
|
|
|
|
it('opening mizu', function () {
|
|
cy.visit(Cypress.env('testUrl'));
|
|
});
|
|
|
|
verifyMinimumEntries();
|
|
|
|
it('top bar check', function () {
|
|
cy.get(`[data-cy="podsCountText"]`).trigger('mouseover');
|
|
podsArray.map(findLineAndCheck);
|
|
cy.reload();
|
|
});
|
|
|
|
it('filtering guide check', function () {
|
|
cy.reload();
|
|
cy.get('[title="Open Filtering Guide (Cheatsheet)"]').click();
|
|
cy.get('#modal-modal-title').should('be.visible');
|
|
cy.get('[lang="en"]').click(0, 0);
|
|
cy.get('#modal-modal-title').should('not.exist');
|
|
});
|
|
|
|
it('right side sanity test', function () {
|
|
cy.get('#entryDetailedTitleElapsedTime').then(timeInMs => {
|
|
const time = timeInMs.text();
|
|
if (time < '0ms') {
|
|
throw new Error(`The time in the top line cannot be negative ${time}`);
|
|
}
|
|
});
|
|
|
|
// temporary fix, change to some "data-cy" attribute,
|
|
// this will fix the issue that happen because we have "response:" in the header of the right side
|
|
cy.get('#rightSideContainer > :nth-child(3)').contains('Response').click();
|
|
|
|
cy.get('#rightSideContainer [title="Status Code"]').then(status => {
|
|
const statusCode = status.text();
|
|
cy.contains('Status').parent().next().then(statusInDetails => {
|
|
const statusCodeInDetails = statusInDetails.text();
|
|
|
|
expect(statusCode).to.equal(statusCodeInDetails, 'The status code in the top line should match the status code in details');
|
|
});
|
|
});
|
|
});
|
|
|
|
checkIllegalFilter('invalid filter');
|
|
|
|
checkFilter({
|
|
filter: 'http',
|
|
leftSidePath: '> :nth-child(1) > :nth-child(1)',
|
|
leftSideExpectedText: 'HTTP',
|
|
rightSidePath: '[title=HTTP]',
|
|
rightSideExpectedText: 'Hypertext Transfer Protocol -- HTTP/1.1',
|
|
applyByCtrlEnter: true
|
|
});
|
|
|
|
checkFilter({
|
|
filter: 'response.status == 200',
|
|
leftSidePath: '[title="Status Code"]',
|
|
leftSideExpectedText: '200',
|
|
rightSidePath: '> :nth-child(2) [title="Status Code"]',
|
|
rightSideExpectedText: '200',
|
|
applyByCtrlEnter: false
|
|
});
|
|
|
|
if (Cypress.env('shouldCheckSrcAndDest')) {
|
|
serviceMapCheck();
|
|
|
|
checkFilter({
|
|
filter: 'src.name == ""',
|
|
leftSidePath: '[title="Source Name"]',
|
|
leftSideExpectedText: '[Unresolved]',
|
|
rightSidePath: '> :nth-child(2) [title="Source Name"]',
|
|
rightSideExpectedText: '[Unresolved]',
|
|
applyByCtrlEnter: false
|
|
});
|
|
|
|
checkFilter({
|
|
filter: `dst.name == "httpbin.mizu-tests"`,
|
|
leftSidePath: '> :nth-child(3) > :nth-child(2) > :nth-child(3) > :nth-child(2)',
|
|
leftSideExpectedText: 'httpbin.mizu-tests',
|
|
rightSidePath: '> :nth-child(2) > :nth-child(2) > :nth-child(2) > :nth-child(3) > :nth-child(2)',
|
|
rightSideExpectedText: 'httpbin.mizu-tests',
|
|
applyByCtrlEnter: false
|
|
});
|
|
}
|
|
|
|
checkFilter({
|
|
filter: 'request.method == "GET"',
|
|
leftSidePath: '> :nth-child(3) > :nth-child(1) > :nth-child(1) > :nth-child(2)',
|
|
leftSideExpectedText: 'GET',
|
|
rightSidePath: '> :nth-child(2) > :nth-child(2) > :nth-child(1) > :nth-child(1) > :nth-child(2)',
|
|
rightSideExpectedText: 'GET',
|
|
applyByCtrlEnter: true
|
|
});
|
|
|
|
checkFilter({
|
|
filter: 'request.path == "/get"',
|
|
leftSidePath: '> :nth-child(3) > :nth-child(1) > :nth-child(2) > :nth-child(2)',
|
|
leftSideExpectedText: '/get',
|
|
rightSidePath: '> :nth-child(2) > :nth-child(2) > :nth-child(1) > :nth-child(2) > :nth-child(2)',
|
|
rightSideExpectedText: '/get',
|
|
applyByCtrlEnter: false
|
|
});
|
|
|
|
checkFilter({
|
|
filter: 'src.ip == "127.0.0.1"',
|
|
leftSidePath: '[title="Source IP"]',
|
|
leftSideExpectedText: '127.0.0.1',
|
|
rightSidePath: '> :nth-child(2) [title="Source IP"]',
|
|
rightSideExpectedText: '127.0.0.1',
|
|
applyByCtrlEnter: false
|
|
});
|
|
|
|
checkFilterNoResults('request.method == "POST"');
|
|
|
|
function checkFilterNoResults(filterName) {
|
|
it(`checking the filter: ${filterName}. Expecting no results`, function () {
|
|
cy.get('#total-entries').then(number => {
|
|
const totalEntries = number.text();
|
|
|
|
// applying the filter
|
|
cy.get('.w-tc-editor-text').type(filterName);
|
|
cy.get('.w-tc-editor').should('have.attr', 'style').and('include', Cypress.env('greenFilterColor'));
|
|
cy.get('[type="submit"]').click();
|
|
|
|
// waiting for the entries number to load
|
|
cy.get('#total-entries', {timeout: refreshWaitTimeout}).should('have.text', totalEntries);
|
|
|
|
// the DOM should show 0 entries
|
|
cy.get('#entries-length').should('have.text', '0');
|
|
|
|
cy.get('[title="Fetch old records"]').click();
|
|
cy.get('#noMoreDataTop', {timeout: refreshWaitTimeout}).should('be.visible');
|
|
cy.get('#entries-length').should('have.text', '0'); // after loading all entries there should still be 0 entries
|
|
|
|
// reloading then waiting for the entries number to load
|
|
cy.reload();
|
|
cy.get('#total-entries', {timeout: refreshWaitTimeout}).should('have.text', totalEntries);
|
|
});
|
|
});
|
|
}
|
|
|
|
function checkIllegalFilter(illegalFilterName) {
|
|
it(`should show red search bar with the input: ${illegalFilterName}`, function () {
|
|
cy.reload();
|
|
cy.get('#total-entries').then(number => {
|
|
const totalEntries = number.text();
|
|
|
|
cy.get('.w-tc-editor-text').type(illegalFilterName);
|
|
cy.get('.w-tc-editor').should('have.attr', 'style').and('include', Cypress.env('redFilterColor'));
|
|
cy.get('[type="submit"]').click();
|
|
|
|
cy.get('[role="alert"]').should('be.visible');
|
|
cy.get('.w-tc-editor-text').clear();
|
|
|
|
// reloading then waiting for the entries number to load
|
|
cy.reload();
|
|
cy.get('#total-entries', {timeout: refreshWaitTimeout}).should('have.text', totalEntries);
|
|
});
|
|
});
|
|
}
|
|
|
|
function checkFilter(filterDetails) {
|
|
const {
|
|
filter,
|
|
leftSidePath,
|
|
rightSidePath,
|
|
rightSideExpectedText,
|
|
leftSideExpectedText,
|
|
applyByCtrlEnter
|
|
} = filterDetails;
|
|
|
|
const entriesForDeeperCheck = 5;
|
|
|
|
it(`checking the filter: ${filter}`, function () {
|
|
waitForFetch50AndPause();
|
|
|
|
cy.get('#total-entries').should('not.have.text', '0').then(number => {
|
|
const totalEntries = number.text();
|
|
|
|
cy.get(`#list [id^=entry]`).last().then(elem => {
|
|
const element = elem[0];
|
|
const entryId = getEntryId(element.id);
|
|
// checks the hover on the last entry (the only one in DOM at the beginning)
|
|
leftOnHoverCheck(entryId, leftSidePath, filter);
|
|
|
|
cy.get('.w-tc-editor-text').clear();
|
|
// applying the filter with alt+enter or with the button
|
|
cy.get('.w-tc-editor-text').type(`${filter}${applyByCtrlEnter ? '{ctrl+enter}' : ''}`);
|
|
cy.get('.w-tc-editor').should('have.attr', 'style').and('include', Cypress.env('greenFilterColor'));
|
|
if (!applyByCtrlEnter)
|
|
cy.get('[type="submit"]').click();
|
|
|
|
waitForFetch50AndPause();
|
|
|
|
// only one entry in DOM after filtering, checking all checks on it
|
|
leftTextCheck(entryId, leftSidePath, leftSideExpectedText);
|
|
leftOnHoverCheck(entryId, leftSidePath, filter);
|
|
|
|
rightTextCheck(rightSidePath, rightSideExpectedText);
|
|
rightOnHoverCheck(rightSidePath, filter);
|
|
checkRightSideResponseBody();
|
|
});
|
|
|
|
resizeToHugeMizu();
|
|
|
|
// checking only 'leftTextCheck' on all entries because the rest of the checks require more time
|
|
cy.get(`#list [id^=entry]`).each(elem => {
|
|
const element = elem[0];
|
|
let entryId = getEntryId(element.id);
|
|
leftTextCheck(entryId, leftSidePath, leftSideExpectedText);
|
|
});
|
|
|
|
// making the other 3 checks on the first X entries (longer time for each check)
|
|
deeperCheck(leftSidePath, rightSidePath, filter, rightSideExpectedText, entriesForDeeperCheck);
|
|
|
|
// reloading then waiting for the entries number to load
|
|
resizeToNormalMizu();
|
|
cy.reload();
|
|
cy.get('#total-entries', {timeout: refreshWaitTimeout}).should('have.text', totalEntries);
|
|
})
|
|
});
|
|
}
|
|
|
|
function waitForFetch50AndPause() {
|
|
// wait half a second and pause the stream to preserve the DOM
|
|
cy.wait(500);
|
|
cy.get('#pause-icon').click();
|
|
cy.get('#pause-icon').should('not.be.visible');
|
|
}
|
|
|
|
function deeperCheck(leftSidePath, rightSidePath, filterName, rightSideExpectedText, entriesNumToCheck) {
|
|
cy.get(`#list [id^=entry]`).each((element, index) => {
|
|
if (index < entriesNumToCheck) {
|
|
const entryId = getEntryId(element[0].id);
|
|
leftOnHoverCheck(entryId, leftSidePath, filterName);
|
|
|
|
cy.get(`#list #entry-${entryId}`).click();
|
|
rightTextCheck(rightSidePath, rightSideExpectedText);
|
|
rightOnHoverCheck(rightSidePath, filterName);
|
|
}
|
|
});
|
|
}
|
|
|
|
function checkRightSideResponseBody() {
|
|
// temporary fix, change to some "data-cy" attribute,
|
|
// this will fix the issue that happen because we have "response:" in the header of the right side
|
|
cy.get('#rightSideContainer > :nth-child(3)').contains('Response').click();
|
|
clickCheckbox('Decode Base64');
|
|
|
|
cy.get(`${Cypress.env('bodyJsonClass')}`).then(value => {
|
|
const encodedBody = value.text();
|
|
const decodedBody = atob(encodedBody);
|
|
const responseBody = JSON.parse(decodedBody);
|
|
|
|
const expectdJsonBody = {
|
|
args: RegExp({}),
|
|
url: RegExp('http://.*/get'),
|
|
headers: {
|
|
"User-Agent": RegExp('[REDACTED]'),
|
|
"Accept-Encoding": RegExp('gzip'),
|
|
"X-Forwarded-Uri": RegExp('/api/v1/namespaces/.*/services/.*/proxy/get')
|
|
}
|
|
};
|
|
|
|
expect(responseBody.args).to.match(expectdJsonBody.args);
|
|
expect(responseBody.url).to.match(expectdJsonBody.url);
|
|
expect(responseBody.headers['User-Agent']).to.match(expectdJsonBody.headers['User-Agent']);
|
|
expect(responseBody.headers['Accept-Encoding']).to.match(expectdJsonBody.headers['Accept-Encoding']);
|
|
expect(responseBody.headers['X-Forwarded-Uri']).to.match(expectdJsonBody.headers['X-Forwarded-Uri']);
|
|
|
|
cy.get(`${Cypress.env('bodyJsonClass')}`).should('have.text', encodedBody);
|
|
clickCheckbox('Decode Base64');
|
|
|
|
cy.get(`${Cypress.env('bodyJsonClass')} > `).its('length').should('be.gt', 1).then(linesNum => {
|
|
cy.get(`${Cypress.env('bodyJsonClass')} > >`).its('length').should('be.gt', linesNum).then(jsonItemsNum => {
|
|
checkPrettyAndLineNums(jsonItemsNum, decodedBody);
|
|
|
|
clickCheckbox('Line numbers');
|
|
checkPrettyOrNothing(jsonItemsNum, decodedBody);
|
|
|
|
clickCheckbox('Pretty');
|
|
checkPrettyOrNothing(jsonItemsNum, decodedBody);
|
|
|
|
clickCheckbox('Line numbers');
|
|
checkOnlyLineNumberes(jsonItemsNum, decodedBody);
|
|
});
|
|
});
|
|
});
|
|
}
|
|
|
|
function clickCheckbox(type) {
|
|
cy.contains(`${type}`).prev().children().click();
|
|
}
|
|
|
|
function checkPrettyAndLineNums(jsonItemsLen, decodedBody) {
|
|
decodedBody = decodedBody.replaceAll(' ', '');
|
|
cy.get(`${Cypress.env('bodyJsonClass')} >`).then(elements => {
|
|
const lines = Object.values(elements);
|
|
lines.forEach((line, index) => {
|
|
if (line.getAttribute) {
|
|
const cleanLine = getCleanLine(line);
|
|
const currentLineFromDecodedText = decodedBody.substring(0, cleanLine.length);
|
|
|
|
expect(cleanLine).to.equal(currentLineFromDecodedText, `expected the text in line number ${index + 1} to match the text that generated by the base64 decoding`)
|
|
|
|
decodedBody = decodedBody.substring(cleanLine.length);
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
function getCleanLine(lineElement) {
|
|
return (lineElement.innerText.substring(0, lineElement.innerText.length - 1)).replaceAll(' ', '');
|
|
}
|
|
|
|
function checkPrettyOrNothing(jsonItems, decodedBody) {
|
|
cy.get(`${Cypress.env('bodyJsonClass')} > `).should('have.length', jsonItems).then(text => {
|
|
const json = text.text();
|
|
expect(json).to.equal(decodedBody);
|
|
});
|
|
}
|
|
|
|
function checkOnlyLineNumberes(jsonItems, decodedText) {
|
|
cy.get(`${Cypress.env('bodyJsonClass')} >`).should('have.length', 1).and('have.text', decodedText);
|
|
cy.get(`${Cypress.env('bodyJsonClass')} > >`).should('have.length', jsonItems)
|
|
}
|
|
|
|
function serviceMapCheck() {
|
|
it('service map test', function () {
|
|
cy.intercept(`${Cypress.env('testUrl')}/servicemap/get`).as('serviceMapRequest');
|
|
cy.get('#total-entries').should('not.have.text', '0').then(() => {
|
|
cy.get('#total-entries').invoke('text').then(entriesNum => {
|
|
cy.get('[alt="service-map"]').click();
|
|
cy.wait('@serviceMapRequest').then(({response}) => {
|
|
const body = response.body;
|
|
const nodeParams = {
|
|
destination: 'httpbin.mizu-tests',
|
|
source: '127.0.0.1'
|
|
};
|
|
serviceMapAPICheck(body, parseInt(entriesNum), nodeParams);
|
|
cy.reload();
|
|
});
|
|
});
|
|
});
|
|
});
|
|
}
|
|
|
|
function serviceMapAPICheck(body, entriesNum, nodeParams) {
|
|
const {nodes, edges} = body;
|
|
|
|
expect(nodes.length).to.equal(Object.keys(nodeParams).length, `Expected nodes count`);
|
|
|
|
expect(edges.some(edge => edge.source.name === nodeParams.source)).to.be.true;
|
|
expect(edges.some(edge => edge.destination.name === nodeParams.destination)).to.be.true;
|
|
|
|
let count = 0;
|
|
edges.forEach(edge => {
|
|
count += edge.count;
|
|
if (edge.destination.name === nodeParams.destination) {
|
|
expect(edge.source.name).to.equal(nodeParams.source);
|
|
}
|
|
});
|
|
|
|
expect(count).to.equal(entriesNum);
|
|
}
|