mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-08-07 09:01:29 -04:00
Fix after
when sorting with remmapped keys
This commit is contained in:
parent
6e293efc2b
commit
81958f6c3b
@ -49,6 +49,9 @@ export const keysetPaginate = <
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const generateAfter = (cursor: any, sort: Sort<any, any>) => {
|
export const generateAfter = (cursor: any, sort: Sort<any, any>) => {
|
||||||
const ret = [...sort.map((by) => cursor[by.key]), cursor.pk];
|
const ret = [
|
||||||
|
...sort.map((by) => cursor[by.remmapedKey ?? by.key]),
|
||||||
|
cursor.pk,
|
||||||
|
];
|
||||||
return Buffer.from(JSON.stringify(ret), "utf-8").toString("base64url");
|
return Buffer.from(JSON.stringify(ret), "utf-8").toString("base64url");
|
||||||
};
|
};
|
||||||
|
@ -5,6 +5,7 @@ export type Sort<
|
|||||||
Remap extends Partial<Record<T[number], string>>,
|
Remap extends Partial<Record<T[number], string>>,
|
||||||
> = {
|
> = {
|
||||||
key: Exclude<T[number], keyof Remap> | NonNullable<Remap[keyof Remap]>;
|
key: Exclude<T[number], keyof Remap> | NonNullable<Remap[keyof Remap]>;
|
||||||
|
remmapedKey?: keyof Remap;
|
||||||
desc: boolean;
|
desc: boolean;
|
||||||
}[];
|
}[];
|
||||||
|
|
||||||
@ -44,7 +45,7 @@ export const Sort = <
|
|||||||
return sort.map((x) => {
|
return sort.map((x) => {
|
||||||
const desc = x[0] === "-";
|
const desc = x[0] === "-";
|
||||||
const key = (desc ? x.substring(1) : x) as T[number];
|
const key = (desc ? x.substring(1) : x) as T[number];
|
||||||
if (key in remap) return { key: remap[key]!, desc };
|
if (key in remap) return { key: remap[key]!, remmapedKey: key, desc };
|
||||||
return { key: key as Exclude<typeof key, keyof Remap>, desc };
|
return { key: key as Exclude<typeof key, keyof Remap>, desc };
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { afterAll, beforeAll, describe, expect, it } from "bun:test";
|
import { afterAll, beforeAll, describe, expect, it } from "bun:test";
|
||||||
import { eq } from "drizzle-orm";
|
|
||||||
import Elysia from "elysia";
|
import Elysia from "elysia";
|
||||||
import { base } from "~/base";
|
import { base } from "~/base";
|
||||||
import { movies } from "~/controllers/movies";
|
import { movies } from "~/controllers/movies";
|
||||||
@ -18,7 +17,7 @@ const getMovies = async ({
|
|||||||
filter?: string;
|
filter?: string;
|
||||||
limit?: number;
|
limit?: number;
|
||||||
after?: string;
|
after?: string;
|
||||||
sort?: string[];
|
sort?: string | string[];
|
||||||
langs?: string;
|
langs?: string;
|
||||||
}) => {
|
}) => {
|
||||||
const params = new URLSearchParams();
|
const params = new URLSearchParams();
|
||||||
@ -98,7 +97,7 @@ describe("Get all movies", () => {
|
|||||||
this: "http://localhost/movies?limit=2",
|
this: "http://localhost/movies?limit=2",
|
||||||
// we can't have the exact after since it contains the pk that changes with every tests.
|
// we can't have the exact after since it contains the pk that changes with every tests.
|
||||||
next: expect.stringContaining(
|
next: expect.stringContaining(
|
||||||
"http://localhost/movies?limit=2&after=WyJkdW5lIiw0",
|
"http://localhost/movies?limit=2&after=WyJkdW5lIiw",
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -116,11 +115,43 @@ describe("Get all movies", () => {
|
|||||||
expect(body).toMatchObject({
|
expect(body).toMatchObject({
|
||||||
items: [expect.objectContaining({ slug: dune1984.slug })],
|
items: [expect.objectContaining({ slug: dune1984.slug })],
|
||||||
this: expect.stringContaining(
|
this: expect.stringContaining(
|
||||||
"http://localhost/movies?limit=2&after=WyJkdW5lIiw0",
|
"http://localhost/movies?limit=2&after=WyJkdW5lIiw",
|
||||||
),
|
),
|
||||||
next: null,
|
next: null,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
it("Limit 2, sort by dates desc, page 2", async () => {
|
||||||
|
let [resp, body] = await getMovies({
|
||||||
|
limit: 2,
|
||||||
|
sort: "-airDate",
|
||||||
|
langs: "en",
|
||||||
|
});
|
||||||
|
expectStatus(resp, body).toBe(200);
|
||||||
|
|
||||||
|
// we copy this due to https://github.com/oven-sh/bun/issues/3521
|
||||||
|
const next = body.next;
|
||||||
|
expect(body).toMatchObject({
|
||||||
|
items: [
|
||||||
|
expect.objectContaining({ slug: bubble.slug, airDate: bubble.airDate }),
|
||||||
|
expect.objectContaining({ slug: dune.slug, airDate: dune.airDate }),
|
||||||
|
],
|
||||||
|
this: "http://localhost/movies?limit=2&sort=-airDate",
|
||||||
|
next: expect.stringContaining(
|
||||||
|
"http://localhost/movies?limit=2&sort=-airDate&after=WyIyMDIxLTEwLTIyIiw",
|
||||||
|
),
|
||||||
|
});
|
||||||
|
|
||||||
|
resp = await app.handle(new Request(next));
|
||||||
|
body = await resp.json();
|
||||||
|
|
||||||
|
expectStatus(resp, body).toBe(200);
|
||||||
|
expect(body).toMatchObject({
|
||||||
|
items: [expect.objectContaining({ slug: dune1984.slug })],
|
||||||
|
this: next,
|
||||||
|
next: null,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
// TODO: sort with an item that has null in it. We want it to always be last (in both asc & desc).
|
||||||
});
|
});
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user