Skip to content
Open

Fixes #319

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ jobs:
- uses: actions/checkout@v4

- id: extract_ref
run: echo ::set-output name=GIT_REF::$(echo ${GITHUB_REF##*/})
run: echo "GIT_REF=${GITHUB_REF##*/}" >> $GITHUB_OUTPUT

- uses: actions/setup-node@v4
with:
Expand Down Expand Up @@ -111,7 +111,7 @@ jobs:
- uses: actions/checkout@v4

- id: extract_ref
run: echo ::set-output name=GIT_REF::$(echo ${GITHUB_REF##*/})
run: echo "GIT_REF=${GITHUB_REF##*/}" >> $GITHUB_OUTPUT

- uses: actions/download-artifact@v4
with:
Expand Down
2 changes: 1 addition & 1 deletion .nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
16
25
2 changes: 1 addition & 1 deletion client/components/History.scss
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@import "../variables.scss";
@use "../variables.scss" as *;

#root .history {
padding: 1em 5% 0;
Expand Down
3 changes: 2 additions & 1 deletion client/components/Mermaid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ export const Mermaid = ({
} catch (e) {
setDiagram("");
console.error(e);
setError(e.str || `${e}`);
const error = e as { str?: string };
setError(error.str || `${e}`);
}
}, 1);
}, [name, chart]);
Expand Down
12 changes: 6 additions & 6 deletions client/components/MockEditor/KeyValueEditor.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import * as React from "react";
import { MinusCircleOutlined, PlusOutlined } from "@ant-design/icons";
import { Button, Form, Input, Select, Space } from "antd";
import { defaultMatcher } from "../../modules/types";
import { positiveMatchers, negativeMatchers, unaryMatchers } from "./utils";
import { FormListFieldData, FormListOperation } from "antd/lib/form/FormList";
import * as React from "react";
import { defaultMatcher } from "../../modules/types";
import { negativeMatchers, positiveMatchers, unaryMatchers } from "./utils";

export interface KeyValueEditorProps {
name: string[];
Expand Down Expand Up @@ -49,7 +49,7 @@ export const KeyValueEditorEngine = ({
<Form.Item
{...restField}
name={[fieldName, "key"]}
fieldKey={[fieldKey, "key"]}
fieldKey={fieldKey ? [fieldKey, "key"] : undefined}
>
<Input placeholder="Key" />
</Form.Item>
Expand All @@ -58,7 +58,7 @@ export const KeyValueEditorEngine = ({
<Form.Item
{...restField}
name={[fieldName, "matcher"]}
fieldKey={[fieldKey, "matcher"]}
fieldKey={fieldKey ? [fieldKey, "matcher"] : undefined}
>
<Select>
<Select.OptGroup label="Positive">
Expand All @@ -84,7 +84,7 @@ export const KeyValueEditorEngine = ({
<Form.Item
{...restField}
name={[fieldName, "value"]}
fieldKey={[fieldKey, "value"]}
fieldKey={fieldKey ? [fieldKey, "value"] : undefined}
hidden={unaryMatchers.includes(
getFieldValue([...name, fieldKey, "matcher"])
)}
Expand Down
23 changes: 11 additions & 12 deletions client/components/MockEditor/MockStaticResponseEditor.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,9 @@
import * as React from "react";
import {
Col, Form, InputNumber,
Radio,
RadioChangeEvent,
Row
} from "antd";
import { Col, Form, InputNumber, Radio, RadioChangeEvent, Row } from "antd";
import { getReasonPhrase } from "http-status-codes";
import * as React from "react";
import Code, { Language } from "../Code";
import { defaultResponseStatus } from "./utils";
import { KeyValueEditor } from "./KeyValueEditor";
import { defaultResponseStatus } from "./utils";

export const MockStaticResponseEditor = (): JSX.Element => {
const [bodyLanguage, setBodyLanguage] = React.useState<Language>("json");
Expand Down Expand Up @@ -38,9 +33,10 @@ export const MockStaticResponseEditor = (): JSX.Element => {
<InputNumber
min={100}
max={599}
onChange={(value?: string | number) => {
onChange={(value?: string | number | null) => {
setResponseStatus(typeof value === "number" ? value : NaN);
}} />
}}
/>
</Form.Item>
<span> {responseStatusText()}</span>
</Form.Item>
Expand All @@ -56,11 +52,14 @@ export const MockStaticResponseEditor = (): JSX.Element => {
<Radio.Group
options={languages}
value={bodyLanguage}
onChange={(e: RadioChangeEvent) => setBodyLanguage(e.target.value)}
onChange={(e: RadioChangeEvent) =>
setBodyLanguage(e.target.value)
}
optionType="button"
buttonStyle="solid"
size="small"
style={{ marginBottom: 5 }} />
style={{ marginBottom: 5 }}
/>
<Form.Item name={["response", "body"]} noStyle>
<Code language={bodyLanguage} />
</Form.Item>
Expand Down
2 changes: 1 addition & 1 deletion client/components/Mocks.scss
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@import "../variables.scss";
@use "../variables.scss" as *;

#root .mocks {
padding: 1em 5% 0;
Expand Down
3 changes: 3 additions & 0 deletions client/components/Navbar.scss
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,7 @@
padding-bottom: 5px;
}
}
.menu {
flex: auto;
}
}
4 changes: 3 additions & 1 deletion client/components/Navbar.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { Layout, Menu, Row } from "antd";
import * as React from "react";
import { Link, useLocation } from "react-router-dom";
import Logo from "../assets/logo180.png";
import { cleanQueryParams } from "../modules/utils";

import "./Navbar.scss";

const Navbar = (): JSX.Element => {
const location = useLocation();
// @ts-ignore

Check failure on line 10 in client/components/Navbar.tsx

View workflow job for this annotation

GitHub Actions / lint

Do not use "// @ts-ignore" because it alters compilation errors
const Logo = new URL("../assets/logo180.png", import.meta.url).href;
return (
<Layout.Header className="navbar">
<Row justify="start" align="middle">
Expand Down
1 change: 1 addition & 0 deletions client/components/Sidebar.scss
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
height: calc(100% - 3.5em);
.ant-menu-item-group-title {
padding-top: 1em;
height: 42px;
.ant-spin .ant-spin-dot {
top: 50%;
left: 100%;
Expand Down
2 changes: 1 addition & 1 deletion client/components/Visualize.scss
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@import "../variables.scss";
@use "../variables.scss" as *;

#root .visualize {
padding: 1em 8em 0;
Expand Down
5 changes: 4 additions & 1 deletion client/globals.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,7 @@ declare var basePath: string;
declare var version: string;
declare module "codemirror/mode/*";
declare module "codemirror/addon/*";
declare module "*.png";
declare module "*.png" {
const value: string;
export default value;
}
2 changes: 1 addition & 1 deletion client/modules/epics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@

const extractError = (error: AjaxResponse | AjaxError | SmockerError) => {
const ajaxError = error as AjaxResponse | AjaxError;
let message = ajaxError?.xhr?.response?.message || error["message"];
let message = ajaxError?.xhr?.response?.message || (error as any).message;

Check warning on line 37 in client/modules/epics.ts

View workflow job for this annotation

GitHub Actions / lint

Unexpected any. Specify a different type
if (message === "ajax error") {
message =
"Failed to connect to the server, please make sure it's still running";
Expand Down
23 changes: 15 additions & 8 deletions client/modules/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ function simplifyMultimap(multimap: { [x: string]: string[] }) {
}
newMultimap[key] = [...values];
return newMultimap;
}, {});
}, {} as Record<string, string | string[]>);
}

const headersToClean = [
Expand All @@ -102,12 +102,16 @@ const headersToClean = [
export const cleanupRequest = (historyEntry: Entry): EntryRequest => {
let request: EntryRequest = { ...historyEntry.request };
if (historyEntry.request.headers) {
request.headers = simplifyMultimap(historyEntry.request.headers);
request.headers = simplifyMultimap(
historyEntry.request.headers
) as Multimap;
// remove useless headers
request.headers = omit(request.headers, headersToClean);
}
if (historyEntry.request.query_params) {
request.query_params = simplifyMultimap(historyEntry.request.query_params);
request.query_params = simplifyMultimap(
historyEntry.request.query_params
) as Multimap;
}
request = omit(request, "body_string") as EntryRequest;
request = omit(request, "date") as EntryRequest;
Expand All @@ -127,7 +131,7 @@ export const cleanupRequest = (historyEntry: Entry): EntryRequest => {
export const bodyMatcherToPaths = (
bodyMatcher: unknown | Record<string, unknown>,
currentPath = "",
result = {}
result: Record<string, unknown> = {}
): Record<string, unknown> => {
if (Array.isArray(bodyMatcher)) {
bodyMatcher.forEach((item, index) => {
Expand All @@ -152,7 +156,9 @@ export const bodyMatcherToPaths = (
export const cleanupResponse = (historyEntry: Entry): EntryResponse => {
let response: EntryResponse = { ...historyEntry.response };
if (historyEntry.response.headers) {
response.headers = simplifyMultimap(historyEntry.response.headers);
response.headers = simplifyMultimap(
historyEntry.response.headers
) as Multimap;
// remove useless headers
response.headers = omit(response.headers, headersToClean);
}
Expand Down Expand Up @@ -192,11 +198,12 @@ export const formatQueryParams = (
Object.keys(params)
.reduce((acc: string[], key) => {
params[key].forEach((v: StringMatcher | string) => {
const value = v["value"] || v;
const isObject = typeof v === "object" && v !== null;
const value = isObject ? v.value : v;
const encodedValue = encodeURIComponent(value);
const param =
v["matcher"] && v["matcher"] !== defaultMatcher
? `${key}=>(${v["matcher"]} "${encodedValue}")`
isObject && v.matcher && v.matcher !== defaultMatcher
? `${key}=>(${v.matcher} "${encodedValue}")`
: `${key}=${encodedValue}`;
acc.push(param);
});
Expand Down
1 change: 1 addition & 0 deletions client/use-lodash-debounce.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
declare module "use-lodash-debounce";
20 changes: 12 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@
"targets": {
"default": {
"distDir": "./build/client",
"publicUrl": "./assets"
"publicUrl": "/assets"
}
},
"dependencies": {
"@ant-design/icons": "^4.x",
"@ant-design/icons": "^4.8.3",
"antd": "^4.16.9",
"classnames": "^2.2.6",
"codemirror": "^5.55.0",
Expand All @@ -44,16 +44,16 @@
},
"devDependencies": {
"@hot-loader/react-dom": "^16.10.2",
"@parcel/transformer-sass": "^2.0.0",
"@parcel/transformer-sass": "^2.16.3",
"@types/classnames": "^2.2.9",
"@types/codemirror": "0.0.96",
"@types/jest": "^26.0.3",
"@types/js-yaml": "^3.12.5",
"@types/lodash": "^4.14.157",
"@types/mermaid": "^8.2.1",
"@types/node": "^14.0.14",
"@types/react": "^16.9.41",
"@types/react-dom": "^16.9.2",
"@types/react": "^16.14.0",
"@types/react-dom": "^16.9.8",
"@types/react-redux": "^7.1.5",
"@types/react-router-dom": "^5.1.0",
"@types/redux": "^3.6.0",
Expand All @@ -66,7 +66,7 @@
"eslint-config-prettier": "^6.11.0",
"eslint-plugin-jest": "^23.17.1",
"eslint-plugin-react": "^7.20.2",
"husky": ">=1",
"husky": "4.2.5",
"jest": "^26.1.0",
"lint-staged": ">=10.2.11",
"parcel": "^2.0.0",
Expand All @@ -76,10 +76,14 @@
"sass": "^1.26.9",
"ts-jest": "^26.1.1",
"tslib": "^2.3.0",
"typescript": "^3.8.3"
"typescript": "^4.9.5"
},
"resolutions": {
"@types/react": "16.9.41"
"@types/react": "^16.14.0",
"lmdb-store": "2.0.0"
},
"overrides": {
"@ant-design/icons-svg": "4.4.2"
},
"alias": {
"react-dom": "@hot-loader/react-dom"
Expand Down
6 changes: 5 additions & 1 deletion server/services/mocks.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"sync"
"time"

log "github.com/sirupsen/logrus"
"github.com/smocker-dev/smocker/server/types"
"github.com/teris-io/shortid"
)
Expand Down Expand Up @@ -47,8 +48,11 @@ func NewMocks(sessions types.Sessions, historyRetention int, persistence Persist
historyRetention: historyRetention,
persistence: persistence,
}
if sessions != nil {
if len(sessions) > 0 {
s.sessions = sessions
log.Infof("Initialized mock service with %d session(s)", len(sessions))
} else {
log.Info("Initialized mock service with no sessions")
}
return s
}
Expand Down
9 changes: 9 additions & 0 deletions server/services/persistence.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,25 +140,32 @@ func (p *persistence) LoadSessions() (types.Sessions, error) {
p.mu.Lock()
defer p.mu.Unlock()
if p.persistenceDirectory == "" {
log.Debug("Persistence directory not set, skipping session loading")
return nil, nil
}
log.Debugf("Loading sessions from %q", p.persistenceDirectory)
if _, err := os.Stat(p.persistenceDirectory); os.IsNotExist(err) {
log.WithError(err).Warnf("Persistence directory %q does not exist", p.persistenceDirectory)
return nil, err
}
file, err := os.Open(filepath.Join(p.persistenceDirectory, sessionsFileName))
if err != nil {
log.WithError(err).Errorf("Unable to open sessions file %q", sessionsFileName)
return nil, err
}
defer file.Close()
bytes, err := io.ReadAll(file)
if err != nil {
log.WithError(err).Errorf("Unable to read sessions file %q", sessionsFileName)
return nil, err
}
var sessions types.Sessions
err = yaml.Unmarshal(bytes, &sessions)
if err != nil {
log.WithError(err).Errorf("Unable to unmarshal sessions from %q", sessionsFileName)
return nil, err
}
log.Infof("Loading %d session(s) from persistence", len(sessions))
var sessionsGroup errgroup.Group
var sessionsLock sync.Mutex
for i := range sessions {
Expand Down Expand Up @@ -213,8 +220,10 @@ func (p *persistence) LoadSessions() (types.Sessions, error) {
})
}
if err := sessionsGroup.Wait(); err != nil {
log.WithError(err).Error("Unable to load some sessions")
return nil, err
}
log.Infof("Successfully loaded %d session(s) from persistence", len(sessions))
return sessions, nil
}

Expand Down
Loading
Loading