Skip to content

Commit

Permalink
Merge pull request woltsu#11 from mindler-sasu/main
Browse files Browse the repository at this point in the history
type tests
  • Loading branch information
woltsu authored Mar 18, 2024
2 parents f60af20 + bcdd047 commit 02e36d2
Show file tree
Hide file tree
Showing 9 changed files with 207 additions and 10 deletions.
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@
"scripts": {
"build": "tsup ./src/index.ts",
"tsc": "tsc",
"test": "vitest"
"test": "vitest --typecheck --watch false && pnpm test:integration",
"test:watch": "vitest --typecheck",
"test:integration": "vitest --config vitest.integration.config.mts"
},
"license": "MIT",
"devDependencies": {
Expand Down
19 changes: 16 additions & 3 deletions src/queryBuilders/getItemQueryBuilder.integration.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { beforeAll, describe, expect, it } from "vitest";
import { DDB, TEST_DATA } from "../../test/testFixture";
import { getDDBClientFor, startDDBTestContainer } from "../../test/testUtil";
import { Tsynamo } from "./../index";
Expand Down Expand Up @@ -99,11 +98,25 @@ describe("GetItemQueryBuilder", () => {
stringTimestamp: "123",
})
.consistentRead(true)
.attributes(["tuplez[0]"])
.attributes(["tuplez[1]"])
.execute();

expect(Object.keys(data!).length).toBe(1);
expect(data?.tuplez?.[0]).toEqual(TEST_DATA[6].tuplez[0]);
expect(data?.tuplez?.[0]).toEqual(TEST_DATA[6].tuplez[1]);
});
it("handles selecting multiple attributes from tuples", async () => {
const data = await tsynamoClient
.getItemFrom("myOtherTable")
.keys({
userId: TEST_DATA[6].userId,
stringTimestamp: "123",
})
.consistentRead(true)
.attributes(["tuplez[0]", "tuplez[1]"])
.execute();

expect(Object.keys(data!).length).toBe(1);
expect(data?.tuplez).toEqual(TEST_DATA[6].tuplez);
});

it("can't await instance directly", async () => {
Expand Down
1 change: 0 additions & 1 deletion src/queryBuilders/queryQueryBuilder.integration.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { beforeAll, describe, expect, it } from "vitest";
import { DDB, TEST_DATA } from "../../test/testFixture";
import { getDDBClientFor, startDDBTestContainer } from "../../test/testUtil";
import { Tsynamo } from "./../index";
Expand Down
156 changes: 156 additions & 0 deletions src/typeHelpers.test-d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
import { SelectAttributes, type ObjectFullPaths } from "./typeHelpers";

describe("typeHelpers typecheck", () => {
it("ObjectFullPaths typecheck", () => {
type empty = ObjectFullPaths<{}>;
expectTypeOf<empty>().toEqualTypeOf<never>();

type simpleObject = ObjectFullPaths<{ key: string; anotherKey: number }>;
expectTypeOf<simpleObject>().toEqualTypeOf<"key" | "anotherKey">();

type nestedObject = ObjectFullPaths<{ key: { nested: string } }>;
expectTypeOf<nestedObject>().toEqualTypeOf<"key" | "key.nested">();

type deepNested = ObjectFullPaths<{
key: { n: { nn: { nnn: { nnnn: string } } } };
}>;
expectTypeOf<deepNested>().toEqualTypeOf<
"key" | "key.n" | "key.n.nn" | "key.n.nn.nnn" | "key.n.nn.nnn.nnnn"
>();

type array = ObjectFullPaths<{ array: string[] }>;
expectTypeOf<array>().toEqualTypeOf<"array" | `array[${number}]`>();

type arrayWObject = ObjectFullPaths<{
cats: { name: string; age: number }[];
}>;
expectTypeOf<arrayWObject>().toEqualTypeOf<
| "cats"
| `cats[${number}]`
| `cats[${number}].name`
| `cats[${number}].age`
>();

type arrayWArray = ObjectFullPaths<{
house: { cats: { name: string; age: number }[] }[];
}>;
expectTypeOf<arrayWArray>().toEqualTypeOf<
| "house"
| `house[${number}]`
| `house[${number}].cats`
| `house[${number}].cats[${number}]`
| `house[${number}].cats[${number}].name`
| `house[${number}].cats[${number}].age`
>();

type tuple = ObjectFullPaths<{
tuple: [string, number];
}>;
expectTypeOf<tuple>().toEqualTypeOf<"tuple" | "tuple[0]" | "tuple[1]">();

type tupleWObject = ObjectFullPaths<{
tuple: [{ left: boolean }, { right: boolean }];
}>;
expectTypeOf<tupleWObject>().toEqualTypeOf<
"tuple" | "tuple[0]" | "tuple[1]" | "tuple[0].left" | "tuple[1].right"
>();

type tupleWArrayOrTuple = ObjectFullPaths<{
tuple: [{ left: boolean[] }, { right: [boolean] }];
}>;
expectTypeOf<tupleWArrayOrTuple>().toEqualTypeOf<
| "tuple"
| "tuple[0]"
| "tuple[1]"
| "tuple[0].left"
| "tuple[1].right"
| `tuple[0].left[${number}]`
| "tuple[1].right[0]"
>();

// TODO ObjectFullPaths doesnt work with multi-dimensional arrays yet
});

it("SelectAttributes typecheck", () => {
interface Table {
key: number;
otherKey: string;
obj: {
nestedKey: boolean;
anotherNestedKey: true;
};
tuple: [{ kissa: "koira" }, number];
cats: {
name: string;
age: number;
}[];
}

type selectKey = SelectAttributes<Table, ["key"]>;
expectTypeOf<selectKey>().toEqualTypeOf<{
key: number;
}>();
type selectObjectKey = SelectAttributes<Table, ["key", "obj"]>;
expectTypeOf<selectObjectKey>().toEqualTypeOf<{
key: number;
obj: {
nestedKey: boolean;
anotherNestedKey: true;
};
}>();

type selectAll = SelectAttributes<
Table,
["key", "otherKey", "cats", "obj", "tuple"]
>;
expectTypeOf<selectAll>().toEqualTypeOf<Table>();

type selectNested = SelectAttributes<Table, ["key", "obj.nestedKey"]>;
expectTypeOf<selectNested>().toEqualTypeOf<{
key: number;
obj: {
nestedKey: boolean;
};
}>();

type selectTuple1 = SelectAttributes<Table, ["key", "tuple[0]"]>;
expectTypeOf<selectTuple1>().toEqualTypeOf<{
key: number;
tuple: [
{
kissa: "koira";
}
];
}>();

type selectTuple2 = SelectAttributes<Table, ["key", "tuple[1]"]>;
expectTypeOf<selectTuple2>().toEqualTypeOf<{
key: number;
tuple: [number];
}>();

type selectTuple3 = SelectAttributes<
Table,
["key", "tuple[0]", "tuple[1]"]
>;
// TODO Fix this to be [{kissa: "koira"}, number] or at least union
expectTypeOf<selectTuple3>().toEqualTypeOf<{
key: number;
tuple: [
{
kissa: "koira";
}
] &
[number];
}>();

type selectArray = SelectAttributes<Table, ["key", "cats[0]"]>;
expectTypeOf<selectArray>().toEqualTypeOf<{
key: number;
cats: {
name: string;
age: number;
}[];
}>();
});
});
11 changes: 7 additions & 4 deletions src/typeHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,14 @@ type RecursiveSelectAttributes<Table, Properties> = Properties extends [
infer First,
...infer Rest
]
? First extends keyof Table
? { [key in First]: RecursiveSelectAttributes<Table[First], Rest> }
: // When "First" in path is a number, and Table is an Array, Recurse to the inner type of the array
[First, Table] extends [`${number}`, any[]]
? [First, IsTuple<Table>] extends [`${number}`, true]
? First extends keyof Table
? [RecursiveSelectAttributes<Table[First], Rest>]
: never
: [First, Table] extends [`${number}`, any[]]
? RecursiveSelectAttributes<As<Table, any[]>[number], Rest>[]
: First extends keyof Table
? { [key in First]: RecursiveSelectAttributes<Table[First], Rest> }
: never
: Table;

Expand Down
4 changes: 4 additions & 0 deletions test/testFixture.ts
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,10 @@ export const TEST_DATA = [
name: "Sylvester J. Pussycat Sr.",
age: 78,
},
{
name: "Tommy the Cat",
age: 12,
},
],
},
{
Expand Down
3 changes: 2 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
"extends": "@tsconfig/node20/tsconfig.json",
"exclude": ["node_modules"]
"exclude": ["node_modules"],
"compilerOptions": { "types": ["vitest/globals"] }
}
19 changes: 19 additions & 0 deletions vitest.config.mts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { defineConfig } from "vitest/config";
import path from "path";

export default defineConfig({
test: {
globals: true,
exclude: [
"**/node_modules/**",
"**/build/**",
"**/*.integration.test.ts/**",
],
hookTimeout: 30000,
},
resolve: {
alias: {
"@shared": path.resolve(__dirname, "../../shared"),
},
},
});
File renamed without changes.

0 comments on commit 02e36d2

Please sign in to comment.