chore: generate
This commit is contained in:
parent
44edb639c2
commit
e0e9414cbd
2 changed files with 608 additions and 506 deletions
|
|
@ -115,7 +115,9 @@ describe("file/index Filesystem patterns", () => {
|
||||||
it.instance("handles multi-line text files", () =>
|
it.instance("handles multi-line text files", () =>
|
||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
const test = yield* TestInstance
|
const test = yield* TestInstance
|
||||||
yield* Effect.promise(() => fs.writeFile(path.join(test.directory, "multiline.txt"), "line1\nline2\nline3", "utf-8"))
|
yield* Effect.promise(() =>
|
||||||
|
fs.writeFile(path.join(test.directory, "multiline.txt"), "line1\nline2\nline3", "utf-8"),
|
||||||
|
)
|
||||||
|
|
||||||
const result = yield* read("multiline.txt")
|
const result = yield* read("multiline.txt")
|
||||||
expect(result.content).toBe("line1\nline2\nline3")
|
expect(result.content).toBe("line1\nline2\nline3")
|
||||||
|
|
@ -141,7 +143,9 @@ describe("file/index Filesystem patterns", () => {
|
||||||
it.instance("returns empty for binary non-image files", () =>
|
it.instance("returns empty for binary non-image files", () =>
|
||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
const test = yield* TestInstance
|
const test = yield* TestInstance
|
||||||
yield* Effect.promise(() => fs.writeFile(path.join(test.directory, "binary.so"), Buffer.from([0x7f, 0x45, 0x4c, 0x46])))
|
yield* Effect.promise(() =>
|
||||||
|
fs.writeFile(path.join(test.directory, "binary.so"), Buffer.from([0x7f, 0x45, 0x4c, 0x46])),
|
||||||
|
)
|
||||||
|
|
||||||
const result = yield* read("binary.so")
|
const result = yield* read("binary.so")
|
||||||
expect(result.type).toBe("binary")
|
expect(result.type).toBe("binary")
|
||||||
|
|
@ -250,7 +254,9 @@ describe("file/index Filesystem patterns", () => {
|
||||||
yield* Effect.promise(() => fs.writeFile(path.join(test.directory, "readonly.txt"), "content", "utf-8"))
|
yield* Effect.promise(() => fs.writeFile(path.join(test.directory, "readonly.txt"), "content", "utf-8"))
|
||||||
|
|
||||||
const nonExistentPath = path.join(test.directory, "does-not-exist.txt")
|
const nonExistentPath = path.join(test.directory, "does-not-exist.txt")
|
||||||
expect(Exit.isFailure(yield* Effect.promise(() => Filesystem.readText(nonExistentPath)).pipe(Effect.exit))).toBe(true)
|
expect(
|
||||||
|
Exit.isFailure(yield* Effect.promise(() => Filesystem.readText(nonExistentPath)).pipe(Effect.exit)),
|
||||||
|
).toBe(true)
|
||||||
|
|
||||||
const result = yield* read("does-not-exist.txt")
|
const result = yield* read("does-not-exist.txt")
|
||||||
expect(result.content).toBe("")
|
expect(result.content).toBe("")
|
||||||
|
|
@ -261,7 +267,9 @@ describe("file/index Filesystem patterns", () => {
|
||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
const test = yield* TestInstance
|
const test = yield* TestInstance
|
||||||
const nonExistentPath = path.join(test.directory, "does-not-exist.bin")
|
const nonExistentPath = path.join(test.directory, "does-not-exist.bin")
|
||||||
const buffer = yield* Effect.promise(() => Filesystem.readArrayBuffer(nonExistentPath).catch(() => new ArrayBuffer(0)))
|
const buffer = yield* Effect.promise(() =>
|
||||||
|
Filesystem.readArrayBuffer(nonExistentPath).catch(() => new ArrayBuffer(0)),
|
||||||
|
)
|
||||||
expect(buffer.byteLength).toBe(0)
|
expect(buffer.byteLength).toBe(0)
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|
@ -279,7 +287,9 @@ describe("file/index Filesystem patterns", () => {
|
||||||
it.instance("treats .ts files as text", () =>
|
it.instance("treats .ts files as text", () =>
|
||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
const test = yield* TestInstance
|
const test = yield* TestInstance
|
||||||
yield* Effect.promise(() => fs.writeFile(path.join(test.directory, "test.ts"), "export const value = 1", "utf-8"))
|
yield* Effect.promise(() =>
|
||||||
|
fs.writeFile(path.join(test.directory, "test.ts"), "export const value = 1", "utf-8"),
|
||||||
|
)
|
||||||
|
|
||||||
const result = yield* read("test.ts")
|
const result = yield* read("test.ts")
|
||||||
expect(result.type).toBe("text")
|
expect(result.type).toBe("text")
|
||||||
|
|
@ -290,7 +300,9 @@ describe("file/index Filesystem patterns", () => {
|
||||||
it.instance("treats .mts files as text", () =>
|
it.instance("treats .mts files as text", () =>
|
||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
const test = yield* TestInstance
|
const test = yield* TestInstance
|
||||||
yield* Effect.promise(() => fs.writeFile(path.join(test.directory, "test.mts"), "export const value = 1", "utf-8"))
|
yield* Effect.promise(() =>
|
||||||
|
fs.writeFile(path.join(test.directory, "test.mts"), "export const value = 1", "utf-8"),
|
||||||
|
)
|
||||||
|
|
||||||
const result = yield* read("test.mts")
|
const result = yield* read("test.mts")
|
||||||
expect(result.type).toBe("text")
|
expect(result.type).toBe("text")
|
||||||
|
|
@ -301,7 +313,9 @@ describe("file/index Filesystem patterns", () => {
|
||||||
it.instance("treats .sh files as text", () =>
|
it.instance("treats .sh files as text", () =>
|
||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
const test = yield* TestInstance
|
const test = yield* TestInstance
|
||||||
yield* Effect.promise(() => fs.writeFile(path.join(test.directory, "test.sh"), "#!/usr/bin/env bash\necho hello", "utf-8"))
|
yield* Effect.promise(() =>
|
||||||
|
fs.writeFile(path.join(test.directory, "test.sh"), "#!/usr/bin/env bash\necho hello", "utf-8"),
|
||||||
|
)
|
||||||
|
|
||||||
const result = yield* read("test.sh")
|
const result = yield* read("test.sh")
|
||||||
expect(result.type).toBe("text")
|
expect(result.type).toBe("text")
|
||||||
|
|
@ -334,7 +348,9 @@ describe("file/index Filesystem patterns", () => {
|
||||||
it.instance("returns base64 encoding for images", () =>
|
it.instance("returns base64 encoding for images", () =>
|
||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
const test = yield* TestInstance
|
const test = yield* TestInstance
|
||||||
yield* Effect.promise(() => fs.writeFile(path.join(test.directory, "test.jpg"), Buffer.from([0xff, 0xd8, 0xff, 0xe0])))
|
yield* Effect.promise(() =>
|
||||||
|
fs.writeFile(path.join(test.directory, "test.jpg"), Buffer.from([0xff, 0xd8, 0xff, 0xe0])),
|
||||||
|
)
|
||||||
|
|
||||||
const result = yield* read("test.jpg")
|
const result = yield* read("test.jpg")
|
||||||
expect(result.encoding).toBe("base64")
|
expect(result.encoding).toBe("base64")
|
||||||
|
|
@ -384,7 +400,9 @@ describe("file/index Filesystem patterns", () => {
|
||||||
() =>
|
() =>
|
||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
const test = yield* TestInstance
|
const test = yield* TestInstance
|
||||||
yield* Effect.promise(() => fs.writeFile(path.join(test.directory, "new.txt"), "line1\nline2\nline3\n", "utf-8"))
|
yield* Effect.promise(() =>
|
||||||
|
fs.writeFile(path.join(test.directory, "new.txt"), "line1\nline2\nline3\n", "utf-8"),
|
||||||
|
)
|
||||||
|
|
||||||
const result = yield* status()
|
const result = yield* status()
|
||||||
const entry = result.find((file) => file.path === "new.txt")
|
const entry = result.find((file) => file.path === "new.txt")
|
||||||
|
|
@ -457,10 +475,14 @@ describe("file/index Filesystem patterns", () => {
|
||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
const test = yield* TestInstance
|
const test = yield* TestInstance
|
||||||
const filepath = path.join(test.directory, "data.bin")
|
const filepath = path.join(test.directory, "data.bin")
|
||||||
yield* Effect.promise(() => fs.writeFile(filepath, Buffer.from(Array.from({ length: 256 }, (_, index) => index))))
|
yield* Effect.promise(() =>
|
||||||
|
fs.writeFile(filepath, Buffer.from(Array.from({ length: 256 }, (_, index) => index))),
|
||||||
|
)
|
||||||
yield* gitAddAll(test.directory)
|
yield* gitAddAll(test.directory)
|
||||||
yield* gitCommit(test.directory, "add binary")
|
yield* gitCommit(test.directory, "add binary")
|
||||||
yield* Effect.promise(() => fs.writeFile(filepath, Buffer.from(Array.from({ length: 512 }, (_, index) => index % 256))))
|
yield* Effect.promise(() =>
|
||||||
|
fs.writeFile(filepath, Buffer.from(Array.from({ length: 512 }, (_, index) => index % 256))),
|
||||||
|
)
|
||||||
|
|
||||||
const result = yield* status()
|
const result = yield* status()
|
||||||
const entry = result.find((file) => file.path === "data.bin")
|
const entry = result.find((file) => file.path === "data.bin")
|
||||||
|
|
@ -481,7 +503,9 @@ describe("file/index Filesystem patterns", () => {
|
||||||
const test = yield* TestInstance
|
const test = yield* TestInstance
|
||||||
yield* Effect.promise(() => fs.mkdir(path.join(test.directory, "subdir")))
|
yield* Effect.promise(() => fs.mkdir(path.join(test.directory, "subdir")))
|
||||||
yield* Effect.promise(() => fs.writeFile(path.join(test.directory, "file.txt"), "content", "utf-8"))
|
yield* Effect.promise(() => fs.writeFile(path.join(test.directory, "file.txt"), "content", "utf-8"))
|
||||||
yield* Effect.promise(() => fs.writeFile(path.join(test.directory, "subdir", "nested.txt"), "nested", "utf-8"))
|
yield* Effect.promise(() =>
|
||||||
|
fs.writeFile(path.join(test.directory, "subdir", "nested.txt"), "nested", "utf-8"),
|
||||||
|
)
|
||||||
|
|
||||||
const nodes = yield* list()
|
const nodes = yield* list()
|
||||||
expect(nodes.length).toBeGreaterThanOrEqual(2)
|
expect(nodes.length).toBeGreaterThanOrEqual(2)
|
||||||
|
|
@ -633,8 +657,12 @@ describe("file/index Filesystem patterns", () => {
|
||||||
|
|
||||||
const result = yield* search({ query: "", type: "directory" })
|
const result = yield* search({ query: "", type: "directory" })
|
||||||
expect(result.length).toBeGreaterThan(0)
|
expect(result.length).toBeGreaterThan(0)
|
||||||
const firstHidden = result.findIndex((dir) => dir.split("/").some((part) => part.startsWith(".") && part.length > 1))
|
const firstHidden = result.findIndex((dir) =>
|
||||||
const lastVisible = result.findLastIndex((dir) => !dir.split("/").some((part) => part.startsWith(".") && part.length > 1))
|
dir.split("/").some((part) => part.startsWith(".") && part.length > 1),
|
||||||
|
)
|
||||||
|
const lastVisible = result.findLastIndex(
|
||||||
|
(dir) => !dir.split("/").some((part) => part.startsWith(".") && part.length > 1),
|
||||||
|
)
|
||||||
if (firstHidden >= 0 && lastVisible >= 0) {
|
if (firstHidden >= 0 && lastVisible >= 0) {
|
||||||
expect(firstHidden).toBeGreaterThan(lastVisible)
|
expect(firstHidden).toBeGreaterThan(lastVisible)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -126,17 +126,20 @@ const addCompactionPart = Effect.fn("Test.addCompactionPart")(function* (
|
||||||
|
|
||||||
describe("MessageV2.page", () => {
|
describe("MessageV2.page", () => {
|
||||||
it.instance("returns sync result", () =>
|
it.instance("returns sync result", () =>
|
||||||
withSession(({ sessionID }) => Effect.gen(function* () {
|
withSession(({ sessionID }) =>
|
||||||
|
Effect.gen(function* () {
|
||||||
yield* fill(sessionID, 2)
|
yield* fill(sessionID, 2)
|
||||||
|
|
||||||
const result = MessageV2.page({ sessionID, limit: 10 })
|
const result = MessageV2.page({ sessionID, limit: 10 })
|
||||||
expect(result).toBeDefined()
|
expect(result).toBeDefined()
|
||||||
expect(result.items).toBeArray()
|
expect(result.items).toBeArray()
|
||||||
})),
|
}),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
it.instance("pages backward with opaque cursors", () =>
|
it.instance("pages backward with opaque cursors", () =>
|
||||||
withSession(({ sessionID }) => Effect.gen(function* () {
|
withSession(({ sessionID }) =>
|
||||||
|
Effect.gen(function* () {
|
||||||
const ids = yield* fill(sessionID, 6)
|
const ids = yield* fill(sessionID, 6)
|
||||||
|
|
||||||
const a = MessageV2.page({ sessionID, limit: 2 })
|
const a = MessageV2.page({ sessionID, limit: 2 })
|
||||||
|
|
@ -154,25 +157,30 @@ describe("MessageV2.page", () => {
|
||||||
expect(c.items.map((item) => item.info.id)).toEqual(ids.slice(0, 2))
|
expect(c.items.map((item) => item.info.id)).toEqual(ids.slice(0, 2))
|
||||||
expect(c.more).toBe(false)
|
expect(c.more).toBe(false)
|
||||||
expect(c.cursor).toBeUndefined()
|
expect(c.cursor).toBeUndefined()
|
||||||
})),
|
}),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
it.instance("returns items in chronological order within a page", () =>
|
it.instance("returns items in chronological order within a page", () =>
|
||||||
withSession(({ sessionID }) => Effect.gen(function* () {
|
withSession(({ sessionID }) =>
|
||||||
|
Effect.gen(function* () {
|
||||||
const ids = yield* fill(sessionID, 4)
|
const ids = yield* fill(sessionID, 4)
|
||||||
|
|
||||||
const result = MessageV2.page({ sessionID, limit: 4 })
|
const result = MessageV2.page({ sessionID, limit: 4 })
|
||||||
expect(result.items.map((item) => item.info.id)).toEqual(ids)
|
expect(result.items.map((item) => item.info.id)).toEqual(ids)
|
||||||
})),
|
}),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
it.instance("returns empty items for session with no messages", () =>
|
it.instance("returns empty items for session with no messages", () =>
|
||||||
withSession(({ sessionID }) => Effect.gen(function* () {
|
withSession(({ sessionID }) =>
|
||||||
|
Effect.gen(function* () {
|
||||||
const result = MessageV2.page({ sessionID, limit: 10 })
|
const result = MessageV2.page({ sessionID, limit: 10 })
|
||||||
expect(result.items).toEqual([])
|
expect(result.items).toEqual([])
|
||||||
expect(result.more).toBe(false)
|
expect(result.more).toBe(false)
|
||||||
expect(result.cursor).toBeUndefined()
|
expect(result.cursor).toBeUndefined()
|
||||||
})),
|
}),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
it.instance("throws NotFoundError for non-existent session", () =>
|
it.instance("throws NotFoundError for non-existent session", () =>
|
||||||
|
|
@ -183,29 +191,34 @@ describe("MessageV2.page", () => {
|
||||||
)
|
)
|
||||||
|
|
||||||
it.instance("handles exact limit boundary", () =>
|
it.instance("handles exact limit boundary", () =>
|
||||||
withSession(({ sessionID }) => Effect.gen(function* () {
|
withSession(({ sessionID }) =>
|
||||||
|
Effect.gen(function* () {
|
||||||
const ids = yield* fill(sessionID, 3)
|
const ids = yield* fill(sessionID, 3)
|
||||||
|
|
||||||
const result = MessageV2.page({ sessionID, limit: 3 })
|
const result = MessageV2.page({ sessionID, limit: 3 })
|
||||||
expect(result.items.map((item) => item.info.id)).toEqual(ids)
|
expect(result.items.map((item) => item.info.id)).toEqual(ids)
|
||||||
expect(result.more).toBe(false)
|
expect(result.more).toBe(false)
|
||||||
expect(result.cursor).toBeUndefined()
|
expect(result.cursor).toBeUndefined()
|
||||||
})),
|
}),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
it.instance("limit of 1 returns single newest message", () =>
|
it.instance("limit of 1 returns single newest message", () =>
|
||||||
withSession(({ sessionID }) => Effect.gen(function* () {
|
withSession(({ sessionID }) =>
|
||||||
|
Effect.gen(function* () {
|
||||||
const ids = yield* fill(sessionID, 5)
|
const ids = yield* fill(sessionID, 5)
|
||||||
|
|
||||||
const result = MessageV2.page({ sessionID, limit: 1 })
|
const result = MessageV2.page({ sessionID, limit: 1 })
|
||||||
expect(result.items).toHaveLength(1)
|
expect(result.items).toHaveLength(1)
|
||||||
expect(result.items[0].info.id).toBe(ids[ids.length - 1])
|
expect(result.items[0].info.id).toBe(ids[ids.length - 1])
|
||||||
expect(result.more).toBe(true)
|
expect(result.more).toBe(true)
|
||||||
})),
|
}),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
it.instance("hydrates multiple parts per message", () =>
|
it.instance("hydrates multiple parts per message", () =>
|
||||||
withSession(({ session, sessionID }) => Effect.gen(function* () {
|
withSession(({ session, sessionID }) =>
|
||||||
|
Effect.gen(function* () {
|
||||||
const [id] = yield* fill(sessionID, 1)
|
const [id] = yield* fill(sessionID, 1)
|
||||||
|
|
||||||
yield* session.updatePart({
|
yield* session.updatePart({
|
||||||
|
|
@ -219,11 +232,13 @@ describe("MessageV2.page", () => {
|
||||||
const result = MessageV2.page({ sessionID, limit: 10 })
|
const result = MessageV2.page({ sessionID, limit: 10 })
|
||||||
expect(result.items).toHaveLength(1)
|
expect(result.items).toHaveLength(1)
|
||||||
expect(result.items[0].parts).toHaveLength(2)
|
expect(result.items[0].parts).toHaveLength(2)
|
||||||
})),
|
}),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
it.instance("accepts cursors from fractional timestamps", () =>
|
it.instance("accepts cursors from fractional timestamps", () =>
|
||||||
withSession(({ sessionID }) => Effect.gen(function* () {
|
withSession(({ sessionID }) =>
|
||||||
|
Effect.gen(function* () {
|
||||||
const ids = yield* fill(sessionID, 4, (i: number) => 1000.5 + i)
|
const ids = yield* fill(sessionID, 4, (i: number) => 1000.5 + i)
|
||||||
|
|
||||||
const a = MessageV2.page({ sessionID, limit: 2 })
|
const a = MessageV2.page({ sessionID, limit: 2 })
|
||||||
|
|
@ -231,11 +246,13 @@ describe("MessageV2.page", () => {
|
||||||
|
|
||||||
expect(a.items.map((item) => item.info.id)).toEqual(ids.slice(-2))
|
expect(a.items.map((item) => item.info.id)).toEqual(ids.slice(-2))
|
||||||
expect(b.items.map((item) => item.info.id)).toEqual(ids.slice(0, 2))
|
expect(b.items.map((item) => item.info.id)).toEqual(ids.slice(0, 2))
|
||||||
})),
|
}),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
it.instance("messages with same timestamp are ordered by id", () =>
|
it.instance("messages with same timestamp are ordered by id", () =>
|
||||||
withSession(({ sessionID }) => Effect.gen(function* () {
|
withSession(({ sessionID }) =>
|
||||||
|
Effect.gen(function* () {
|
||||||
const ids = yield* fill(sessionID, 4, () => 1000)
|
const ids = yield* fill(sessionID, 4, () => 1000)
|
||||||
|
|
||||||
const a = MessageV2.page({ sessionID, limit: 2 })
|
const a = MessageV2.page({ sessionID, limit: 2 })
|
||||||
|
|
@ -245,7 +262,8 @@ describe("MessageV2.page", () => {
|
||||||
const b = MessageV2.page({ sessionID, limit: 2, before: a.cursor! })
|
const b = MessageV2.page({ sessionID, limit: 2, before: a.cursor! })
|
||||||
expect(b.items.map((item) => item.info.id)).toEqual(ids.slice(0, 2))
|
expect(b.items.map((item) => item.info.id)).toEqual(ids.slice(0, 2))
|
||||||
expect(b.more).toBe(false)
|
expect(b.more).toBe(false)
|
||||||
})),
|
}),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
it.instance("does not return messages from other sessions", () =>
|
it.instance("does not return messages from other sessions", () =>
|
||||||
|
|
@ -269,7 +287,8 @@ describe("MessageV2.page", () => {
|
||||||
)
|
)
|
||||||
|
|
||||||
it.instance("large limit returns all messages without cursor", () =>
|
it.instance("large limit returns all messages without cursor", () =>
|
||||||
withSession(({ sessionID }) => Effect.gen(function* () {
|
withSession(({ sessionID }) =>
|
||||||
|
Effect.gen(function* () {
|
||||||
const ids = yield* fill(sessionID, 10)
|
const ids = yield* fill(sessionID, 10)
|
||||||
|
|
||||||
const result = MessageV2.page({ sessionID, limit: 100 })
|
const result = MessageV2.page({ sessionID, limit: 100 })
|
||||||
|
|
@ -277,39 +296,47 @@ describe("MessageV2.page", () => {
|
||||||
expect(result.items.map((item) => item.info.id)).toEqual(ids)
|
expect(result.items.map((item) => item.info.id)).toEqual(ids)
|
||||||
expect(result.more).toBe(false)
|
expect(result.more).toBe(false)
|
||||||
expect(result.cursor).toBeUndefined()
|
expect(result.cursor).toBeUndefined()
|
||||||
})),
|
}),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("MessageV2.stream", () => {
|
describe("MessageV2.stream", () => {
|
||||||
it.instance("yields items newest first", () =>
|
it.instance("yields items newest first", () =>
|
||||||
withSession(({ sessionID }) => Effect.gen(function* () {
|
withSession(({ sessionID }) =>
|
||||||
|
Effect.gen(function* () {
|
||||||
const ids = yield* fill(sessionID, 5)
|
const ids = yield* fill(sessionID, 5)
|
||||||
|
|
||||||
const items = Array.from(MessageV2.stream(sessionID))
|
const items = Array.from(MessageV2.stream(sessionID))
|
||||||
expect(items.map((item) => item.info.id)).toEqual(ids.slice().reverse())
|
expect(items.map((item) => item.info.id)).toEqual(ids.slice().reverse())
|
||||||
})),
|
}),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
it.instance("yields nothing for empty session", () =>
|
it.instance("yields nothing for empty session", () =>
|
||||||
withSession(({ sessionID }) => Effect.gen(function* () {
|
withSession(({ sessionID }) =>
|
||||||
|
Effect.gen(function* () {
|
||||||
const items = Array.from(MessageV2.stream(sessionID))
|
const items = Array.from(MessageV2.stream(sessionID))
|
||||||
expect(items).toHaveLength(0)
|
expect(items).toHaveLength(0)
|
||||||
})),
|
}),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
it.instance("yields single message", () =>
|
it.instance("yields single message", () =>
|
||||||
withSession(({ sessionID }) => Effect.gen(function* () {
|
withSession(({ sessionID }) =>
|
||||||
|
Effect.gen(function* () {
|
||||||
const ids = yield* fill(sessionID, 1)
|
const ids = yield* fill(sessionID, 1)
|
||||||
|
|
||||||
const items = Array.from(MessageV2.stream(sessionID))
|
const items = Array.from(MessageV2.stream(sessionID))
|
||||||
expect(items).toHaveLength(1)
|
expect(items).toHaveLength(1)
|
||||||
expect(items[0].info.id).toBe(ids[0])
|
expect(items[0].info.id).toBe(ids[0])
|
||||||
})),
|
}),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
it.instance("hydrates parts for each yielded message", () =>
|
it.instance("hydrates parts for each yielded message", () =>
|
||||||
withSession(({ sessionID }) => Effect.gen(function* () {
|
withSession(({ sessionID }) =>
|
||||||
|
Effect.gen(function* () {
|
||||||
yield* fill(sessionID, 3)
|
yield* fill(sessionID, 3)
|
||||||
|
|
||||||
const items = Array.from(MessageV2.stream(sessionID))
|
const items = Array.from(MessageV2.stream(sessionID))
|
||||||
|
|
@ -317,22 +344,26 @@ describe("MessageV2.stream", () => {
|
||||||
expect(item.parts).toHaveLength(1)
|
expect(item.parts).toHaveLength(1)
|
||||||
expect(item.parts[0].type).toBe("text")
|
expect(item.parts[0].type).toBe("text")
|
||||||
}
|
}
|
||||||
})),
|
}),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
it.instance("handles sets exceeding internal page size", () =>
|
it.instance("handles sets exceeding internal page size", () =>
|
||||||
withSession(({ sessionID }) => Effect.gen(function* () {
|
withSession(({ sessionID }) =>
|
||||||
|
Effect.gen(function* () {
|
||||||
const ids = yield* fill(sessionID, 60)
|
const ids = yield* fill(sessionID, 60)
|
||||||
|
|
||||||
const items = Array.from(MessageV2.stream(sessionID))
|
const items = Array.from(MessageV2.stream(sessionID))
|
||||||
expect(items).toHaveLength(60)
|
expect(items).toHaveLength(60)
|
||||||
expect(items[0].info.id).toBe(ids[ids.length - 1])
|
expect(items[0].info.id).toBe(ids[ids.length - 1])
|
||||||
expect(items[59].info.id).toBe(ids[0])
|
expect(items[59].info.id).toBe(ids[0])
|
||||||
})),
|
}),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
it.instance("is a sync generator", () =>
|
it.instance("is a sync generator", () =>
|
||||||
withSession(({ sessionID }) => Effect.gen(function* () {
|
withSession(({ sessionID }) =>
|
||||||
|
Effect.gen(function* () {
|
||||||
yield* fill(sessionID, 1)
|
yield* fill(sessionID, 1)
|
||||||
|
|
||||||
const gen = MessageV2.stream(sessionID)
|
const gen = MessageV2.stream(sessionID)
|
||||||
|
|
@ -341,33 +372,39 @@ describe("MessageV2.stream", () => {
|
||||||
expect(first).toHaveProperty("value")
|
expect(first).toHaveProperty("value")
|
||||||
expect(first).toHaveProperty("done")
|
expect(first).toHaveProperty("done")
|
||||||
expect(first.done).toBe(false)
|
expect(first.done).toBe(false)
|
||||||
})),
|
}),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("MessageV2.parts", () => {
|
describe("MessageV2.parts", () => {
|
||||||
it.instance("returns parts for a message", () =>
|
it.instance("returns parts for a message", () =>
|
||||||
withSession(({ sessionID }) => Effect.gen(function* () {
|
withSession(({ sessionID }) =>
|
||||||
|
Effect.gen(function* () {
|
||||||
const [id] = yield* fill(sessionID, 1)
|
const [id] = yield* fill(sessionID, 1)
|
||||||
|
|
||||||
const result = MessageV2.parts(id)
|
const result = MessageV2.parts(id)
|
||||||
expect(result).toHaveLength(1)
|
expect(result).toHaveLength(1)
|
||||||
expect(result[0].type).toBe("text")
|
expect(result[0].type).toBe("text")
|
||||||
expect((result[0] as MessageV2.TextPart).text).toBe("m0")
|
expect((result[0] as MessageV2.TextPart).text).toBe("m0")
|
||||||
})),
|
}),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
it.instance("returns empty array for message with no parts", () =>
|
it.instance("returns empty array for message with no parts", () =>
|
||||||
withSession(({ sessionID }) => Effect.gen(function* () {
|
withSession(({ sessionID }) =>
|
||||||
|
Effect.gen(function* () {
|
||||||
const id = yield* addUser(sessionID)
|
const id = yield* addUser(sessionID)
|
||||||
|
|
||||||
const result = MessageV2.parts(id)
|
const result = MessageV2.parts(id)
|
||||||
expect(result).toEqual([])
|
expect(result).toEqual([])
|
||||||
})),
|
}),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
it.instance("returns multiple parts in order", () =>
|
it.instance("returns multiple parts in order", () =>
|
||||||
withSession(({ session, sessionID }) => Effect.gen(function* () {
|
withSession(({ session, sessionID }) =>
|
||||||
|
Effect.gen(function* () {
|
||||||
const [id] = yield* fill(sessionID, 1)
|
const [id] = yield* fill(sessionID, 1)
|
||||||
|
|
||||||
yield* session.updatePart({
|
yield* session.updatePart({
|
||||||
|
|
@ -390,7 +427,8 @@ describe("MessageV2.parts", () => {
|
||||||
expect((result[0] as MessageV2.TextPart).text).toBe("m0")
|
expect((result[0] as MessageV2.TextPart).text).toBe("m0")
|
||||||
expect((result[1] as MessageV2.TextPart).text).toBe("second")
|
expect((result[1] as MessageV2.TextPart).text).toBe("second")
|
||||||
expect((result[2] as MessageV2.TextPart).text).toBe("third")
|
expect((result[2] as MessageV2.TextPart).text).toBe("third")
|
||||||
})),
|
}),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
it.instance("returns empty for non-existent message id", () =>
|
it.instance("returns empty for non-existent message id", () =>
|
||||||
|
|
@ -402,19 +440,22 @@ describe("MessageV2.parts", () => {
|
||||||
)
|
)
|
||||||
|
|
||||||
it.instance("parts contain sessionID and messageID", () =>
|
it.instance("parts contain sessionID and messageID", () =>
|
||||||
withSession(({ sessionID }) => Effect.gen(function* () {
|
withSession(({ sessionID }) =>
|
||||||
|
Effect.gen(function* () {
|
||||||
const [id] = yield* fill(sessionID, 1)
|
const [id] = yield* fill(sessionID, 1)
|
||||||
|
|
||||||
const result = MessageV2.parts(id)
|
const result = MessageV2.parts(id)
|
||||||
expect(result[0].sessionID).toBe(sessionID)
|
expect(result[0].sessionID).toBe(sessionID)
|
||||||
expect(result[0].messageID).toBe(id)
|
expect(result[0].messageID).toBe(id)
|
||||||
})),
|
}),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("MessageV2.get", () => {
|
describe("MessageV2.get", () => {
|
||||||
it.instance("returns message with hydrated parts", () =>
|
it.instance("returns message with hydrated parts", () =>
|
||||||
withSession(({ sessionID }) => Effect.gen(function* () {
|
withSession(({ sessionID }) =>
|
||||||
|
Effect.gen(function* () {
|
||||||
const [id] = yield* fill(sessionID, 1)
|
const [id] = yield* fill(sessionID, 1)
|
||||||
|
|
||||||
const result = MessageV2.get({ sessionID, messageID: id })
|
const result = MessageV2.get({ sessionID, messageID: id })
|
||||||
|
|
@ -423,15 +464,16 @@ describe("MessageV2.get", () => {
|
||||||
expect(result.info.role).toBe("user")
|
expect(result.info.role).toBe("user")
|
||||||
expect(result.parts).toHaveLength(1)
|
expect(result.parts).toHaveLength(1)
|
||||||
expect((result.parts[0] as MessageV2.TextPart).text).toBe("m0")
|
expect((result.parts[0] as MessageV2.TextPart).text).toBe("m0")
|
||||||
})),
|
}),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
it.instance("throws NotFoundError for non-existent message", () =>
|
it.instance("throws NotFoundError for non-existent message", () =>
|
||||||
withSession(({ sessionID }) => Effect.gen(function* () {
|
withSession(({ sessionID }) =>
|
||||||
expect(() => MessageV2.get({ sessionID, messageID: MessageID.ascending() })).toThrow(
|
Effect.gen(function* () {
|
||||||
"NotFoundError",
|
expect(() => MessageV2.get({ sessionID, messageID: MessageID.ascending() })).toThrow("NotFoundError")
|
||||||
)
|
}),
|
||||||
})),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
it.instance("scopes by session id", () =>
|
it.instance("scopes by session id", () =>
|
||||||
|
|
@ -451,7 +493,8 @@ describe("MessageV2.get", () => {
|
||||||
)
|
)
|
||||||
|
|
||||||
it.instance("returns message with multiple parts", () =>
|
it.instance("returns message with multiple parts", () =>
|
||||||
withSession(({ session, sessionID }) => Effect.gen(function* () {
|
withSession(({ session, sessionID }) =>
|
||||||
|
Effect.gen(function* () {
|
||||||
const [id] = yield* fill(sessionID, 1)
|
const [id] = yield* fill(sessionID, 1)
|
||||||
|
|
||||||
yield* session.updatePart({
|
yield* session.updatePart({
|
||||||
|
|
@ -464,11 +507,13 @@ describe("MessageV2.get", () => {
|
||||||
|
|
||||||
const result = MessageV2.get({ sessionID, messageID: id })
|
const result = MessageV2.get({ sessionID, messageID: id })
|
||||||
expect(result.parts).toHaveLength(2)
|
expect(result.parts).toHaveLength(2)
|
||||||
})),
|
}),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
it.instance("returns assistant message with correct role", () =>
|
it.instance("returns assistant message with correct role", () =>
|
||||||
withSession(({ session, sessionID }) => Effect.gen(function* () {
|
withSession(({ session, sessionID }) =>
|
||||||
|
Effect.gen(function* () {
|
||||||
const uid = yield* addUser(sessionID, "hello")
|
const uid = yield* addUser(sessionID, "hello")
|
||||||
const aid = yield* addAssistant(sessionID, uid)
|
const aid = yield* addAssistant(sessionID, uid)
|
||||||
|
|
||||||
|
|
@ -484,34 +529,40 @@ describe("MessageV2.get", () => {
|
||||||
expect(result.info.role).toBe("assistant")
|
expect(result.info.role).toBe("assistant")
|
||||||
expect(result.parts).toHaveLength(1)
|
expect(result.parts).toHaveLength(1)
|
||||||
expect((result.parts[0] as MessageV2.TextPart).text).toBe("response")
|
expect((result.parts[0] as MessageV2.TextPart).text).toBe("response")
|
||||||
})),
|
}),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
it.instance("returns message with zero parts", () =>
|
it.instance("returns message with zero parts", () =>
|
||||||
withSession(({ sessionID }) => Effect.gen(function* () {
|
withSession(({ sessionID }) =>
|
||||||
|
Effect.gen(function* () {
|
||||||
const id = yield* addUser(sessionID)
|
const id = yield* addUser(sessionID)
|
||||||
|
|
||||||
const result = MessageV2.get({ sessionID, messageID: id })
|
const result = MessageV2.get({ sessionID, messageID: id })
|
||||||
expect(result.info.id).toBe(id)
|
expect(result.info.id).toBe(id)
|
||||||
expect(result.parts).toEqual([])
|
expect(result.parts).toEqual([])
|
||||||
})),
|
}),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("MessageV2.filterCompacted", () => {
|
describe("MessageV2.filterCompacted", () => {
|
||||||
it.instance("returns all messages when no compaction", () =>
|
it.instance("returns all messages when no compaction", () =>
|
||||||
withSession(({ sessionID }) => Effect.gen(function* () {
|
withSession(({ sessionID }) =>
|
||||||
|
Effect.gen(function* () {
|
||||||
const ids = yield* fill(sessionID, 5)
|
const ids = yield* fill(sessionID, 5)
|
||||||
|
|
||||||
const result = MessageV2.filterCompacted(MessageV2.stream(sessionID))
|
const result = MessageV2.filterCompacted(MessageV2.stream(sessionID))
|
||||||
expect(result).toHaveLength(5)
|
expect(result).toHaveLength(5)
|
||||||
// reversed from newest-first to chronological
|
// reversed from newest-first to chronological
|
||||||
expect(result.map((item) => item.info.id)).toEqual(ids)
|
expect(result.map((item) => item.info.id)).toEqual(ids)
|
||||||
})),
|
}),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
it.instance("stops at compaction boundary and returns chronological order", () =>
|
it.instance("stops at compaction boundary and returns chronological order", () =>
|
||||||
withSession(({ session, sessionID }) => Effect.gen(function* () {
|
withSession(({ session, sessionID }) =>
|
||||||
|
Effect.gen(function* () {
|
||||||
// Chronological: u1(+compaction part), a1(summary, parentID=u1), u2, a2
|
// Chronological: u1(+compaction part), a1(summary, parentID=u1), u2, a2
|
||||||
// Stream (newest first): a2, u2, a1(adds u1 to completed), u1(in completed + compaction) -> break
|
// Stream (newest first): a2, u2, a1(adds u1 to completed), u1(in completed + compaction) -> break
|
||||||
const u1 = yield* addUser(sessionID, "first question")
|
const u1 = yield* addUser(sessionID, "first question")
|
||||||
|
|
@ -539,27 +590,33 @@ describe("MessageV2.filterCompacted", () => {
|
||||||
// Includes compaction boundary: u1, a1, u2, a2
|
// Includes compaction boundary: u1, a1, u2, a2
|
||||||
expect(result[0].info.id).toBe(u1)
|
expect(result[0].info.id).toBe(u1)
|
||||||
expect(result.length).toBe(4)
|
expect(result.length).toBe(4)
|
||||||
})),
|
}),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
it.live("handles empty iterable", () => Effect.sync(() => {
|
it.live("handles empty iterable", () =>
|
||||||
|
Effect.sync(() => {
|
||||||
const result = MessageV2.filterCompacted([])
|
const result = MessageV2.filterCompacted([])
|
||||||
expect(result).toEqual([])
|
expect(result).toEqual([])
|
||||||
}))
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
it.instance("does not break on compaction part without matching summary", () =>
|
it.instance("does not break on compaction part without matching summary", () =>
|
||||||
withSession(({ sessionID }) => Effect.gen(function* () {
|
withSession(({ sessionID }) =>
|
||||||
|
Effect.gen(function* () {
|
||||||
const u1 = yield* addUser(sessionID, "hello")
|
const u1 = yield* addUser(sessionID, "hello")
|
||||||
yield* addCompactionPart(sessionID, u1)
|
yield* addCompactionPart(sessionID, u1)
|
||||||
yield* addUser(sessionID, "world")
|
yield* addUser(sessionID, "world")
|
||||||
|
|
||||||
const result = MessageV2.filterCompacted(MessageV2.stream(sessionID))
|
const result = MessageV2.filterCompacted(MessageV2.stream(sessionID))
|
||||||
expect(result).toHaveLength(2)
|
expect(result).toHaveLength(2)
|
||||||
})),
|
}),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
it.instance("skips assistant with error even if marked as summary", () =>
|
it.instance("skips assistant with error even if marked as summary", () =>
|
||||||
withSession(({ sessionID }) => Effect.gen(function* () {
|
withSession(({ sessionID }) =>
|
||||||
|
Effect.gen(function* () {
|
||||||
const u1 = yield* addUser(sessionID, "hello")
|
const u1 = yield* addUser(sessionID, "hello")
|
||||||
yield* addCompactionPart(sessionID, u1)
|
yield* addCompactionPart(sessionID, u1)
|
||||||
|
|
||||||
|
|
@ -573,11 +630,13 @@ describe("MessageV2.filterCompacted", () => {
|
||||||
const result = MessageV2.filterCompacted(MessageV2.stream(sessionID))
|
const result = MessageV2.filterCompacted(MessageV2.stream(sessionID))
|
||||||
// Error assistant doesn't add to completed, so compaction boundary never triggers
|
// Error assistant doesn't add to completed, so compaction boundary never triggers
|
||||||
expect(result).toHaveLength(3)
|
expect(result).toHaveLength(3)
|
||||||
})),
|
}),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
it.instance("skips assistant without finish even if marked as summary", () =>
|
it.instance("skips assistant without finish even if marked as summary", () =>
|
||||||
withSession(({ sessionID }) => Effect.gen(function* () {
|
withSession(({ sessionID }) =>
|
||||||
|
Effect.gen(function* () {
|
||||||
const u1 = yield* addUser(sessionID, "hello")
|
const u1 = yield* addUser(sessionID, "hello")
|
||||||
yield* addCompactionPart(sessionID, u1)
|
yield* addCompactionPart(sessionID, u1)
|
||||||
|
|
||||||
|
|
@ -587,11 +646,13 @@ describe("MessageV2.filterCompacted", () => {
|
||||||
|
|
||||||
const result = MessageV2.filterCompacted(MessageV2.stream(sessionID))
|
const result = MessageV2.filterCompacted(MessageV2.stream(sessionID))
|
||||||
expect(result).toHaveLength(3)
|
expect(result).toHaveLength(3)
|
||||||
})),
|
}),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
it.instance("ignores original tail when compaction stores tail_start_id", () =>
|
it.instance("ignores original tail when compaction stores tail_start_id", () =>
|
||||||
withSession(({ session, sessionID }) => Effect.gen(function* () {
|
withSession(({ session, sessionID }) =>
|
||||||
|
Effect.gen(function* () {
|
||||||
const u1 = yield* addUser(sessionID, "first")
|
const u1 = yield* addUser(sessionID, "first")
|
||||||
const a1 = yield* addAssistant(sessionID, u1, { finish: "end_turn" })
|
const a1 = yield* addAssistant(sessionID, u1, { finish: "end_turn" })
|
||||||
yield* session.updatePart({
|
yield* session.updatePart({
|
||||||
|
|
@ -636,7 +697,8 @@ describe("MessageV2.filterCompacted", () => {
|
||||||
const result = MessageV2.filterCompacted(MessageV2.stream(sessionID))
|
const result = MessageV2.filterCompacted(MessageV2.stream(sessionID))
|
||||||
|
|
||||||
expect(result.map((item) => item.info.id)).toEqual([c1, s1, u3, a3])
|
expect(result.map((item) => item.info.id)).toEqual([c1, s1, u3, a3])
|
||||||
})),
|
}),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
it.instance("fork keeps legacy tail_start_id without replaying the tail", () =>
|
it.instance("fork keeps legacy tail_start_id without replaying the tail", () =>
|
||||||
|
|
@ -704,7 +766,8 @@ describe("MessageV2.filterCompacted", () => {
|
||||||
)
|
)
|
||||||
|
|
||||||
it.instance("does not replay an assistant tail when compaction starts inside a turn", () =>
|
it.instance("does not replay an assistant tail when compaction starts inside a turn", () =>
|
||||||
withSession(({ session, sessionID }) => Effect.gen(function* () {
|
withSession(({ session, sessionID }) =>
|
||||||
|
Effect.gen(function* () {
|
||||||
const u1 = yield* addUser(sessionID, "first")
|
const u1 = yield* addUser(sessionID, "first")
|
||||||
const a1 = yield* addAssistant(sessionID, u1, { finish: "end_turn" })
|
const a1 = yield* addAssistant(sessionID, u1, { finish: "end_turn" })
|
||||||
yield* session.updatePart({
|
yield* session.updatePart({
|
||||||
|
|
@ -757,11 +820,13 @@ describe("MessageV2.filterCompacted", () => {
|
||||||
const result = MessageV2.filterCompacted(MessageV2.stream(sessionID))
|
const result = MessageV2.filterCompacted(MessageV2.stream(sessionID))
|
||||||
|
|
||||||
expect(result.map((item) => item.info.id)).toEqual([c1, s1, u3, a4])
|
expect(result.map((item) => item.info.id)).toEqual([c1, s1, u3, a4])
|
||||||
})),
|
}),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
it.instance("prefers latest compaction boundary when repeated compactions exist", () =>
|
it.instance("prefers latest compaction boundary when repeated compactions exist", () =>
|
||||||
withSession(({ session, sessionID }) => Effect.gen(function* () {
|
withSession(({ session, sessionID }) =>
|
||||||
|
Effect.gen(function* () {
|
||||||
const u1 = yield* addUser(sessionID, "first")
|
const u1 = yield* addUser(sessionID, "first")
|
||||||
const a1 = yield* addAssistant(sessionID, u1, { finish: "end_turn" })
|
const a1 = yield* addAssistant(sessionID, u1, { finish: "end_turn" })
|
||||||
yield* session.updatePart({
|
yield* session.updatePart({
|
||||||
|
|
@ -827,7 +892,8 @@ describe("MessageV2.filterCompacted", () => {
|
||||||
const result = MessageV2.filterCompacted(MessageV2.stream(sessionID))
|
const result = MessageV2.filterCompacted(MessageV2.stream(sessionID))
|
||||||
|
|
||||||
expect(result.map((item) => item.info.id)).toEqual([c2, s2, u4, a4])
|
expect(result.map((item) => item.info.id)).toEqual([c2, s2, u4, a4])
|
||||||
})),
|
}),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
test("works with array input", () => {
|
test("works with array input", () => {
|
||||||
|
|
@ -876,7 +942,8 @@ describe("MessageV2.cursor", () => {
|
||||||
|
|
||||||
describe("MessageV2 consistency", () => {
|
describe("MessageV2 consistency", () => {
|
||||||
it.instance("page hydration matches get for each message", () =>
|
it.instance("page hydration matches get for each message", () =>
|
||||||
withSession(({ sessionID }) => Effect.gen(function* () {
|
withSession(({ sessionID }) =>
|
||||||
|
Effect.gen(function* () {
|
||||||
yield* fill(sessionID, 3)
|
yield* fill(sessionID, 3)
|
||||||
|
|
||||||
const paged = MessageV2.page({ sessionID, limit: 10 })
|
const paged = MessageV2.page({ sessionID, limit: 10 })
|
||||||
|
|
@ -885,21 +952,25 @@ describe("MessageV2 consistency", () => {
|
||||||
expect(got.info).toEqual(item.info)
|
expect(got.info).toEqual(item.info)
|
||||||
expect(got.parts).toEqual(item.parts)
|
expect(got.parts).toEqual(item.parts)
|
||||||
}
|
}
|
||||||
})),
|
}),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
it.instance("parts from get match standalone parts call", () =>
|
it.instance("parts from get match standalone parts call", () =>
|
||||||
withSession(({ sessionID }) => Effect.gen(function* () {
|
withSession(({ sessionID }) =>
|
||||||
|
Effect.gen(function* () {
|
||||||
const [id] = yield* fill(sessionID, 1)
|
const [id] = yield* fill(sessionID, 1)
|
||||||
|
|
||||||
const got = MessageV2.get({ sessionID, messageID: id })
|
const got = MessageV2.get({ sessionID, messageID: id })
|
||||||
const standalone = MessageV2.parts(id)
|
const standalone = MessageV2.parts(id)
|
||||||
expect(got.parts).toEqual(standalone)
|
expect(got.parts).toEqual(standalone)
|
||||||
})),
|
}),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
it.instance("stream collects same messages as exhaustive page iteration", () =>
|
it.instance("stream collects same messages as exhaustive page iteration", () =>
|
||||||
withSession(({ sessionID }) => Effect.gen(function* () {
|
withSession(({ sessionID }) =>
|
||||||
|
Effect.gen(function* () {
|
||||||
yield* fill(sessionID, 7)
|
yield* fill(sessionID, 7)
|
||||||
|
|
||||||
const streamed = Array.from(MessageV2.stream(sessionID))
|
const streamed = Array.from(MessageV2.stream(sessionID))
|
||||||
|
|
@ -916,17 +987,20 @@ describe("MessageV2 consistency", () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
expect(streamed.map((m) => m.info.id)).toEqual(paged.map((m) => m.info.id))
|
expect(streamed.map((m) => m.info.id)).toEqual(paged.map((m) => m.info.id))
|
||||||
})),
|
}),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
it.instance("filterCompacted of full stream returns same as Array.from when no compaction", () =>
|
it.instance("filterCompacted of full stream returns same as Array.from when no compaction", () =>
|
||||||
withSession(({ sessionID }) => Effect.gen(function* () {
|
withSession(({ sessionID }) =>
|
||||||
|
Effect.gen(function* () {
|
||||||
yield* fill(sessionID, 4)
|
yield* fill(sessionID, 4)
|
||||||
|
|
||||||
const filtered = MessageV2.filterCompacted(MessageV2.stream(sessionID))
|
const filtered = MessageV2.filterCompacted(MessageV2.stream(sessionID))
|
||||||
const all = Array.from(MessageV2.stream(sessionID)).reverse()
|
const all = Array.from(MessageV2.stream(sessionID)).reverse()
|
||||||
|
|
||||||
expect(filtered.map((m) => m.info.id)).toEqual(all.map((m) => m.info.id))
|
expect(filtered.map((m) => m.info.id)).toEqual(all.map((m) => m.info.id))
|
||||||
})),
|
}),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue