Skip to content
Snippets Groups Projects
Commit 85326a38 authored by Jack Hu's avatar Jack Hu
Browse files

Merge branch 'ts-migration' into 'main'

Typescript Migration

See merge request !1
parents dcc93443 aad6d9c6
No related branches found
No related tags found
1 merge request!1Typescript Migration
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
/coverage /coverage
# production # production
/build /dist
# misc # misc
.DS_Store .DS_Store
......
-----GRPC TESTS-----
randomProduct
39.50119981765747
product
37.52583360671997
allProducts
31.22728362083435
categories
29.51584138870239
allOrders
52.35934963226318
ordersByUser
42.86946668624878
user
31.468091630935668
allUsers
31.84824995994568
postOrder
32.73759984970093
patchUser
34.883433198928834
\ No newline at end of file
const grpc = require("@grpc/grpc-js");
const protoLoader = require("@grpc/proto-loader");
const PROTO_PATH = "./app.proto";
const packageDefinition = protoLoader.loadSync(PROTO_PATH, {
keepCase: true,
longs: String,
enums: String,
defaults: true,
oneofs: true,
});
const app = grpc.loadPackageDefinition(packageDefinition);
const getTests = (endpoint, user, product) => {
const client = new app.App(endpoint, grpc.credentials.createInsecure());
return [
{
name: "randomProduct",
run: async () => {
const response = await new Promise((resolve, reject) => {
client.getRandomProduct({}, function (_err, response) {
if (_err) reject(_err);
resolve(response);
});
});
return [0, response];
},
},
{
name: "product",
run: async () => {
const response = await new Promise((resolve, reject) => {
client.getProduct(
{ product_id: product },
function (_err, response) {
if (_err) reject(_err);
resolve(response);
},
);
});
return [0, response];
},
},
{
name: "allProducts",
run: async () => {
const response = await new Promise((resolve, reject) => {
client.getAllProducts({}, function (_err, response) {
if (_err) reject(_err);
resolve(response);
});
});
return [0, response];
},
},
{
name: "categories",
run: async () => {
const response = await new Promise((resolve, reject) => {
client.getAllCategories({}, function (_err, response) {
if (_err) reject(_err);
resolve(response);
});
});
return [0, response];
},
},
{
name: "allOrders",
run: async () => {
const response = await new Promise((resolve, reject) => {
client.getAllOrders({}, function (_err, response) {
if (_err) reject(_err);
resolve(response);
});
});
return [0, response];
},
},
{
name: "ordersByUser",
run: async () => {
const response = await new Promise((resolve, reject) => {
client.getAllUserOrders(
{ id: user },
function (_err, response) {
if (_err) reject(_err);
resolve(response);
},
);
});
return [0, response];
},
},
{
name: "user",
run: async () => {
const response = await new Promise((resolve, reject) => {
client.getUser(
{ id: user },
function (_err, response) {
if (_err) reject(_err);
resolve(response);
},
);
});
return [0, response];
},
},
{
name: "allUsers",
run: async () => {
const response = await new Promise((resolve, reject) => {
client.getAllUsers({}, function (_err, response) {
if (_err) reject(_err);
resolve(response);
});
});
return [0, response];
},
},
{
name: "postOrder",
run: async () => {
{
const response = await new Promise((resolve, reject) => {
client.postOrder(
{
user_id: user,
products: [
{
product_id: product,
quantity: 2,
},
],
total_amount: 600.0,
},
function (_err, response) {
if (_err) reject(_err);
resolve(response);
},
);
});
return [0, response];
}
},
},
{
name: "patchUser",
run: async () => {
const response = await new Promise((resolve, reject) => {
client.patchAccountDetails(
{
id: user,
email: "update@test.com",
name: "update test",
},
function (_err, response) {
if (_err) reject(_err);
resolve(response);
},
);
});
return [0, response];
},
},
];
};
module.exports = { getTests };
const rest = require("./restTests");
const grpc = require("./grpcTests");
const { performance } = require("perf_hooks");
const REST_ENDPOINT = "http://18.209.23.10:3000";
const GRPC_ENDPOINT = "18.209.23.10:3001";
const runTest = async (func) => {
const start = performance.now();
await func();
const end = performance.now();
return end-start;
}
const avgRuntime = async (func, times) => {
const promises = [];
for (let i = 0; i < times; i++) {
promises.push(runTest(func));
}
const results = await Promise.all(promises);
return results.reduce((acc, curr) => acc + curr) / times;
};
async function getExamples() {
let resp = await fetch(REST_ENDPOINT + "/randomproduct");
let body = await resp.json();
const prodId = body.id;
resp = await fetch(REST_ENDPOINT + "/users");
body = await resp.json();
const userId = body[0].id;
return { product: prodId, user: userId };
}
async function runTests() {
const {user, product} = await getExamples();
const ITERATIONS = 5;
console.log("-----GRPC TESTS-----");
for (const test of grpc.getTests(GRPC_ENDPOINT, user, product)) {
console.log(test.name);
console.log(await avgRuntime(test.run, ITERATIONS));
}
console.log("-----REST TESTS-----");
for (const test of rest.getTests(REST_ENDPOINT, user, product)) {
console.log(test.name);
console.log(await avgRuntime(test.run, ITERATIONS));
}
}
runTests();
This diff is collapsed.
...@@ -2,17 +2,29 @@ ...@@ -2,17 +2,29 @@
"name": "lab1-measure", "name": "lab1-measure",
"version": "1.0.0", "version": "1.0.0",
"description": "", "description": "",
"main": "main.js", "main": "dist/main.js",
"scripts": { "scripts": {
"start": "node main.js", "start": "tsc && cp public/* dist && node dist/main.js",
"test": "echo \"Error: no test specified\" && exit 1" "test": "echo \"Error: no test specified\" && exit 1"
}, },
"author": "based JAML", "author": "based JAML",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"@grpc/grpc-js": "^1.9.0", "@grpc/grpc-js": "1.9.0",
"@grpc/proto-loader": "^0.7.8", "@grpc/proto-loader": "^0.7.8",
"@types/express": "^4.17.21",
"benchmark": "^2.1.4", "benchmark": "^2.1.4",
"google-protobuf": "^3.21.2" "express": "^4.18.2",
"express-ws": "^5.0.2",
"google-protobuf": "^3.21.2",
"nice-grpc": "^2.1.7",
"path": "^0.12.7",
"typescript": "^5.3.3",
"uuidv4": "^6.2.13"
},
"devDependencies": {
"@types/express-ws": "^3.0.4",
"grpc-tools": "^1.12.4",
"ts-proto": "^1.167.2"
} }
} }
\ No newline at end of file
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>SE464 Lab Testing</title>
</head>
<body>
<h1>SE 464 Benchmarker</h1>
<noscript>
For full functionality of this site it is necessary to enable JavaScript.
Here are the <a href="https://www.enable-javascript.com/">
instructions how to enable JavaScript in your web browser</a>.
</noscript>
<p>Input your AWS EC2/LoadBalancer URL</p>
<form action="viewResults" method="post">
<input type="text" name="url" id="url" required>
<input type="submit" value="Submit">
</body>
</html>
\ No newline at end of file
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>SE464 Lab Test Results</title>
<style>
table {
border-collapse: collapse;
}
th,
td {
border: 1px solid #dddddd;
text-align: left;
padding: 8px;
}
.success {
color: green;
}
.fail {
color: orange;
}
tr:nth-child(even) {
background-color: #f2f2f2;
}
</style>
</head>
<body>
<h1>Results for SE464 <span id="aws-url"></span></h1>
<div>
<label for="iterations">Rerun with number of iterations:</label>
<input type="text" id="iterations">
<button type="button">Submit</button>
</div>
<div id="results"></div>
</body>
<script>
const urlParts = window.location.href.split('/');
const id = urlParts[urlParts.length - 1]
const awsUrl = atob(id);
const titleHeading = document.getElementById('aws-url');
titleHeading.innerHTML = `${awsUrl}`;
const socket = new WebSocket(`/results/${id}`);
// Listen for messages
socket.addEventListener("message", (event) => {
try {
const data = JSON.parse(event.data);
const restJsonData = data["rest"];
const grpcJsonData = data["grpc"];
document.getElementById('results').replaceChildren(jsonToTable("REST", restJsonData));
document.getElementById('results').appendChild(jsonToTable("gRPC", grpcJsonData));
} catch (e) {
console.error(e);
}
});
document.querySelector('button').addEventListener('click', () => {
const iterations = document.getElementById('iterations').value;
socket.send(iterations);
});
function jsonToTable(title, jsonData) {
// Create a table
const div = document.createElement('div');
const titleElement = document.createElement('h2');
titleElement.textContent = title;
div.appendChild(titleElement);
const table = document.createElement('table');
for (const [k, v] of Object.entries(jsonData)) {
const row = document.createElement('tr');
const td1 = document.createElement('td');
const td2 = document.createElement('td');
td1.textContent = k;
td2.textContent = v["time"] + ' ms';
td2.className = v["ok"] ? 'success' : 'fail';
row.appendChild(td1);
row.appendChild(td2);
table.appendChild(row);
}
div.appendChild(table);
// Return the table
return div;
}
</script>
</html>
\ No newline at end of file
-----REST TESTS-----
randomProduct
50.12581658363342
product
33.34259166717529
allProducts
34.9744167804718
categories
32.45142498016357
allOrders
62.56571636199951
ordersByUser
52.71434187889099
user
31.619408416748048
allUsers
31.58545837402344
postOrder
36.04820818901062
patchUser
35.95475001335144
\ No newline at end of file
const getTests = (endpoint, user, product) => [
// {
// run: async () => {
// const resp = await fetch(endpoint + "/");
// const body = await resp.json();
// return [resp.status, body];
// },
// },
{
name: "randomProduct",
run: async () => {
const resp = await fetch(endpoint + "/randomproduct");
const body = await resp.json();
return [resp.status, body];
},
},
{
name: "product",
run: async () => {
const resp = await fetch(
`${endpoint}/product/${product}`,
);
const body = await resp.json();
return [resp.status, body];
},
},
{
name: "allProducts",
run: async () => {
const resp = await fetch(endpoint + "/products");
const body = await resp.json();
return [resp.status, body];
},
},
{
name: "categories",
run: async () => {
const resp = await fetch(endpoint + "/categories");
const body = await resp.json();
return [resp.status, body];
},
},
{
name: "allOrders",
run: async () => {
const resp = await fetch(endpoint + "/allorders");
const body = await resp.json();
return [resp.status, body];
},
},
{
name: "ordersByUser",
run: async () => {
const resp = await fetch(`${endpoint}/orders?userId=${user}`);
const body = await resp.json();
return [resp.status, body];
},
},
{
name: "user",
run: async () => {
const resp = await fetch(
`${endpoint}/user/${user}`,
);
const body = await resp.json();
return [resp.status, body];
},
},
{
name: "allUsers",
run: async () => {
const resp = await fetch(endpoint + "/users");
const body = await resp.json();
return [resp.status, body];
},
},
{
name: "postOrder",
run: async () => {
const resp = await fetch(endpoint + "/orders", {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify({
user_id: user,
products: [
{
product_id: product,
quantity: 2,
},
],
total_amount: 600.0,
}),
});
const body = null;
return [resp.status, body];
},
},
{
name: "patchUser",
run: async () => {
const resp = await fetch(
endpoint + `/user/${user}`,
{
method: "PATCH",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify({
id: user,
email: "update@test.com",
name: "update test",
}),
},
);
const body = null;
return [resp.status, body];
},
},
];
module.exports = { getTests };
This diff is collapsed.
const constants = {
TEST_USER_ID: "5b4b67e2-3b09-4309-8de2-82cc469fc1cc",
TEST_PRODUCT_ID: "dc878081-060b-4a6c-9038-02069f1ecef8",
TEST_ORDER_ID: "f38c26bf-8583-4e6f-88e9-0492490e47be",
TEST_ORDER: {
userId: "05843a96-1d34-43fb-88ca-0567e2f39ef6",
products: [{ productId: "0d00fb9d-0733-4c57-956f-85d52c1d14ee", quantity: 1 }],
totalAmount: 8
},
TEST_UPDATE: {
id: "05843a96-1d34-43fb-88ca-0567e2f39ef6",
password: "test123"
},
EXPECTED_USER: {
id: "5b4b67e2-3b09-4309-8de2-82cc469fc1cc",
email: "JamesWilliams@gmail.com",
},
EXPECTED_PRODUCT: {
id: "dc878081-060b-4a6c-9038-02069f1ecef8",
stock: 167,
price: 12,
name: "Shoes",
description: "Shoes for sale",
categoryId: "44adf4f9-cdd3-49ba-9788-eaed531580de"
},
EXPECTED_ORDER: {
id: "f38c26bf-8583-4e6f-88e9-0492490e47be",
products: [{ "productId": "d3e11810-8b5a-4468-a781-84109dd7569a", "quantity": 2 }]
},
};
export default constants;
\ No newline at end of file
import { UserPatchRequest } from "./compiled_proto/app";
import { Category, Order, Product, TestResults, User } from "./types";
export interface ITestSuite {
testRandomProduct(): Promise<Product>;
testUserById(id: string): Promise<User>;
testAllProducts(categoryId?: string): Promise<Product[]>;
testProductById(productId: string): Promise<Product>;
testAllCategories(): Promise<Category[]>;
testAllOrders(): Promise<Order[]>;
testOrdersByUser(id: string): Promise<Order[]>;
testOrderById(id: string): Promise<Order>;
testAllUsers(): Promise<User[]>;
testInsertOrder(order: Order): Promise<void>;
updateUser(patch: UserPatchRequest): Promise<void>;
runSuite(iterations: number): Promise<TestResults>;
}
\ No newline at end of file
import express from 'express';
import expressWs from 'express-ws';
import path from 'path';
import { runTests } from './testing';
const { app } = expressWs(express());
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
const resultsCache = {};
app.get('/', (req, res) => {
res.sendFile(path.join(__dirname, 'index.html'));
});
app.post('/viewResults', (req, res) => {
const url = req.body.url;
const id = btoa(url);
res.redirect(`/viewResults/${id}`);
});
app.get('/viewResults/:id', (req, res) => {
res.sendFile(path.join(__dirname, 'results.html'));
});
app.ws('/results/:id', async (ws, req) => {
const awsUrl = atob(req.params.id);
const iterations: number = Number(req.query.iterations) || 1;
if (resultsCache[awsUrl]) {
ws.send(JSON.stringify(resultsCache[awsUrl]));
} else {
runTests(awsUrl, resultsCache, iterations, ws);
}
ws.onmessage = (msg) => {
const iterations = Number(msg.data);
runTests(awsUrl, resultsCache, iterations, ws);
};
});
app.listen(80, () => {
console.log('Server is running on port 80');
});
...@@ -5,7 +5,7 @@ service App { ...@@ -5,7 +5,7 @@ service App {
rpc GetRandomProduct (EmptyRequest) returns (Product) {} rpc GetRandomProduct (EmptyRequest) returns (Product) {}
rpc GetAllProducts (EmptyRequest) returns (Products) {} rpc GetAllProducts (AllProductsRequest) returns (Products) {}
rpc GetAllCategories (EmptyRequest) returns (Categories) {} rpc GetAllCategories (EmptyRequest) returns (Categories) {}
...@@ -28,13 +28,16 @@ message EmptyRequest {} ...@@ -28,13 +28,16 @@ message EmptyRequest {}
// Products // Products
message AllProductsRequest {
optional string category_id = 1;
}
message ProductRequest { message ProductRequest {
string product_id = 1; string product_id = 1;
} }
message Product { message Product {
string category_id = 1; string category_id = 1;
string images = 2;
int64 stock = 3; int64 stock = 3;
int64 price = 4; int64 price = 4;
string description = 5; string description = 5;
......
import RestTestSuite from "./tests/restTests";
import GrpcTestSuite from "./tests/grpcTests";
import { performance } from "perf_hooks";
import { TestResult } from "./types";
const runTest: (func: () => any, expected?: any) => Promise<TestResult> = async (func: () => any, expected?: any) => {
const start = performance.now();
const result = await func();
const end = performance.now();
return {
ok: expected != null ? JSON.stringify(result) === JSON.stringify(expected) : true,
time: end - start
};
}
export const avgRuntime: (func: () => any, iterations: number, expected?: any) => Promise<TestResult> = async (func: () => any, iterations: number, expected?: any) => {
const promises = [];
for (let i = 0; i < iterations; i++) {
promises.push(runTest(func, expected));
}
const results = await Promise.all(promises);
return {
ok: results.reduce((acc, curr) => acc && curr.ok, true),
time: results.reduce((acc, curr) => acc + curr.time, 0) / iterations
};
};
export async function runTests(awsUrl: string, resultCache: any, iterations: number, ws?: any) {
const restTestSuite = new RestTestSuite(awsUrl);
const grpcTestSuite = new GrpcTestSuite(awsUrl);
// Warmup
await restTestSuite.runSuite(1);
await grpcTestSuite.runSuite(1);
resultCache[awsUrl] = {};
resultCache[awsUrl]["rest"] = await restTestSuite.runSuite(iterations);
resultCache[awsUrl]["grpc"] = await grpcTestSuite.runSuite(iterations);
if (ws)
ws.send(JSON.stringify(resultCache[awsUrl]));
}
import { ITestSuite } from "../interfaces";
import { AppClient, AppDefinition } from "../compiled_proto/app";
import { createChannel, createClient } from 'nice-grpc';
import { Order, TestResults, UserPatchRequest } from "../types";
import { avgRuntime } from "../testing";
import constants from "../constants";
import { uuid } from "uuidv4";
export default class GrpcTestSuite implements ITestSuite {
private channel: any;
private client: AppClient;
constructor(ip: string) {
this.channel = createChannel(`${ip}:3001`);
this.client = createClient(AppDefinition, this.channel);
}
public async testRandomProduct(): Promise<any> {
try {
const data = await this.client.getRandomProduct({});
return data;
} catch (e) {
console.error(e);
return null;
}
}
public async testUserById(id: string): Promise<any> {
try {
const data = await this.client.getUser({ id });
return data;
} catch (e) {
console.error(e);
return null;
}
}
public async testAllProducts(categoryId?: string): Promise<any> {
try {
const data = await this.client.getAllProducts({ categoryId });
return data;
} catch (e) {
console.error(e);
return null;
}
}
public async testProductById(productId: string): Promise<any> {
try {
const data = await this.client.getProduct({ productId });
return data;
} catch (e) {
console.error(e);
return null;
}
}
public async testAllCategories(): Promise<any> {
try {
const data = await this.client.getAllCategories({});
return data;
} catch (e) {
console.error(e);
return null;
}
}
public async testAllOrders(): Promise<any> {
try {
const data = await this.client.getAllOrders({});
return data;
} catch (e) {
console.error(e);
return null;
}
}
public async testOrdersByUser(id: string): Promise<any> {
try {
const data = await this.client.getAllUserOrders({ id });
return data;
} catch (e) {
console.error(e);
return null;
}
}
public async testOrderById(id: string): Promise<any> {
try {
const data = await this.client.getOrder({ id });
return data;
} catch (e) {
console.error(e);
return null;
}
}
public async testAllUsers(): Promise<any> {
try {
const data = await this.client.getAllUsers({});
return data;
} catch (e) {
console.error(e);
return null;
}
}
public async testInsertOrder(order: Order): Promise<any> {
try {
const data = await this.client.postOrder(order);
return data;
} catch (e) {
console.error(e);
return null;
}
}
public async updateUser(patch: UserPatchRequest): Promise<any> {
try {
const data = await this.client.patchAccountDetails(patch);
return data;
} catch (e) {
console.error(e);
return null;
}
}
public async runSuite(iterations: number): Promise<TestResults> {
const results: TestResults = {
randomProduct: {
ok: false,
time: 0
},
userById: {
ok: false,
time: 0
},
allProducts: {
ok: false,
time: 0
},
productById: {
ok: false,
time: 0
},
allCategories: {
ok: false,
time: 0
},
allOrders: {
ok: false,
time: 0
},
ordersByUser: {
ok: false,
time: 0
},
orderById: {
ok: false,
time: 0
},
allUsers: {
ok: false,
time: 0
},
insertOrder: {
ok: false,
time: 0
},
updateUser: {
ok: false,
time: 0
}
};
results.randomProduct = await avgRuntime(async () => await this.testRandomProduct(), iterations);
results.userById = await avgRuntime(async () => await this.testUserById(constants.TEST_USER_ID), iterations, constants.EXPECTED_USER);
results.allProducts = await avgRuntime(async () => await this.testAllProducts(), iterations);
results.productById = await avgRuntime(async () => await this.testProductById(constants.TEST_PRODUCT_ID), iterations, constants.EXPECTED_PRODUCT);
results.allCategories = await avgRuntime(async () => await this.testAllCategories(), iterations);
results.allOrders = await avgRuntime(async () => await this.testAllOrders(), iterations);
results.ordersByUser = await avgRuntime(async () => await this.testOrdersByUser(constants.TEST_USER_ID), iterations);
results.orderById = await avgRuntime(async () => await this.testOrderById(constants.TEST_ORDER_ID), iterations, constants.EXPECTED_ORDER);
results.allUsers = await avgRuntime(async () => await this.testAllUsers(), iterations);
results.insertOrder = await avgRuntime(async () => await this.testInsertOrder({ id: uuid(), ...constants.TEST_ORDER }), iterations);
results.updateUser = await avgRuntime(async () => await this.updateUser(constants.TEST_UPDATE), iterations);
return results;
}
}
\ No newline at end of file
import { ITestSuite } from '../interfaces';
import { Category, Order, Product, TestResults, User, UserPatchRequest } from '../types';
import { avgRuntime } from '../testing';
import { uuid } from 'uuidv4';
import constants from '../constants';
export default class RestTestSuite implements ITestSuite {
private endpoint: string;
constructor(ip: string) {
this.endpoint = `http://${ip}:3000`;
}
public async testRandomProduct(): Promise<Product> {
try {
const resp = await fetch(this.endpoint + "/randomproduct");
if (!resp.ok) throw new Error("Failed to fetch random product");
const json = await resp.json();
return json;
} catch (e) {
console.error(e);
return null;
}
}
public async testUserById(id: string): Promise<User> {
try {
const resp = await fetch(this.endpoint + "/user/" + id);
if (!resp.ok) throw new Error("Failed to fetch user by id");
const json = await resp.json();
return json;
} catch (e) {
console.error("error");
return null;
}
}
public async testAllProducts(categoryId?: string): Promise<Product[]> {
try {
const resp = await fetch(this.endpoint + "/products" + (categoryId ? "?categoryId=" + categoryId : ""));
if (!resp.ok) throw new Error("Failed to fetch all products");
const json = await resp.json();
return json;
} catch (e) {
console.error(e);
return null;
}
}
public async testProductById(productId: string): Promise<Product> {
try {
const resp = await fetch(this.endpoint + "/product/" + productId);
if (!resp.ok) throw new Error("Failed to fetch product by id");
const json = await resp.json();
return json;
} catch (e) {
console.error(e);
return null;
}
}
public async testAllCategories(): Promise<Category[]> {
try {
const resp = await fetch(this.endpoint + "/categories");
if (!resp.ok) throw new Error("Failed to fetch all categories");
const json = await resp.json();
return json;
} catch (e) {
console.error(e);
return null;
}
}
public async testAllOrders(): Promise<Order[]> {
try {
const resp = await fetch(this.endpoint + "/allorders");
if (!resp.ok) throw new Error("Failed to fetch all orders");
const json = await resp.json();
return json;
} catch (e) {
console.error(e);
return null;
}
}
public async testOrdersByUser(id: string): Promise<Order[]> {
try {
const resp = await fetch(this.endpoint + "/orders?id=" + id);
if (!resp.ok) throw new Error("Failed to fetch orders by user");
const json = await resp.json();
return json;
} catch (e) {
console.error(e);
return null;
}
}
public async testOrderById(id: string): Promise<Order> {
try {
const resp = await fetch(this.endpoint + "/order/" + id);
if (!resp.ok) throw new Error("Failed to fetch order by id");
const json = await resp.json();
return json;
} catch (e) {
console.error(e);
return null;
}
}
public async testAllUsers(): Promise<User[]> {
try {
const resp = await fetch(this.endpoint + "/users");
if (!resp.ok) throw new Error("Failed to fetch all users");
const json = await resp.json();
return json;
} catch (e) {
console.error(e);
return null;
}
}
public async testInsertOrder(order: Order): Promise<void> {
try {
const resp = await fetch(this.endpoint + "/orders", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(order)
});
if (!resp.ok) throw new Error("Failed to insert order");
} catch (e) {
console.error(e);
}
}
public async updateUser(patch: UserPatchRequest): Promise<void> {
try {
const resp = await fetch(this.endpoint + `/user/${patch.id}`, {
method: "PATCH",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(patch)
});
if (!resp.ok) throw new Error("Failed to update user");
} catch (e) {
console.error(e);
}
}
public async runSuite(iterations: number): Promise<TestResults> {
const results: TestResults = {
randomProduct: {
ok: false,
time: 0
},
userById: {
ok: false,
time: 0
},
allProducts: {
ok: false,
time: 0
},
productById: {
ok: false,
time: 0
},
allCategories: {
ok: false,
time: 0
},
allOrders: {
ok: false,
time: 0
},
ordersByUser: {
ok: false,
time: 0
},
orderById: {
ok: false,
time: 0
},
allUsers: {
ok: false,
time: 0
},
insertOrder: {
ok: false,
time: 0
},
updateUser: {
ok: false,
time: 0
}
};
results.randomProduct = await avgRuntime(async () => await this.testRandomProduct(), iterations);
results.userById = await avgRuntime(async () => await this.testUserById(constants.TEST_USER_ID), iterations, constants.EXPECTED_USER);
results.allProducts = await avgRuntime(async () => await this.testAllProducts(), iterations);
results.productById = await avgRuntime(async () => await this.testProductById(constants.TEST_PRODUCT_ID), iterations, constants.EXPECTED_PRODUCT);
results.allCategories = await avgRuntime(async () => await this.testAllCategories(), iterations);
results.allOrders = await avgRuntime(async () => await this.testAllOrders(), iterations);
results.ordersByUser = await avgRuntime(async () => await this.testOrdersByUser(constants.TEST_USER_ID), iterations);
results.orderById = await avgRuntime(async () => await this.testOrderById(constants.TEST_ORDER_ID), iterations, constants.EXPECTED_ORDER);
results.allUsers = await avgRuntime(async () => await this.testAllUsers(), iterations);
results.insertOrder = await avgRuntime(async () => await this.testInsertOrder({ id: uuid(), ...constants.TEST_ORDER }), iterations);
results.updateUser = await avgRuntime(async () => await this.updateUser(constants.TEST_UPDATE), iterations);
return results;
}
}
\ No newline at end of file
export type ProductRequest = {
productId: string;
};
export type AllProductsRequest = {
categoryId: string;
}
export type Product = {
categoryId: string;
stock: number;
price: number;
description: string;
id: string;
name: string;
};
export type Order = {
userId: string;
id: string;
products: OrderProduct[];
totalAmount: number;
};
export type OrderRequest = {
id: string;
}
export type OrderProduct = {
productId: string;
quantity: number;
};
export type Category = {
description: string;
id: string;
price: number;
name: string;
};
export type UserRequest = {
id: string;
};
export type UserPatchRequest = {
id: string;
email?: string;
password?: string;
}
export type User = {
id: string;
email: string;
}
export type TestResult = {
ok: boolean;
time: number;
}
export type TestResults = {
randomProduct: TestResult;
userById: TestResult;
allProducts: TestResult;
productById: TestResult;
allCategories: TestResult;
allOrders: TestResult;
ordersByUser: TestResult;
orderById: TestResult;
allUsers: TestResult;
insertOrder: TestResult;
updateUser: TestResult;
}
\ No newline at end of file
{
"compilerOptions": {
"module": "commonjs",
"esModuleInterop": true,
"target": "es6",
"moduleResolution": "node",
"sourceMap": true,
"outDir": "dist",
},
"include": [
"src/**/*"
],
"lib": [
"es2015"
]
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment