UNPKG

@arkiv-network/sdk

Version:

TypeScript client library for Arkiv's blockchains interactions

100 lines (83 loc) • 4.13 kB
import { describe, expect, it } from "bun:test" import { bytes, dec, defineSchema, InvalidAttributeNameError, str, u256 } from "../schema" import { InvalidPredicateError } from "./errors" import { asc, desc, isOrderTerm, type OrderTerm, renderOrderBy } from "./order" const Posts = defineSchema("posts", { score: dec().indexed(), title: str(), rank: u256().indexed().optional(), body: bytes(), }) describe("asc and desc", () => { it("build a frozen key with the direction and the type written", () => { const key = desc("score", "u256") expect(key).toEqual({ kind: "order", name: "score", type: "u256", direction: "desc" }) expect(Object.isFrozen(key)).toBe(true) expect(asc("title").direction).toBe("asc") }) it("leave a user attribute's type for the schema to supply", () => { expect(asc("score").type).toBeUndefined() }) it("give a system attribute its fixed type", () => { expect(asc("$expiresAt").type).toBe("u64") expect(desc("$owner").type).toBe("addr") expect(asc("$key", "key").type).toBe("key") }) it("reject a system attribute that cannot be sorted on", () => { expect(() => desc("$createdAt")).toThrow(/cannot be sorted on.*sort the results/) expect(() => asc("$nope")).toThrow(InvalidPredicateError) }) it("reject a system attribute given another type", () => { expect(() => asc("$expiresAt", "u256")).toThrow(/always a u64/) }) it("reject a type that is not indexable", () => { // @ts-expect-error - bytes cannot be sorted on expect(() => asc("blob", "bytes")).toThrow(/"blob" cannot be sorted as "bytes"/) }) it("reject a name outside the attribute grammar", () => { expect(() => asc("not a name", "str")).toThrow(InvalidAttributeNameError) }) it("build keys isOrderTerm recognises", () => { expect(isOrderTerm(asc("score"))).toBe(true) expect(isOrderTerm([asc("score")])).toBe(false) expect(isOrderTerm("score")).toBe(false) expect(isOrderTerm(undefined)).toBe(false) }) }) describe("renderOrderBy", () => { it("writes the key as name:type and its direction", () => { expect(renderOrderBy(desc("score", "u256"), undefined)).toBe("ORDER BY score:u256 DESC") expect(renderOrderBy(asc("title", "str"), undefined)).toBe("ORDER BY title:str ASC") }) it("takes the key's type from the schema's column", () => { expect(renderOrderBy(desc("score"), Posts)).toBe("ORDER BY score:dec DESC") expect(renderOrderBy(asc("rank"), Posts)).toBe("ORDER BY rank:u256 ASC") expect(renderOrderBy(asc("$expiresAt"), Posts)).toBe("ORDER BY $expiresAt:u64 ASC") }) it("needs a type for a user attribute without a schema", () => { expect(() => renderOrderBy(desc("score"), undefined)).toThrow(/needs its type/) }) it("sorts on a column whether or not it is indexed", () => { expect(renderOrderBy(asc("title"), Posts)).toBe("ORDER BY title:str ASC") expect(renderOrderBy(desc("title", "str"), Posts)).toBe("ORDER BY title:str DESC") }) it("checks a key against the schema", () => { expect(() => renderOrderBy(asc("nope"), Posts)).toThrow(/not a column of the schema/) expect(() => renderOrderBy(asc("body"), Posts)).toThrow(/bytes cannot be sorted on/) expect(() => renderOrderBy(asc("title", "u256"), Posts)).toThrow(/str column/) expect(() => renderOrderBy(asc("score", "u256"), Posts)).toThrow(/dec column/) }) it("words the schema errors for a sort, not a filter", () => { expect(() => renderOrderBy(asc("nope"), Posts)).toThrow(/so it cannot be sorted on/) expect(() => renderOrderBy(asc("body"), Posts)).not.toThrow(/hash/) expect(() => renderOrderBy(asc("body"), Posts)).toThrow(/sort the results in JavaScript/) }) it("says a typeless system key was not built by asc() or desc(), schema or not", () => { const handBuilt = { kind: "order", name: "$key", type: undefined, direction: "asc" } as const for (const schema of [Posts, undefined]) { expect(() => renderOrderBy(handBuilt as OrderTerm, schema)).toThrow( /system attribute's is fixed\. Build it with asc\(\) or desc\(\)/, ) } }) })