mirror of
https://github.com/kubeshark/kubeshark.git
synced 2026-02-27 17:12:21 +00:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cc4638afe6 | ||
|
|
acf3894824 | ||
|
|
6235217ead |
@@ -4,17 +4,19 @@
|
||||
"viewportHeight": 1080,
|
||||
"video": false,
|
||||
"screenshotOnRunFailure": false,
|
||||
|
||||
"testFiles":
|
||||
["tests/GuiPort.js",
|
||||
"tests/MultipleNamespaces.js",
|
||||
"tests/Redact.js",
|
||||
"testFiles": [
|
||||
"tests/GuiPort.js",
|
||||
"tests/MultipleNamespaces.js",
|
||||
"tests/Redact.js",
|
||||
"tests/NoRedact.js",
|
||||
"tests/Regex.js"],
|
||||
"tests/Regex.js",
|
||||
"tests/RegexMasking.js"
|
||||
],
|
||||
|
||||
"env": {
|
||||
"testUrl": "http://localhost:8899/",
|
||||
"redactHeaderContent": "User-Header[REDACTED]",
|
||||
"redactBodyContent": "{ \"User\": \"[REDACTED]\" }"
|
||||
"redactBodyContent": "{ \"User\": \"[REDACTED]\" }",
|
||||
"regexMaskingBodyContent": "[REDACTED]"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"watchForFileChanges":false,
|
||||
"viewportWidth": 1920,
|
||||
"viewportHeight": 3500,
|
||||
"video": false,
|
||||
"screenshotOnRunFailure": false,
|
||||
"testFiles": [
|
||||
"tests/IgnoredUserAgents.js"
|
||||
],
|
||||
|
||||
"env": {
|
||||
"testUrl": "http://localhost:8899/"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
import {isValueExistsInElement} from "../testHelpers/TrafficHelper";
|
||||
|
||||
it('Loading Mizu', function () {
|
||||
cy.visit(Cypress.env('testUrl'));
|
||||
});
|
||||
|
||||
it('going through each entry', function () {
|
||||
cy.get('#total-entries').then(number => {
|
||||
const getNum = () => {
|
||||
const numOfEntries = number.text();
|
||||
return parseInt(numOfEntries);
|
||||
};
|
||||
cy.wrap({ there: getNum }).invoke('there').should('be.gte', 25);
|
||||
|
||||
checkThatAllEntriesShown();
|
||||
|
||||
const entriesNum = getNum();
|
||||
[...Array(entriesNum).keys()].map(checkEntry);
|
||||
});
|
||||
});
|
||||
|
||||
function checkThatAllEntriesShown() {
|
||||
cy.get('#entries-length').then(number => {
|
||||
if (number.text() === '1')
|
||||
cy.get('[title="Fetch old records"]').click();
|
||||
});
|
||||
}
|
||||
|
||||
function checkEntry(entryIndex) {
|
||||
cy.get(`#entry-${entryIndex}`).click();
|
||||
cy.get('#tbody-Headers').should('be.visible');
|
||||
isValueExistsInElement(false, 'Ignored-User-Agent', '#tbody-Headers');
|
||||
}
|
||||
@@ -15,4 +15,3 @@ function doItFunc(number) {
|
||||
findLineAndCheck(getExpectedDetailsDict(podName, namespace));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
import {isValueExistsInElement} from "../testHelpers/TrafficHelper";
|
||||
|
||||
it('Loading Mizu', function () {
|
||||
cy.visit(Cypress.env('testUrl'));
|
||||
})
|
||||
|
||||
isValueExistsInElement(true, Cypress.env('regexMaskingBodyContent'), '.hljs');
|
||||
@@ -138,7 +138,7 @@ func TestTapGuiPort(t *testing.T) {
|
||||
return
|
||||
}
|
||||
|
||||
runCypressTests(t, fmt.Sprintf("npx cypress run --spec \"cypress/integration/tests/GuiPort.js\" --env port=%d", guiPort))
|
||||
runCypressTests(t, fmt.Sprintf("npx cypress run --spec \"cypress/integration/tests/GuiPort.js\" --env port=%d --config-file cypress/integration/configurations/Default.json", guiPort))
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -184,7 +184,7 @@ func TestTapAllNamespaces(t *testing.T) {
|
||||
return
|
||||
}
|
||||
|
||||
runCypressTests(t, fmt.Sprintf("npx cypress run --spec \"cypress/integration/tests/MultipleNamespaces.js\" --env name1=%v,name2=%v,name3=%v,namespace1=%v,namespace2=%v,namespace3=%v",
|
||||
runCypressTests(t, fmt.Sprintf("npx cypress run --spec \"cypress/integration/tests/MultipleNamespaces.js\" --env name1=%v,name2=%v,name3=%v,namespace1=%v,namespace2=%v,namespace3=%v --config-file cypress/integration/configurations/Default.json",
|
||||
expectedPods[0].Name, expectedPods[1].Name, expectedPods[2].Name, expectedPods[0].Namespace, expectedPods[1].Namespace, expectedPods[2].Namespace))
|
||||
}
|
||||
|
||||
@@ -233,7 +233,7 @@ func TestTapMultipleNamespaces(t *testing.T) {
|
||||
return
|
||||
}
|
||||
|
||||
runCypressTests(t, fmt.Sprintf("npx cypress run --spec \"cypress/integration/tests/MultipleNamespaces.js\" --env name1=%v,name2=%v,name3=%v,namespace1=%v,namespace2=%v,namespace3=%v",
|
||||
runCypressTests(t, fmt.Sprintf("npx cypress run --spec \"cypress/integration/tests/MultipleNamespaces.js\" --env name1=%v,name2=%v,name3=%v,namespace1=%v,namespace2=%v,namespace3=%v --config-file cypress/integration/configurations/Default.json",
|
||||
expectedPods[0].Name, expectedPods[1].Name, expectedPods[2].Name, expectedPods[0].Namespace, expectedPods[1].Namespace, expectedPods[2].Namespace))
|
||||
}
|
||||
|
||||
@@ -279,7 +279,7 @@ func TestTapRegex(t *testing.T) {
|
||||
return
|
||||
}
|
||||
|
||||
runCypressTests(t, fmt.Sprintf("npx cypress run --spec \"cypress/integration/tests/Regex.js\" --env name=%v,namespace=%v",
|
||||
runCypressTests(t, fmt.Sprintf("npx cypress run --spec \"cypress/integration/tests/Regex.js\" --env name=%v,namespace=%v --config-file cypress/integration/configurations/Default.json",
|
||||
expectedPods[0].Name, expectedPods[0].Namespace))
|
||||
}
|
||||
|
||||
@@ -377,7 +377,7 @@ func TestTapRedact(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
runCypressTests(t, fmt.Sprintf("npx cypress run --spec \"cypress/integration/tests/Redact.js\""))
|
||||
runCypressTests(t, fmt.Sprintf("npx cypress run --spec \"cypress/integration/tests/Redact.js\" --config-file cypress/integration/configurations/Default.json"))
|
||||
}
|
||||
|
||||
func TestTapNoRedact(t *testing.T) {
|
||||
@@ -429,7 +429,7 @@ func TestTapNoRedact(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
runCypressTests(t, "npx cypress run --spec \"cypress/integration/tests/NoRedact.js\"")
|
||||
runCypressTests(t, "npx cypress run --spec \"cypress/integration/tests/NoRedact.js\" --config-file cypress/integration/configurations/Default.json")
|
||||
}
|
||||
|
||||
func TestTapRegexMasking(t *testing.T) {
|
||||
@@ -480,41 +480,8 @@ func TestTapRegexMasking(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
redactCheckFunc := func() error {
|
||||
timestamp := time.Now().UnixNano() / int64(time.Millisecond)
|
||||
runCypressTests(t, "npx cypress run --spec \"cypress/integration/tests/RegexMasking.js\" --config-file cypress/integration/configurations/Default.json")
|
||||
|
||||
entries, err := getDBEntries(timestamp, defaultEntriesCount, 1*time.Second)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = checkEntriesAtLeast(entries, 1)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
firstEntry := entries[0]
|
||||
|
||||
entryUrl := fmt.Sprintf("%v/entries/%v", apiServerUrl, firstEntry["id"])
|
||||
requestResult, requestErr := executeHttpGetRequest(entryUrl)
|
||||
if requestErr != nil {
|
||||
return fmt.Errorf("failed to get entry, err: %v", requestErr)
|
||||
}
|
||||
|
||||
entry := requestResult.(map[string]interface{})["data"].(map[string]interface{})
|
||||
request := entry["request"].(map[string]interface{})
|
||||
|
||||
postData := request["postData"].(map[string]interface{})
|
||||
textData := postData["text"].(string)
|
||||
|
||||
if textData != "[REDACTED]" {
|
||||
return fmt.Errorf("unexpected result - body is not redacted")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
if err := retriesExecute(shortRetriesCount, redactCheckFunc); err != nil {
|
||||
t.Errorf("%v", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func TestTapIgnoredUserAgents(t *testing.T) {
|
||||
@@ -575,45 +542,7 @@ func TestTapIgnoredUserAgents(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
ignoredUserAgentsCheckFunc := func() error {
|
||||
timestamp := time.Now().UnixNano() / int64(time.Millisecond)
|
||||
|
||||
entries, err := getDBEntries(timestamp, defaultEntriesCount, 1*time.Second)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = checkEntriesAtLeast(entries, 1)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, entryInterface := range entries {
|
||||
entryUrl := fmt.Sprintf("%v/entries/%v", apiServerUrl, entryInterface["id"])
|
||||
requestResult, requestErr := executeHttpGetRequest(entryUrl)
|
||||
if requestErr != nil {
|
||||
return fmt.Errorf("failed to get entry, err: %v", requestErr)
|
||||
}
|
||||
|
||||
entry := requestResult.(map[string]interface{})["data"].(map[string]interface{})
|
||||
request := entry["request"].(map[string]interface{})
|
||||
|
||||
headers := request["_headers"].([]interface{})
|
||||
for _, headerInterface := range headers {
|
||||
header := headerInterface.(map[string]interface{})
|
||||
if header["name"].(string) != ignoredUserAgentCustomHeader {
|
||||
continue
|
||||
}
|
||||
|
||||
return fmt.Errorf("unexpected result - user agent is not ignored")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
if err := retriesExecute(shortRetriesCount, ignoredUserAgentsCheckFunc); err != nil {
|
||||
t.Errorf("%v", err)
|
||||
return
|
||||
}
|
||||
runCypressTests(t, "npx cypress run --spec \"cypress/integration/tests/IgnoredUserAgents.js\" --config-file cypress/integration/configurations/HugeMizu.json")
|
||||
}
|
||||
|
||||
func TestTapDumpLogs(t *testing.T) {
|
||||
|
||||
@@ -140,7 +140,7 @@ export const EntryItem: React.FC<EntryProps> = ({entry, style, headingMode}) =>
|
||||
setFocusedEntryId(entry.id.toString());
|
||||
}}
|
||||
style={{
|
||||
border: isSelected ? `1px ${entry.proto.backgroundColor} solid` : "1px transparent solid",
|
||||
border: isSelected && !headingMode ? `1px ${entry.proto.backgroundColor} solid` : "1px transparent solid",
|
||||
position: !headingMode ? "absolute" : "unset",
|
||||
top: style['top'],
|
||||
marginTop: !headingMode ? style['marginTop'] : "10px",
|
||||
|
||||
@@ -9,6 +9,8 @@ import filterUIExample2 from "./assets/filter-ui-example-2.png"
|
||||
import variables from '../variables.module.scss';
|
||||
import {useRecoilState} from "recoil";
|
||||
import queryAtom from "../recoil/query";
|
||||
import useKeyPress from "../hooks/useKeyPress"
|
||||
import shortcutsKeyboard from "../configs/shortcutsKeyboard"
|
||||
|
||||
interface FiltersProps {
|
||||
backgroundColor: string
|
||||
@@ -60,6 +62,8 @@ export const QueryForm: React.FC<QueryFormProps> = ({backgroundColor, ws, openWe
|
||||
setQuery(e.target.value);
|
||||
}
|
||||
|
||||
|
||||
|
||||
const handleSubmit = (e) => {
|
||||
ws.close();
|
||||
if (query) {
|
||||
@@ -70,6 +74,8 @@ export const QueryForm: React.FC<QueryFormProps> = ({backgroundColor, ws, openWe
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
useKeyPress(shortcutsKeyboard.ctrlEnter, handleSubmit, formRef.current);
|
||||
|
||||
return <>
|
||||
<form
|
||||
ref={formRef}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Button } from "@material-ui/core";
|
||||
import React, { useState } from "react";
|
||||
import React, { useState,useRef } from "react";
|
||||
import { adminUsername } from "../consts";
|
||||
import Api, { FormValidationErrorType } from "../helpers/api";
|
||||
import { toast } from 'react-toastify';
|
||||
@@ -7,6 +7,9 @@ import LoadingOverlay from "./LoadingOverlay";
|
||||
import { useCommonStyles } from "../helpers/commonStyle";
|
||||
import {useSetRecoilState} from "recoil";
|
||||
import entPageAtom, {Page} from "../recoil/entPage";
|
||||
import useKeyPress from "../hooks/useKeyPress"
|
||||
import shortcutsKeyboard from "../configs/shortcutsKeyboard"
|
||||
|
||||
|
||||
const api = Api.getInstance();
|
||||
|
||||
@@ -16,6 +19,7 @@ interface InstallPageProps {
|
||||
|
||||
export const InstallPage: React.FC<InstallPageProps> = ({onFirstLogin}) => {
|
||||
|
||||
const formRef = useRef(null);
|
||||
const classes = useCommonStyles();
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [password, setPassword] = useState("");
|
||||
@@ -54,13 +58,9 @@ export const InstallPage: React.FC<InstallPageProps> = ({onFirstLogin}) => {
|
||||
|
||||
}
|
||||
|
||||
const handleFormOnKeyPress = (e: React.KeyboardEvent<HTMLInputElement>) => {
|
||||
if (e.key === "Enter") {
|
||||
onFormSubmit();
|
||||
}
|
||||
};
|
||||
useKeyPress(shortcutsKeyboard.enter, onFormSubmit, formRef.current);
|
||||
|
||||
return <div className="centeredForm" onKeyPress={handleFormOnKeyPress}>
|
||||
return <div className="centeredForm" ref={formRef}>
|
||||
{isLoading && <LoadingOverlay/>}
|
||||
<div className="form-title left-text">Setup</div>
|
||||
<span className="form-subtitle">Welcome to Mizu, please set up the admin user to continue</span>
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
import { Button } from "@material-ui/core";
|
||||
import React, { useState } from "react";
|
||||
import React, { useState,useRef } from "react";
|
||||
import { toast } from "react-toastify";
|
||||
import Api from "../helpers/api";
|
||||
import { useCommonStyles } from "../helpers/commonStyle";
|
||||
import LoadingOverlay from "./LoadingOverlay";
|
||||
import entPageAtom, {Page} from "../recoil/entPage";
|
||||
import {useSetRecoilState} from "recoil";
|
||||
import useKeyPress from "../hooks/useKeyPress"
|
||||
import shortcutsKeyboard from "../configs/shortcutsKeyboard"
|
||||
|
||||
|
||||
const api = Api.getInstance();
|
||||
|
||||
@@ -15,6 +18,7 @@ const LoginPage: React.FC = () => {
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [username, setUsername] = useState("");
|
||||
const [password, setPassword] = useState("");
|
||||
const formRef = useRef(null);
|
||||
|
||||
const setEntPage = useSetRecoilState(entPageAtom);
|
||||
|
||||
@@ -36,13 +40,9 @@ const LoginPage: React.FC = () => {
|
||||
}
|
||||
}
|
||||
|
||||
const handleFormOnKeyPress = (e: React.KeyboardEvent<HTMLInputElement>) => {
|
||||
if (e.key === "Enter") {
|
||||
onFormSubmit();
|
||||
}
|
||||
};
|
||||
useKeyPress(shortcutsKeyboard.enter, onFormSubmit, formRef.current);
|
||||
|
||||
return <div className="centeredForm" onKeyPress={handleFormOnKeyPress}>
|
||||
return <div className="centeredForm" ref={formRef}>
|
||||
{isLoading && <LoadingOverlay/>}
|
||||
<div className="form-title left-text">Login</div>
|
||||
<div className="form-input">
|
||||
|
||||
7
ui/src/configs/shortcutsKeyboard.ts
Normal file
7
ui/src/configs/shortcutsKeyboard.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
const dictionary = {
|
||||
ctrlEnter : [{metaKey : true, code:"Enter"}, {ctrlKey:true, code:"Enter"}], // support Ctrl/command
|
||||
enter : [{code:"Enter"}]
|
||||
};
|
||||
|
||||
|
||||
export default dictionary;
|
||||
35
ui/src/hooks/useKeyPress.ts
Normal file
35
ui/src/hooks/useKeyPress.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import { useCallback, useEffect, useLayoutEffect, useRef } from 'react';
|
||||
|
||||
const useKeyPress = (eventConfigs, callback, node = null) => {
|
||||
// implement the callback ref pattern
|
||||
const callbackRef = useRef(callback);
|
||||
useLayoutEffect(() => {
|
||||
callbackRef.current = callback;
|
||||
});
|
||||
|
||||
// handle what happens on key press
|
||||
const handleKeyPress = useCallback(
|
||||
(event) => {
|
||||
// check if one of the key is part of the ones we want
|
||||
if (eventConfigs.some((eventConfig) => Object.keys(eventConfig).every(nameKey => eventConfig[nameKey] === event[nameKey]))) {
|
||||
callbackRef.current(event);
|
||||
}
|
||||
},
|
||||
[eventConfigs]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
// target is either the provided node or the document
|
||||
const targetNode = node ?? document;
|
||||
// attach the event listener
|
||||
targetNode &&
|
||||
targetNode.addEventListener("keydown", handleKeyPress);
|
||||
|
||||
// remove the event listener
|
||||
return () =>
|
||||
targetNode &&
|
||||
targetNode.removeEventListener("keydown", handleKeyPress);
|
||||
}, [handleKeyPress, node]);
|
||||
};
|
||||
|
||||
export default useKeyPress;
|
||||
Reference in New Issue
Block a user