430 lines
12 KiB
TypeScript
430 lines
12 KiB
TypeScript
import {
|
|
parseJsonRpcErrorResponse,
|
|
parseJsonRpcId,
|
|
parseJsonRpcResponse,
|
|
parseJsonRpcSuccessResponse,
|
|
} from "./parse";
|
|
import { jsonRpcCode, JsonRpcErrorResponse, JsonRpcRequest, JsonRpcSuccessResponse } from "./types";
|
|
|
|
describe("parse", () => {
|
|
describe("parseJsonRpcId", () => {
|
|
it("works for number IDs", () => {
|
|
const request: JsonRpcRequest = {
|
|
jsonrpc: "2.0",
|
|
id: 123,
|
|
method: "foo",
|
|
params: {},
|
|
};
|
|
expect(parseJsonRpcId(request)).toEqual(123);
|
|
});
|
|
|
|
it("works for string IDs", () => {
|
|
const request: JsonRpcRequest = {
|
|
jsonrpc: "2.0",
|
|
id: "329fg3b",
|
|
method: "foo",
|
|
params: {},
|
|
};
|
|
expect(parseJsonRpcId(request)).toEqual("329fg3b");
|
|
});
|
|
|
|
it("returns null for invaid IDs", () => {
|
|
// unset
|
|
{
|
|
const request = {
|
|
jsonrpc: "2.0",
|
|
method: "foo",
|
|
params: {},
|
|
};
|
|
expect(parseJsonRpcId(request)).toBeNull();
|
|
}
|
|
// wrong type (object)
|
|
{
|
|
const request = {
|
|
jsonrpc: "2.0",
|
|
id: { content: 123 },
|
|
method: "foo",
|
|
params: {},
|
|
};
|
|
expect(parseJsonRpcId(request)).toBeNull();
|
|
}
|
|
// wrong type (Array)
|
|
{
|
|
const request = {
|
|
jsonrpc: "2.0",
|
|
id: [1, 2, 3],
|
|
method: "foo",
|
|
params: {},
|
|
};
|
|
expect(parseJsonRpcId(request)).toBeNull();
|
|
}
|
|
// wrong type (null)
|
|
{
|
|
const request = {
|
|
jsonrpc: "2.0",
|
|
id: null,
|
|
method: "foo",
|
|
params: {},
|
|
};
|
|
expect(parseJsonRpcId(request)).toBeNull();
|
|
}
|
|
});
|
|
});
|
|
|
|
describe("parseJsonRpcErrorResponse", () => {
|
|
it("works for valid error", () => {
|
|
const response: any = {
|
|
jsonrpc: "2.0",
|
|
id: 123,
|
|
error: {
|
|
code: jsonRpcCode.serverError.default,
|
|
message: "Something bad happened",
|
|
data: [2, 3, 4],
|
|
},
|
|
};
|
|
expect(parseJsonRpcErrorResponse(response)).toEqual(response);
|
|
});
|
|
|
|
it("works for error with string ID", () => {
|
|
const response: any = {
|
|
jsonrpc: "2.0",
|
|
id: "a3g4g34g",
|
|
error: {
|
|
code: jsonRpcCode.parseError,
|
|
message: "Could not parse request ID",
|
|
},
|
|
};
|
|
expect(parseJsonRpcErrorResponse(response)).toEqual(response);
|
|
});
|
|
|
|
it("works for error with null ID", () => {
|
|
const response: any = {
|
|
jsonrpc: "2.0",
|
|
id: null,
|
|
error: {
|
|
code: jsonRpcCode.parseError,
|
|
message: "Could not parse request ID",
|
|
},
|
|
};
|
|
expect(parseJsonRpcErrorResponse(response)).toEqual(response);
|
|
});
|
|
|
|
it("works for error with null data", () => {
|
|
const response: any = {
|
|
jsonrpc: "2.0",
|
|
id: 123,
|
|
error: {
|
|
code: jsonRpcCode.serverError.default,
|
|
message: "Something bad happened",
|
|
data: null,
|
|
},
|
|
};
|
|
expect(parseJsonRpcErrorResponse(response)).toEqual(response);
|
|
});
|
|
|
|
it("works for error with unset data", () => {
|
|
const response: any = {
|
|
jsonrpc: "2.0",
|
|
id: 123,
|
|
error: {
|
|
code: jsonRpcCode.serverError.default,
|
|
message: "Something bad happened",
|
|
},
|
|
};
|
|
expect(parseJsonRpcErrorResponse(response)).toEqual(response);
|
|
});
|
|
|
|
it("throws for invalid type", () => {
|
|
const expectedError = /data must be JSON compatible dictionary/i;
|
|
expect(() => parseJsonRpcErrorResponse(undefined)).toThrowError(expectedError);
|
|
expect(() => parseJsonRpcErrorResponse(null)).toThrowError(expectedError);
|
|
expect(() => parseJsonRpcErrorResponse(false)).toThrowError(expectedError);
|
|
expect(() => parseJsonRpcErrorResponse("error")).toThrowError(expectedError);
|
|
expect(() => parseJsonRpcErrorResponse(42)).toThrowError(expectedError);
|
|
expect(() => parseJsonRpcErrorResponse(() => true)).toThrowError(expectedError);
|
|
expect(() => parseJsonRpcErrorResponse({ foo: () => true })).toThrowError(expectedError);
|
|
expect(() => parseJsonRpcErrorResponse({ foo: () => new Uint8Array([]) })).toThrowError(expectedError);
|
|
});
|
|
|
|
it("throws for invalid version", () => {
|
|
// wrong type
|
|
{
|
|
const response: any = {
|
|
jsonrpc: 2.0,
|
|
id: 123,
|
|
error: {
|
|
code: jsonRpcCode.serverError.default,
|
|
message: "Something bad happened",
|
|
},
|
|
};
|
|
expect(() => parseJsonRpcErrorResponse(response)).toThrowError(/got unexpected jsonrpc version/i);
|
|
}
|
|
// wrong version
|
|
{
|
|
const response: any = {
|
|
jsonrpc: "1.0",
|
|
id: 123,
|
|
error: {
|
|
code: jsonRpcCode.serverError.default,
|
|
message: "Something bad happened",
|
|
},
|
|
};
|
|
expect(() => parseJsonRpcErrorResponse(response)).toThrowError(/got unexpected jsonrpc version/i);
|
|
}
|
|
// unset
|
|
{
|
|
const response: any = {
|
|
id: 123,
|
|
error: {
|
|
code: jsonRpcCode.serverError.default,
|
|
message: "Something bad happened",
|
|
},
|
|
};
|
|
expect(() => parseJsonRpcErrorResponse(response)).toThrowError(/got unexpected jsonrpc version/i);
|
|
}
|
|
});
|
|
|
|
it("throws for invalid ID", () => {
|
|
// wrong type
|
|
{
|
|
const response: any = {
|
|
jsonrpc: "2.0",
|
|
id: [1, 2, 3],
|
|
error: {
|
|
code: jsonRpcCode.serverError.default,
|
|
message: "Something bad happened",
|
|
},
|
|
};
|
|
expect(() => parseJsonRpcErrorResponse(response)).toThrowError(/invalid id field/i);
|
|
}
|
|
// unset
|
|
{
|
|
const response: any = {
|
|
jsonrpc: "2.0",
|
|
error: {
|
|
code: jsonRpcCode.serverError.default,
|
|
message: "Something bad happened",
|
|
},
|
|
};
|
|
expect(() => parseJsonRpcErrorResponse(response)).toThrowError(/invalid id field/i);
|
|
}
|
|
});
|
|
|
|
it("throws for success response", () => {
|
|
const response: JsonRpcSuccessResponse = {
|
|
jsonrpc: "2.0",
|
|
id: 123,
|
|
result: 3000,
|
|
};
|
|
expect(() => parseJsonRpcErrorResponse(response)).toThrowError(/invalid error field/i);
|
|
});
|
|
});
|
|
|
|
describe("parseJsonRpcSuccessResponse", () => {
|
|
it("works for response with dict result", () => {
|
|
const response: any = {
|
|
jsonrpc: "2.0",
|
|
id: 123,
|
|
result: {
|
|
foo: "bar",
|
|
},
|
|
};
|
|
expect(parseJsonRpcSuccessResponse(response)).toEqual(response);
|
|
});
|
|
|
|
it("works for response with null result", () => {
|
|
const response: any = {
|
|
jsonrpc: "2.0",
|
|
id: 123,
|
|
result: null,
|
|
};
|
|
expect(parseJsonRpcSuccessResponse(response)).toEqual(response);
|
|
});
|
|
|
|
it("works for response with number ID", () => {
|
|
const response: any = {
|
|
jsonrpc: "2.0",
|
|
id: 123,
|
|
result: {},
|
|
};
|
|
expect(parseJsonRpcSuccessResponse(response)).toEqual(response);
|
|
});
|
|
|
|
it("works for response with string ID", () => {
|
|
const response: any = {
|
|
jsonrpc: "2.0",
|
|
id: "40gfh408g",
|
|
result: {},
|
|
};
|
|
expect(parseJsonRpcSuccessResponse(response)).toEqual(response);
|
|
});
|
|
|
|
it("throws for invalid type", () => {
|
|
const expectedError = /data must be JSON compatible dictionary/i;
|
|
expect(() => parseJsonRpcSuccessResponse(undefined)).toThrowError(expectedError);
|
|
expect(() => parseJsonRpcSuccessResponse(null)).toThrowError(expectedError);
|
|
expect(() => parseJsonRpcSuccessResponse(false)).toThrowError(expectedError);
|
|
expect(() => parseJsonRpcSuccessResponse("success")).toThrowError(expectedError);
|
|
expect(() => parseJsonRpcSuccessResponse(42)).toThrowError(expectedError);
|
|
expect(() => parseJsonRpcSuccessResponse(() => true)).toThrowError(expectedError);
|
|
expect(() => parseJsonRpcSuccessResponse({ foo: () => true })).toThrowError(expectedError);
|
|
});
|
|
|
|
it("throws for invalid version", () => {
|
|
// wrong type
|
|
{
|
|
const response: any = {
|
|
jsonrpc: 2.0,
|
|
id: 123,
|
|
result: 3000,
|
|
};
|
|
expect(() => parseJsonRpcSuccessResponse(response)).toThrowError(/got unexpected jsonrpc version/i);
|
|
}
|
|
// wrong version
|
|
{
|
|
const response: any = {
|
|
jsonrpc: "1.0",
|
|
id: 123,
|
|
result: 3000,
|
|
};
|
|
expect(() => parseJsonRpcSuccessResponse(response)).toThrowError(/got unexpected jsonrpc version/i);
|
|
}
|
|
// unset
|
|
{
|
|
const response: any = {
|
|
id: 123,
|
|
result: 3000,
|
|
};
|
|
expect(() => parseJsonRpcSuccessResponse(response)).toThrowError(/got unexpected jsonrpc version/i);
|
|
}
|
|
});
|
|
|
|
it("throws for invalid ID", () => {
|
|
// wrong type
|
|
{
|
|
const response: any = {
|
|
jsonrpc: "2.0",
|
|
id: [1, 2, 3],
|
|
result: 3000,
|
|
};
|
|
expect(() => parseJsonRpcSuccessResponse(response)).toThrowError(/invalid id field/i);
|
|
}
|
|
// wrong type
|
|
{
|
|
const response: any = {
|
|
jsonrpc: "2.0",
|
|
id: null,
|
|
result: 3000,
|
|
};
|
|
expect(() => parseJsonRpcSuccessResponse(response)).toThrowError(/invalid id field/i);
|
|
}
|
|
// unset
|
|
{
|
|
const response: any = {
|
|
jsonrpc: "2.0",
|
|
result: 3000,
|
|
};
|
|
expect(() => parseJsonRpcSuccessResponse(response)).toThrowError(/invalid id field/i);
|
|
}
|
|
});
|
|
|
|
it("throws for error response", () => {
|
|
const response: JsonRpcErrorResponse = {
|
|
jsonrpc: "2.0",
|
|
id: 123,
|
|
error: {
|
|
code: jsonRpcCode.parseError,
|
|
message: "Could not parse request ID",
|
|
},
|
|
};
|
|
expect(() => parseJsonRpcSuccessResponse(response)).toThrowError(/invalid result field/i);
|
|
});
|
|
});
|
|
|
|
describe("parseJsonRpcResponse", () => {
|
|
it("works for success response", () => {
|
|
const response: any = {
|
|
jsonrpc: "2.0",
|
|
id: 123,
|
|
result: 3000,
|
|
};
|
|
expect(parseJsonRpcResponse(response)).toEqual(response);
|
|
});
|
|
|
|
it("works for error response", () => {
|
|
const response: any = {
|
|
jsonrpc: "2.0",
|
|
id: 123,
|
|
error: {
|
|
code: jsonRpcCode.serverError.default,
|
|
message: "Something bad happened",
|
|
data: [2, 3, 4],
|
|
},
|
|
};
|
|
expect(parseJsonRpcResponse(response)).toEqual(response);
|
|
});
|
|
|
|
it("favours error if response is error and success at the same time", () => {
|
|
const response: any = {
|
|
jsonrpc: "2.0",
|
|
id: 123,
|
|
result: 3000,
|
|
error: {
|
|
code: jsonRpcCode.serverError.default,
|
|
message: "Something bad happened",
|
|
},
|
|
};
|
|
expect(parseJsonRpcResponse(response)).toEqual({
|
|
jsonrpc: "2.0",
|
|
id: 123,
|
|
error: {
|
|
code: jsonRpcCode.serverError.default,
|
|
message: "Something bad happened",
|
|
},
|
|
});
|
|
});
|
|
|
|
it("throws for invalid type", () => {
|
|
const expectedError = /data must be JSON compatible dictionary/i;
|
|
expect(() => parseJsonRpcResponse(undefined)).toThrowError(expectedError);
|
|
expect(() => parseJsonRpcResponse(null)).toThrowError(expectedError);
|
|
expect(() => parseJsonRpcResponse(false)).toThrowError(expectedError);
|
|
expect(() => parseJsonRpcResponse("error")).toThrowError(expectedError);
|
|
expect(() => parseJsonRpcResponse(42)).toThrowError(expectedError);
|
|
expect(() => parseJsonRpcResponse(() => true)).toThrowError(expectedError);
|
|
expect(() => parseJsonRpcResponse({ foo: () => true })).toThrowError(expectedError);
|
|
expect(() => parseJsonRpcResponse({ foo: () => new Uint8Array([]) })).toThrowError(expectedError);
|
|
});
|
|
|
|
it("throws for invalid version", () => {
|
|
const expectedError = /got unexpected jsonrpc version/i;
|
|
// wrong type
|
|
{
|
|
const response: any = {
|
|
jsonrpc: 2.0,
|
|
id: 123,
|
|
result: 3000,
|
|
};
|
|
expect(() => parseJsonRpcResponse(response)).toThrowError(expectedError);
|
|
}
|
|
// wrong version
|
|
{
|
|
const response: any = {
|
|
jsonrpc: "1.0",
|
|
id: 123,
|
|
result: 3000,
|
|
};
|
|
expect(() => parseJsonRpcResponse(response)).toThrowError(expectedError);
|
|
}
|
|
// unset
|
|
{
|
|
const response: any = {
|
|
id: 123,
|
|
result: 3000,
|
|
};
|
|
expect(() => parseJsonRpcResponse(response)).toThrowError(expectedError);
|
|
}
|
|
});
|
|
});
|
|
});
|