Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
109 changes: 32 additions & 77 deletions apps/api/src/routes/content/post.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,12 @@ describe("Post Routes Tests", () => {
test("returns a post with its authors and a chapter list sorted by collectionOrder", async () => {
vi.mocked(db.query.posts.findFirst).mockResolvedValue({
slug: "chapter-two",
data: [
{
title: "Chapter Two",
description: "The second chapter",
bannerImage: "content/banner.png",
socialImage: "content/social.png",
wordCount: 500,
publishedAt: new Date("2024-01-15T00:00:00Z"),
},
],
title: "Chapter Two",
description: "The second chapter",
bannerImage: "content/banner.png",
socialImage: "content/social.png",
wordCount: 500,
publishedAt: new Date("2024-01-15T00:00:00Z"),
authors: [
{
slug: "crutchcorn",
Expand All @@ -41,12 +37,12 @@ describe("Post Routes Tests", () => {
{
slug: "chapter-two",
collectionOrder: 1,
data: [{ title: "Chapter Two" }],
title: "Chapter Two",
},
{
slug: "chapter-one",
collectionOrder: 0,
data: [{ title: "Chapter One" }],
title: "Chapter One",
},
],
},
Expand Down Expand Up @@ -96,16 +92,12 @@ describe("Post Routes Tests", () => {
test("omits collection when the post is not part of a collection", async () => {
vi.mocked(db.query.posts.findFirst).mockResolvedValue({
slug: "standalone-post",
data: [
{
title: "Standalone Post",
description: "A post with no collection",
bannerImage: null,
socialImage: null,
wordCount: 200,
publishedAt: new Date("2024-01-15T00:00:00Z"),
},
],
title: "Standalone Post",
description: "A post with no collection",
bannerImage: null,
socialImage: null,
wordCount: 200,
publishedAt: new Date("2024-01-15T00:00:00Z"),
authors: [
{ slug: "crutchcorn", name: "Corbin Crutchley", profileImage: null },
],
Expand Down Expand Up @@ -139,16 +131,12 @@ describe("Post Routes Tests", () => {
test("returns 404 when the requested post is unpublished for the locale", async () => {
vi.mocked(db.query.posts.findFirst).mockResolvedValue({
slug: "draft-post",
data: [
{
title: "Draft Post",
description: "Not yet published",
bannerImage: null,
socialImage: null,
wordCount: 100,
publishedAt: null,
},
],
title: "Draft Post",
description: "Not yet published",
bannerImage: null,
socialImage: null,
wordCount: 100,
publishedAt: null,
authors: [],
collection: null,
} as never);
Expand All @@ -170,16 +158,12 @@ describe("Post Routes Tests", () => {
test("excludes unpublished sibling chapters from the chapter list", async () => {
vi.mocked(db.query.posts.findFirst).mockResolvedValue({
slug: "chapter-one",
data: [
{
title: "Chapter One",
description: "The first chapter",
bannerImage: null,
socialImage: null,
wordCount: 300,
publishedAt: new Date("2024-01-15T00:00:00Z"),
},
],
title: "Chapter One",
description: "The first chapter",
bannerImage: null,
socialImage: null,
wordCount: 300,
publishedAt: new Date("2024-01-15T00:00:00Z"),
authors: [],
collection: {
slug: "example-collection",
Expand All @@ -188,27 +172,20 @@ describe("Post Routes Tests", () => {
{
slug: "chapter-one",
collectionOrder: 0,
data: [
{
title: "Chapter One",
publishedAt: new Date("2024-01-15T00:00:00Z"),
},
],
title: "Chapter One",
publishedAt: new Date("2024-01-15T00:00:00Z"),
},
{
slug: "chapter-two-draft",
collectionOrder: 1,
data: [{ title: "Chapter Two (Draft)", publishedAt: null }],
title: "Chapter Two (Draft)",
publishedAt: null,
},
{
slug: "chapter-three",
collectionOrder: 2,
data: [
{
title: "Chapter Three",
publishedAt: new Date("2024-01-20T00:00:00Z"),
},
],
title: "Chapter Three",
publishedAt: new Date("2024-01-20T00:00:00Z"),
},
],
},
Expand Down Expand Up @@ -263,27 +240,5 @@ describe("Post Routes Tests", () => {
}
`);
});

test("returns 404 when the post has no post_data row for the requested locale", async () => {
vi.mocked(db.query.posts.findFirst).mockResolvedValue({
slug: "spanish-only-post",
data: [],
authors: [],
collection: null,
} as never);

const response = await app.inject({
method: "GET",
url: "/content/post/spanish-only-post",
query: { locale: "en" },
});

expect(response.statusCode).toBe(404);
expect(response.json()).toMatchInlineSnapshot(`
{
"error": "Post not found",
}
`);
});
});
});
66 changes: 30 additions & 36 deletions apps/api/src/routes/content/post.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const PostParamsSchema = Type.Object({

const PostQueryParamsSchema = Type.Object({
locale: Type.String({ default: "en" }),
branch: Type.String({ default: "main" }),
});

const PostResponseSchema = Type.Intersect(
Expand Down Expand Up @@ -99,22 +100,20 @@ const postRoutes: FastifyPluginAsync = async (fastify) => {
},
async (request, reply) => {
const { slug } = request.params;
const { locale } = request.query;
const { locale, branch } = request.query;

const post = await db.query.posts.findFirst({
where: { slug },
where: { slug, locale, branch },
columns: {
slug: true,
title: true,
description: true,
bannerImage: true,
socialImage: true,
wordCount: true,
publishedAt: true,
},
with: {
data: {
columns: {
title: true,
description: true,
bannerImage: true,
socialImage: true,
wordCount: true,
publishedAt: true,
},
where: { locale },
},
authors: { columns: { slug: true, name: true, profileImage: true } },
collection: {
with: {
Expand All @@ -123,22 +122,20 @@ const postRoutes: FastifyPluginAsync = async (fastify) => {
where: { locale },
},
posts: {
columns: { slug: true, collectionOrder: true },
with: {
data: {
columns: { title: true, publishedAt: true },
where: { locale },
},
columns: {
slug: true,
collectionOrder: true,
title: true,
publishedAt: true,
},
where: { locale, branch },
},
},
},
},
});

const postData = post?.data[0];

if (!post || !postData || postData.publishedAt === null) {
if (!post || post.publishedAt === null) {
reply.code(404);
reply.send({ error: "Post not found" });
return;
Expand All @@ -152,31 +149,28 @@ const postRoutes: FastifyPluginAsync = async (fastify) => {
slug: post.collection.slug,
title: collectionData.title,
chapters: post.collection.posts
.filter(
(chapter) =>
chapter.data[0] && chapter.data[0].publishedAt !== null,
)
.filter((chapter) => chapter.publishedAt !== null)
.sort((a, b) => a.collectionOrder - b.collectionOrder)
.map((chapter) => ({
slug: chapter.slug,
title: chapter.data[0].title,
title: chapter.title,
})),
}
: undefined;

const response: PostResponse = {
slug: post.slug,
title: postData.title,
description: postData.description,
bannerUrl: postData.bannerImage
? createImageUrl(postData.bannerImage)
title: post.title,
description: post.description,
bannerUrl: post.bannerImage
? createImageUrl(post.bannerImage)
: undefined,
socialImageUrl: postData.socialImage
? createImageUrl(postData.socialImage)
socialImageUrl: post.socialImage
? createImageUrl(post.socialImage)
: undefined,
wordCount: postData.wordCount,
publishedAt: postData.publishedAt
? postData.publishedAt.toISOString()
wordCount: post.wordCount,
publishedAt: post.publishedAt
? post.publishedAt.toISOString()
: undefined,
authors: post.authors.map((author) => ({
id: author.slug,
Expand Down
Loading