chore: developer cleanup (#300)

* new PR tasks

* add homebox to know words

* formatting

* bump deps

* generate db models

* ts errors

* drop id

* fix accessor

* drop unused time field

* change CI

* add expected error

* add type check

* resolve serveral type errors

* hoise in CI
This commit is contained in:
Hayden 2023-02-17 21:41:01 -09:00 committed by GitHub
parent 88f9ff90d4
commit bd321af29f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
142 changed files with 817 additions and 1200 deletions

View file

@ -9,13 +9,14 @@ import { Requests } from "../../../requests";
function itemField(id = null): ItemField {
return {
// @ts-expect-error
id,
name: faker.lorem.word(),
type: "text",
textValue: faker.lorem.sentence(),
booleanValue: false,
numberValue: faker.datatype.number(),
timeValue: null,
timeValue: "",
};
}
@ -32,8 +33,9 @@ function user(): UserRegistration {
};
}
function location(): LocationCreate {
function location(parentId: string | null = null): LocationCreate {
return {
parentId,
name: faker.address.city(),
description: faker.lorem.sentence(),
};
@ -56,7 +58,7 @@ function publicClient(): PublicApi {
function userClient(token: string): UserClient {
overrideParts(config.BASE_URL, "/api/v1");
const requests = new Requests("", token);
return new UserClient(requests);
return new UserClient(requests, "");
}
type TestUser = {
@ -75,7 +77,7 @@ async function userSingleUse(): Promise<TestUser> {
expect(result.status).toBe(200);
return {
client: new UserClient(new Requests("", result.data.token)),
client: new UserClient(new Requests("", result.data.token), result.data.attachmentToken),
user: usr,
};
}

View file

@ -1,6 +1,6 @@
import { faker } from "@faker-js/faker";
import { describe, test, expect } from "vitest";
import { ItemField, LocationOut } from "../../types/data-contracts";
import { ItemField, ItemUpdate, LocationOut } from "../../types/data-contracts";
import { AttachmentTypes } from "../../types/non-generated";
import { UserClient } from "../../user";
import { factories } from "../factories";
@ -14,6 +14,7 @@ describe("user should be able to create an item and add an attachment", () => {
*/
async function useLocation(api: UserClient): Promise<[LocationOut, () => Promise<void>]> {
const { response, data } = await api.locations.create({
parentId: null,
name: `__test__.location.name_${increment}`,
description: `__test__.location.description_${increment}`,
});
@ -86,12 +87,12 @@ describe("user should be able to create an item and add an attachment", () => {
const itemUpdate = {
parentId: null,
...item,
locationId: item.location.id,
locationId: item.location?.id || null,
labelIds: item.labels.map(l => l.id),
fields,
};
const { response: updateResponse, data: item2 } = await api.items.update(item.id, itemUpdate);
const { response: updateResponse, data: item2 } = await api.items.update(item.id, itemUpdate as ItemUpdate);
expect(updateResponse.status).toBe(200);
expect(item2.fields).toHaveLength(fields.length);
@ -104,7 +105,7 @@ describe("user should be able to create an item and add an attachment", () => {
itemUpdate.fields = [fields[0], fields[1]];
const { response: updateResponse2, data: item3 } = await api.items.update(item.id, itemUpdate);
const { response: updateResponse2, data: item3 } = await api.items.update(item.id, itemUpdate as ItemUpdate);
expect(updateResponse2.status).toBe(200);
expect(item3.fields).toHaveLength(2);

View file

@ -49,6 +49,8 @@ describe("locations lifecycle (create, update, delete)", () => {
const [location, cleanup] = await useLocation(api);
const updateData = {
id: location.id,
parentId: location.parent?.id,
name: "test-location-updated",
description: "test-description-updated",
};

View file

@ -77,13 +77,20 @@ function importFileGenerator(entries: number): ImportObj[] {
describe("group related statistics tests", () => {
const TOTAL_ITEMS = 30;
let api: UserClient | undefined;
let tAPI: UserClient | undefined;
const imports = importFileGenerator(TOTAL_ITEMS);
const api = (): UserClient => {
if (!tAPI) {
throw new Error("API not initialized");
}
return tAPI;
};
beforeAll(async () => {
// -- Setup --
const { client } = await factories.client.singleUse();
api = client;
tAPI = client;
const csv = toCsv(imports);
@ -95,7 +102,7 @@ describe("group related statistics tests", () => {
// Write to file system for debugging
// fs.writeFileSync("test.csv", csv);
test("Validate Group Statistics", async () => {
const { status, data } = await api.stats.group();
const { status, data } = await api().stats.group();
expect(status).toBe(200);
expect(data.totalItems).toEqual(TOTAL_ITEMS);
@ -117,7 +124,7 @@ describe("group related statistics tests", () => {
}
test("Validate Labels Statistics", async () => {
const { status, data } = await api.stats.labels();
const { status, data } = await api().stats.labels();
expect(status).toBe(200);
for (const label of data) {
@ -126,7 +133,7 @@ describe("group related statistics tests", () => {
});
test("Validate Locations Statistics", async () => {
const { status, data } = await api.stats.locations();
const { status, data } = await api().stats.locations();
expect(status).toBe(200);
for (const location of data) {
@ -135,7 +142,7 @@ describe("group related statistics tests", () => {
});
test("Validate Purchase Over Time", async () => {
const { status, data } = await api.stats.totalPriceOverTime();
const { status, data } = await api().stats.totalPriceOverTime();
expect(status).toBe(200);
expect(data.entries.length).toEqual(TOTAL_ITEMS);
});

View file

@ -9,8 +9,8 @@ type BaseApiType = {
[key: string]: any;
};
export function hasKey(obj: object, key: string): obj is Required<BaseApiType> {
return typeof obj[key] === "string";
export function hasKey(obj: Record<string, any>, key: string): obj is Required<BaseApiType> {
return key in obj ? typeof obj[key] === "string" : false;
}
export function parseDate<T>(obj: T, keys: Array<keyof T> = []): T {

View file

@ -141,4 +141,8 @@ export class ItemsApi extends BaseAPI {
data: formData,
});
}
exportURL() {
return route("/items/export");
}
}

View file

@ -1,27 +1,7 @@
import { BaseAPI, route } from "../base";
export class ReportsAPI extends BaseAPI {
async billOfMaterials(): Promise<void> {
const { data: stream, error } = await this.http.get<ReadableStream>({ url: route("/reporting/bill-of-materials") });
if (error) {
return;
}
const reader = stream.getReader();
let data = "";
while (true) {
const { done, value } = await reader.read();
if (done) {
break;
}
data += new TextDecoder("utf-8").decode(value);
}
const blob = new Blob([data], { type: "text/tsv" });
const link = document.createElement("a");
link.href = window.URL.createObjectURL(blob);
link.download = "bill-of-materials.tsv";
link.click();
billOfMaterialsURL(): string {
return route("/reporting/bill-of-materials");
}
}

View file

@ -66,7 +66,6 @@ export interface ItemField {
name: string;
numberValue: number;
textValue: string;
timeValue: string;
type: string;
}