Compare commits

...

3 Commits

Author SHA1 Message Date
Adam Kol
cc4638afe6 Cypress: two new tests --> IgnoredUserAgents and RegexMasking (#663) 2022-01-18 17:32:50 +02:00
M. Mert Yıldıran
acf3894824 Fix EntryItem border on heading mode (#661) 2022-01-18 17:37:58 +03:00
leon-up9
6235217ead Bug/UI/tra 4169 apply qury by enter (#660)
* add shortcuts listeners and config

* key added

* listen for shortcut on input

* refactoring listensing to Enter Press

* comment for support

Co-authored-by: Leon <>
2022-01-18 12:08:53 +02:00
12 changed files with 134 additions and 102 deletions

View File

@@ -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]"
}
}

View File

@@ -0,0 +1,14 @@
{
"watchForFileChanges":false,
"viewportWidth": 1920,
"viewportHeight": 3500,
"video": false,
"screenshotOnRunFailure": false,
"testFiles": [
"tests/IgnoredUserAgents.js"
],
"env": {
"testUrl": "http://localhost:8899/"
}
}

View File

@@ -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');
}

View File

@@ -15,4 +15,3 @@ function doItFunc(number) {
findLineAndCheck(getExpectedDetailsDict(podName, namespace));
});
}

View File

@@ -0,0 +1,7 @@
import {isValueExistsInElement} from "../testHelpers/TrafficHelper";
it('Loading Mizu', function () {
cy.visit(Cypress.env('testUrl'));
})
isValueExistsInElement(true, Cypress.env('regexMaskingBodyContent'), '.hljs');

View File

@@ -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) {

View File

@@ -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",

View File

@@ -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}

View File

@@ -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>

View File

@@ -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">

View 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;

View 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;