Skip to content

Commit

Permalink
v1.4.0
Browse files Browse the repository at this point in the history
  • Loading branch information
AndrewWalsh committed Nov 26, 2023
1 parent 2509d0c commit 068aea0
Show file tree
Hide file tree
Showing 10 changed files with 176 additions and 6 deletions.
2 changes: 1 addition & 1 deletion manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"manifest_version": 3,
"name": "OpenAPI DevTools",
"version": "1.3.3",
"version": "1.4.0",
"devtools_page": "index.html",
"permissions": [],
"icons": {
Expand Down
14 changes: 14 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"cookie": "^0.6.0",
"copy-to-clipboard": "^3.3.3",
"decode-uri-component": "^0.4.1",
"fast-querystring": "^1.1.2",
"framer-motion": "^10.16.4",
"fuse.js": "^6.6.2",
"genson-js": "^0.0.8",
Expand Down
Binary file modified resources/dist.zip
Binary file not shown.
18 changes: 18 additions & 0 deletions src/lib/RequestStore.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -211,3 +211,21 @@ it("parameterisation works after export and import", () => {
// @ts-expect-error accessing private property
expect(store.leafMap).toEqual(expected);
});

it("parameterisation works after export and import", () => {
const store = new RequestStore();
const req = createSimpleRequest(`${base}/1/2/a`);
store.insert(req, { foo: 1 });
store.parameterise(2, "/1/2/a", host);
const exported = store.export();
store.clear();
store.import(exported);
store.insert(req, { foo: 1 });
const expected = {
[host]: {
'/1/2/:param2': expect.any(Object),
}
};
// @ts-expect-error accessing private property
expect(store.leafMap).toEqual(expected);
});
52 changes: 52 additions & 0 deletions src/lib/__fixtures__/post-application-x-www-form-urlencoded.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import type { Entry } from "har-format";

const postXWWWFormUrlEncoded: Entry = {
_priority: "VeryHigh",
_resourceType: "document",
cache: {},
connection: "17359",
pageref: "page_10",
request: {
method: "POST",
url: "https://httpbin.org/post",
httpVersion: "http/2.0",
headers: [],
queryString: [],
cookies: [],
headersSize: -1,
bodySize: 94,
postData: {
mimeType: "application/x-www-form-urlencoded",
text: "custname=asdf&custtel=sadf&custemail=&size=medium&topping=cheese&delivery=11%3A00&comments=sdg",
},
},
response: {
status: 200,
statusText: "",
httpVersion: "http/2.0",
headers: [],
cookies: [],
content: {
size: 1411,
mimeType: "application/json",
},
redirectURL: "",
headersSize: -1,
bodySize: -1,
_transferSize: 1566,
},
serverIPAddress: "75.101.210.237",
startedDateTime: "2023-11-26T03:21:54.665Z",
time: 1121.7940000324434,
timings: {
blocked: 197.47300002474338,
dns: 0.007999999999981355,
ssl: 348.39799999999997,
connect: 615.2149999999999,
send: 0.31799999999998363,
wait: 307.29200002782795,
receive: 1.4879999798722565,
},
};

export default postXWWWFormUrlEncoded;
74 changes: 73 additions & 1 deletion src/lib/store-helpers/create-leaf.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,81 @@
import { it, expect } from "vitest";
import { defaultOptions } from "./persist-options";
import postJson from "../__fixtures__/post-application-json";
import postXWWWFormUrlEncoded from "../__fixtures__/post-application-x-www-form-urlencoded";
import createLeaf, { Params } from "./create-leaf";

it("creates a leaf", () => {
it("creates a leaf when request mime = application/x-www-form-urlencoded", () => {
const harRequest = postXWWWFormUrlEncoded;
const responseBody: Params["responseBody"] = { test: 1 };
const options = defaultOptions;
const leaf = createLeaf({ harRequest, responseBody, options });
expect(leaf).toEqual({
pathname: "/post",
methods: {
POST: {
"200": {
request: {
"application/x-www-form-urlencoded": {
body: {
type: "object",
properties: {
custname: {
type: "string",
},
custtel: {
type: "string",
},
custemail: {
type: "string",
},
size: {
type: "string",
},
topping: {
type: "string",
},
delivery: {
type: "string",
},
comments: {
type: "string",
},
},
required: [
"custname",
"custtel",
"custemail",
"size",
"topping",
"delivery",
"comments",
],
},
},
},
requestHeaders: undefined,
response: {
"application/json": {
body: {
type: "object",
properties: {
test: {
type: "integer",
},
},
required: ["test"],
},
},
},
responseHeaders: undefined,
queryParameters: undefined,
},
},
},
});
});

it("creates a leaf when mime = application/json for req and res", () => {
const harRequest = postJson;
const responseBody: Params["responseBody"] = { test: 1 };
const options = defaultOptions;
Expand Down
13 changes: 12 additions & 1 deletion src/lib/store-helpers/create-leaf.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,24 @@ import determineAuthFromHAR from "./authentication";
import { filterIgnoreHeaders } from "../../utils/headers";
import type { Options } from "../RequestStore";
import type { Entry } from "har-format";
import qs from 'fast-querystring';

const APPLICATION_JSON = "application/json";
const APPLICATION_X_WWW_FORM_URLENCODED = "application/x-www-form-urlencoded";

export type Params = {
harRequest: Entry;
responseBody: JSONType;
options: Options;
};

const parseRequestBody = (harRequest: Entry): JSONType => {
const { mimeType, text } = harRequest.request.postData || {};
if (mimeType === APPLICATION_JSON) return parseJSON(text);
else if (mimeType === APPLICATION_X_WWW_FORM_URLENCODED && text) return qs.parse(text) as JSONType;
return null;
};

function createLeaf({ harRequest, responseBody, options }: Params): Leaf {
const { enableMoreInfo } = options;
const authentication = determineAuthFromHAR(harRequest);
Expand All @@ -27,7 +38,7 @@ function createLeaf({ harRequest, responseBody, options }: Params): Leaf {
const statusCode = harRequest.response.status.toString();
const requestMime = harRequest.request.postData?.mimeType;
const responseMime = harRequest.response.content.mimeType;
const requestBody = parseJSON(harRequest.request.postData?.text);
const requestBody = parseRequestBody(harRequest);
const requestHeaders = entriesToJSONType(harRequest.request.headers);
const responseHeaders = entriesToJSONType(harRequest.response.headers);
const queryParameters = entriesToJSONType(harRequest.request.queryString);
Expand Down
2 changes: 1 addition & 1 deletion src/ui/ControlDynamic.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ const ControlDynamic = () => {
onClick={onClick}
key={outerKey + part}
>
{`/${truncateMiddle(part, 7, 3, "...")}`}
{`/${truncateMiddle(part, 12, 5, "...")}`}
</WrapItem>
</Tooltip>
);
Expand Down
6 changes: 4 additions & 2 deletions src/utils/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ const isValidJSONString = (content: string): boolean => {
};

const validStatuses = new Set(["GET", "POST", "PUT", "DELETE", "PATCH"]);
const validResourceTypes = new Set(["xhr", "fetch"]);
const validResourceTypes = new Set(["xhr", "fetch", "document"]);
const isValidStatus = (status: string) => validStatuses.has(status);
export const isValidRequest = async (
harRequest: chrome.devtools.network.Request
Expand All @@ -44,7 +44,9 @@ export const isValidRequest = async (
if (didNotReachServer) return false;
const content = await getContent(harRequest);
const isNotJSON = harRequest.response.content.mimeType !== "application/json" && !isValidJSONString(content);
if (isNotJSON) return false;
const isNotXWWWFormUrlEncoded = harRequest.request.postData?.mimeType !== "application/x-www-form-urlencoded";
const isNotValidMime = isNotJSON && isNotXWWWFormUrlEncoded;
if (isNotValidMime) return false;
const isNotValidStatus = !isValidStatus(harRequest.request.method);
if (isNotValidStatus) return false;
if (!isValidURL(harRequest.request.url)) return false;
Expand Down

0 comments on commit 068aea0

Please sign in to comment.