aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArmand Philippot <git@armandphilippot.com>2023-11-27 19:40:40 +0100
committerArmand Philippot <git@armandphilippot.com>2023-11-28 18:04:24 +0100
commitfb749e8befb2dcdc266c2e8b7ef7c9001947143a (patch)
tree80ae62cd0a699d4feb14fe2a239b4fe317a400a0
parentab81df7f3d317281a05caec18e2cfd89dc26bc7a (diff)
test(services): add tests for posts fetchers
-rw-r--r--src/services/graphql/fetchers/posts/fetch-all-posts-slugs.test.ts26
-rw-r--r--src/services/graphql/fetchers/posts/fetch-all-posts-slugs.ts2
-rw-r--r--src/services/graphql/fetchers/posts/fetch-last-post-cursor.test.ts25
-rw-r--r--src/services/graphql/fetchers/posts/fetch-last-post-cursor.ts6
-rw-r--r--src/services/graphql/fetchers/posts/fetch-post.test.ts23
-rw-r--r--src/services/graphql/fetchers/posts/fetch-post.ts2
-rw-r--r--src/services/graphql/fetchers/posts/fetch-posts-count.test.ts26
-rw-r--r--src/services/graphql/fetchers/posts/fetch-posts-count.ts6
-rw-r--r--src/services/graphql/fetchers/posts/fetch-posts-list.test.ts26
-rw-r--r--src/services/graphql/fetchers/posts/fetch-posts-list.ts2
-rw-r--r--src/services/graphql/fetchers/posts/fetch-recent-posts.test.ts25
-rw-r--r--src/services/graphql/fetchers/posts/fetch-recent-posts.ts2
-rw-r--r--src/utils/hooks/use-posts-list/use-posts-list.test.ts24
-rw-r--r--src/utils/hooks/use-posts-list/use-posts-list.test.tsx74
-rw-r--r--tests/fixtures/index.ts1
-rw-r--r--tests/fixtures/wp-posts.fixture.ts177
-rw-r--r--tests/msw/handlers/index.ts3
-rw-r--r--tests/msw/handlers/posts/index.ts15
-rw-r--r--tests/msw/handlers/posts/last-post-cursor.handler.ts33
-rw-r--r--tests/msw/handlers/posts/post.handler.ts21
-rw-r--r--tests/msw/handlers/posts/posts-count.handler.ts51
-rw-r--r--tests/msw/handlers/posts/posts-list.handler.ts50
-rw-r--r--tests/msw/handlers/posts/posts-slugs.handler.ts26
-rw-r--r--tests/msw/handlers/posts/recent-posts.handler.ts50
-rw-r--r--tests/msw/index.ts3
-rw-r--r--tests/msw/schema/types/index.ts5
-rw-r--r--tests/msw/schema/types/post.types.ts8
27 files changed, 675 insertions, 37 deletions
diff --git a/src/services/graphql/fetchers/posts/fetch-all-posts-slugs.test.ts b/src/services/graphql/fetchers/posts/fetch-all-posts-slugs.test.ts
new file mode 100644
index 0000000..a90df02
--- /dev/null
+++ b/src/services/graphql/fetchers/posts/fetch-all-posts-slugs.test.ts
@@ -0,0 +1,26 @@
+import { afterEach, describe, expect, it } from '@jest/globals';
+import { wpPostsFixture } from '../../../../../tests/fixtures';
+import { fetchAllPostsSlugs } from './fetch-all-posts-slugs';
+
+describe('fetch-all-posts-slugs', () => {
+ afterEach(() => {
+ window.history.replaceState({}, '', '/');
+ });
+
+ it('returns the WordPress posts using GraphQL', async () => {
+ const result = await fetchAllPostsSlugs(wpPostsFixture.length);
+
+ expect.assertions(1);
+
+ expect(result).toStrictEqual(wpPostsFixture.map((post) => post.slug));
+ });
+
+ it('rejects with an error when no posts are found', async () => {
+ window.history.replaceState({}, '', '/?error=true');
+ expect.assertions(1);
+
+ await expect(async () =>
+ fetchAllPostsSlugs(wpPostsFixture.length)
+ ).rejects.toEqual(new Error('Unable to find the posts slugs.'));
+ });
+});
diff --git a/src/services/graphql/fetchers/posts/fetch-all-posts-slugs.ts b/src/services/graphql/fetchers/posts/fetch-all-posts-slugs.ts
index 25cc782..cca83ff 100644
--- a/src/services/graphql/fetchers/posts/fetch-all-posts-slugs.ts
+++ b/src/services/graphql/fetchers/posts/fetch-all-posts-slugs.ts
@@ -1,7 +1,7 @@
import type { GraphQLNodes, Nullable, SlugNode } from '../../../../types';
import { fetchGraphQL, getGraphQLUrl } from '../../../../utils/helpers';
-type PostsSlugsResponse = {
+export type PostsSlugsResponse = {
posts: Nullable<GraphQLNodes<SlugNode>>;
};
diff --git a/src/services/graphql/fetchers/posts/fetch-last-post-cursor.test.ts b/src/services/graphql/fetchers/posts/fetch-last-post-cursor.test.ts
new file mode 100644
index 0000000..4fe2f50
--- /dev/null
+++ b/src/services/graphql/fetchers/posts/fetch-last-post-cursor.test.ts
@@ -0,0 +1,25 @@
+import { afterEach, describe, expect, it } from '@jest/globals';
+import { fetchLastPostCursor } from './fetch-last-post-cursor';
+
+describe('fetch-last-post-cursor', () => {
+ afterEach(() => {
+ window.history.replaceState({}, '', '/');
+ });
+
+ it('returns the cursor of the last WordPress post using GraphQL', async () => {
+ const result = await fetchLastPostCursor(2);
+
+ expect.assertions(1);
+
+ expect(result).toBe('cursor2');
+ });
+
+ it('rejects with an error when no posts are found', async () => {
+ window.history.replaceState({}, '', '/?error=true');
+ expect.assertions(1);
+
+ await expect(async () => fetchLastPostCursor(1)).rejects.toEqual(
+ new Error('Unable to find the cursor of the last post.')
+ );
+ });
+});
diff --git a/src/services/graphql/fetchers/posts/fetch-last-post-cursor.ts b/src/services/graphql/fetchers/posts/fetch-last-post-cursor.ts
index d5ed174..161a50e 100644
--- a/src/services/graphql/fetchers/posts/fetch-last-post-cursor.ts
+++ b/src/services/graphql/fetchers/posts/fetch-last-post-cursor.ts
@@ -1,10 +1,8 @@
import type { GraphQLPageInfo, Nullable } from '../../../../types';
import { fetchGraphQL, getGraphQLUrl } from '../../../../utils/helpers';
-type LastPostCursorResponse = {
- posts: Nullable<{
- pageInfo: Pick<GraphQLPageInfo, 'endCursor'>;
- }>;
+export type LastPostCursorResponse = {
+ posts: Nullable<Record<'pageInfo', Pick<GraphQLPageInfo, 'endCursor'>>>;
};
const lastPostCursorQuery = `query LastPostCursor($first: Int) {
diff --git a/src/services/graphql/fetchers/posts/fetch-post.test.ts b/src/services/graphql/fetchers/posts/fetch-post.test.ts
new file mode 100644
index 0000000..e19e4de
--- /dev/null
+++ b/src/services/graphql/fetchers/posts/fetch-post.test.ts
@@ -0,0 +1,23 @@
+import { describe, expect, it } from '@jest/globals';
+import { wpPostsFixture } from '../../../../../tests/fixtures';
+import { fetchPost } from './fetch-post';
+
+describe('fetch-post', () => {
+ it('returns a post by slug', async () => {
+ const result = await fetchPost(wpPostsFixture[2].slug);
+
+ expect.assertions(1);
+
+ expect(result).toStrictEqual(wpPostsFixture[2]);
+ });
+
+ it('rejects with an error when the slug does not exist', async () => {
+ const slug = '/inexistent-slug';
+
+ expect.assertions(1);
+
+ await expect(async () => fetchPost(slug)).rejects.toEqual(
+ new Error(`No post found for the following slug ${slug}.`)
+ );
+ });
+});
diff --git a/src/services/graphql/fetchers/posts/fetch-post.ts b/src/services/graphql/fetchers/posts/fetch-post.ts
index 53c6bc3..bbd3912 100644
--- a/src/services/graphql/fetchers/posts/fetch-post.ts
+++ b/src/services/graphql/fetchers/posts/fetch-post.ts
@@ -1,7 +1,7 @@
import type { Nullable, WPPost } from '../../../../types';
import { fetchGraphQL, getGraphQLUrl } from '../../../../utils/helpers';
-type PostResponse = {
+export type PostResponse = {
post: Nullable<WPPost>;
};
diff --git a/src/services/graphql/fetchers/posts/fetch-posts-count.test.ts b/src/services/graphql/fetchers/posts/fetch-posts-count.test.ts
new file mode 100644
index 0000000..a0fd594
--- /dev/null
+++ b/src/services/graphql/fetchers/posts/fetch-posts-count.test.ts
@@ -0,0 +1,26 @@
+import { afterEach, describe, expect, it } from '@jest/globals';
+import { wpPostsFixture } from '../../../../../tests/fixtures';
+import { fetchPostsCount } from './fetch-posts-count';
+
+describe('fetch-posts-count', () => {
+ afterEach(() => {
+ window.history.replaceState({}, '', '/');
+ });
+
+ it('returns the WordPress posts count using GraphQL', async () => {
+ const result = await fetchPostsCount();
+
+ expect.assertions(1);
+
+ expect(result).toBe(wpPostsFixture.length);
+ });
+
+ it('rejects with an error when no posts are found', async () => {
+ window.history.replaceState({}, '', '/?error=true');
+ expect.assertions(1);
+
+ await expect(async () => fetchPostsCount()).rejects.toEqual(
+ new Error('Unable to find the total number of posts.')
+ );
+ });
+});
diff --git a/src/services/graphql/fetchers/posts/fetch-posts-count.ts b/src/services/graphql/fetchers/posts/fetch-posts-count.ts
index a72af52..316cd47 100644
--- a/src/services/graphql/fetchers/posts/fetch-posts-count.ts
+++ b/src/services/graphql/fetchers/posts/fetch-posts-count.ts
@@ -5,10 +5,8 @@ import type {
} from '../../../../types';
import { fetchGraphQL, getGraphQLUrl } from '../../../../utils/helpers';
-type PostsCountResponse = {
- posts: Nullable<{
- pageInfo: Pick<GraphQLPageInfo, 'total'>;
- }>;
+export type PostsCountResponse = {
+ posts: Nullable<Record<'pageInfo', Pick<GraphQLPageInfo, 'total'>>>;
};
const postsCountQuery = `query PostsCount($authorName: String, $search: String, $title: String) {
diff --git a/src/services/graphql/fetchers/posts/fetch-posts-list.test.ts b/src/services/graphql/fetchers/posts/fetch-posts-list.test.ts
new file mode 100644
index 0000000..1e21363
--- /dev/null
+++ b/src/services/graphql/fetchers/posts/fetch-posts-list.test.ts
@@ -0,0 +1,26 @@
+import { afterEach, describe, expect, it } from '@jest/globals';
+import { wpPostsFixture } from '../../../../../tests/fixtures';
+import { fetchPostsList } from './fetch-posts-list';
+
+describe('fetch-posts-list', () => {
+ afterEach(() => {
+ window.history.replaceState({}, '', '/');
+ });
+
+ it('returns the WordPress posts using GraphQL', async () => {
+ const result = await fetchPostsList({});
+
+ expect.assertions(1);
+
+ expect(result.pageInfo.total).toBe(wpPostsFixture.length);
+ });
+
+ it('rejects with an error when no posts are found', async () => {
+ window.history.replaceState({}, '', '/?error=true');
+ expect.assertions(1);
+
+ await expect(async () =>
+ fetchPostsList({ where: { authorName: 'inexistent-author' } })
+ ).rejects.toEqual(new Error('No posts found.'));
+ });
+});
diff --git a/src/services/graphql/fetchers/posts/fetch-posts-list.ts b/src/services/graphql/fetchers/posts/fetch-posts-list.ts
index 452892b..0bf6dc1 100644
--- a/src/services/graphql/fetchers/posts/fetch-posts-list.ts
+++ b/src/services/graphql/fetchers/posts/fetch-posts-list.ts
@@ -8,7 +8,7 @@ import type {
} from '../../../../types';
import { fetchGraphQL, getGraphQLUrl } from '../../../../utils/helpers';
-type PostsListResponse = {
+export type PostsListResponse = {
posts: Nullable<GraphQLConnection<WPPostPreview>>;
};
diff --git a/src/services/graphql/fetchers/posts/fetch-recent-posts.test.ts b/src/services/graphql/fetchers/posts/fetch-recent-posts.test.ts
new file mode 100644
index 0000000..2d2fcc8
--- /dev/null
+++ b/src/services/graphql/fetchers/posts/fetch-recent-posts.test.ts
@@ -0,0 +1,25 @@
+import { afterEach, describe, expect, it } from '@jest/globals';
+import { fetchRecentPosts } from './fetch-recent-posts';
+
+describe('fetch-recent-posts', () => {
+ afterEach(() => {
+ window.history.replaceState({}, '', '/');
+ });
+
+ it('returns the WordPress most recent posts using GraphQL', async () => {
+ const result = await fetchRecentPosts({ first: 2 });
+
+ expect.assertions(1);
+
+ expect(result.edges.length).toBe(2);
+ });
+
+ it('rejects with an error when no posts are found', async () => {
+ window.history.replaceState({}, '', '/?error=true');
+ expect.assertions(1);
+
+ await expect(async () =>
+ fetchRecentPosts({ where: { authorName: 'inexistent-author' } })
+ ).rejects.toEqual(new Error('No recent posts found.'));
+ });
+});
diff --git a/src/services/graphql/fetchers/posts/fetch-recent-posts.ts b/src/services/graphql/fetchers/posts/fetch-recent-posts.ts
index 12785d6..ddbea36 100644
--- a/src/services/graphql/fetchers/posts/fetch-recent-posts.ts
+++ b/src/services/graphql/fetchers/posts/fetch-recent-posts.ts
@@ -7,7 +7,7 @@ import type {
} from '../../../../types';
import { fetchGraphQL, getGraphQLUrl } from '../../../../utils/helpers';
-type RecentPostsResponse = {
+export type RecentPostsResponse = {
posts: Nullable<GraphQLConnection<RecentWPPost>>;
};
diff --git a/src/utils/hooks/use-posts-list/use-posts-list.test.ts b/src/utils/hooks/use-posts-list/use-posts-list.test.ts
deleted file mode 100644
index ff69de2..0000000
--- a/src/utils/hooks/use-posts-list/use-posts-list.test.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-import { describe, expect, it } from '@jest/globals';
-import { act, renderHook } from '@testing-library/react';
-import { fetchPostsList } from '../../../services/graphql';
-import { usePostsList } from './use-posts-list';
-
-describe('usePostsList', () => {
- it('can return the first new result index when loading more posts', async () => {
- const perPage = 5;
- const { result } = renderHook(() =>
- usePostsList({ fetcher: fetchPostsList, perPage })
- );
-
- expect.assertions(2);
-
- expect(result.current.firstNewResultIndex).toBeUndefined();
-
- await act(async () => {
- await result.current.loadMore();
- });
-
- // Assuming there is more than one page.
- expect(result.current.firstNewResultIndex).toBe(perPage + 1);
- });
-});
diff --git a/src/utils/hooks/use-posts-list/use-posts-list.test.tsx b/src/utils/hooks/use-posts-list/use-posts-list.test.tsx
new file mode 100644
index 0000000..f23ddde
--- /dev/null
+++ b/src/utils/hooks/use-posts-list/use-posts-list.test.tsx
@@ -0,0 +1,74 @@
+import {
+ afterEach,
+ beforeEach,
+ describe,
+ expect,
+ it,
+ jest,
+} from '@jest/globals';
+import { act, renderHook } from '@testing-library/react';
+import type { ReactNode } from 'react';
+import { SWRConfig } from 'swr';
+import { fetchPostsList } from '../../../services/graphql';
+import { usePostsList } from './use-posts-list';
+
+const wrapper = ({ children }: { children?: ReactNode }) => {
+ const map = new Map();
+
+ return (
+ <SWRConfig
+ value={{
+ provider: () => map,
+ isOnline() {
+ return true;
+ },
+ isVisible() {
+ return true;
+ },
+ initFocus() {
+ /* nothing */
+ },
+ initReconnect() {
+ /* nothing */
+ },
+ }}
+ >
+ {children}
+ </SWRConfig>
+ );
+};
+
+describe('usePostsList', () => {
+ beforeEach(() => {
+ /* Not sure why it is needed, but without it Jest was complaining with `You
+ * are trying to import a file after the Jest environment has been torn
+ * down`... Maybe because of useSWR? */
+ jest.useFakeTimers({
+ doNotFake: ['queueMicrotask'],
+ });
+ });
+
+ afterEach(() => {
+ jest.runOnlyPendingTimers();
+ jest.useRealTimers();
+ });
+
+ it('can return the first new result index when loading more posts', async () => {
+ const perPage = 5;
+ const { result } = renderHook(
+ () => usePostsList({ fetcher: fetchPostsList, perPage }),
+ { wrapper }
+ );
+
+ expect.assertions(2);
+
+ expect(result.current.firstNewResultIndex).toBeUndefined();
+
+ await act(async () => {
+ await result.current.loadMore();
+ });
+
+ // Assuming there is more than one page.
+ expect(result.current.firstNewResultIndex).toBe(perPage + 1);
+ });
+});
diff --git a/tests/fixtures/index.ts b/tests/fixtures/index.ts
new file mode 100644
index 0000000..c2e1c04
--- /dev/null
+++ b/tests/fixtures/index.ts
@@ -0,0 +1 @@
+export * from './wp-posts.fixture';
diff --git a/tests/fixtures/wp-posts.fixture.ts b/tests/fixtures/wp-posts.fixture.ts
new file mode 100644
index 0000000..a1b1e4a
--- /dev/null
+++ b/tests/fixtures/wp-posts.fixture.ts
@@ -0,0 +1,177 @@
+import type { WPPost } from '../../src/types';
+
+export const wpPostsFixture: WPPost[] = [
+ {
+ acfPosts: null,
+ author: {
+ node: {
+ name: 'Alisha.Dare45',
+ },
+ },
+ commentCount: 2,
+ contentParts: {
+ afterMore:
+ 'Velit rerum ea ex at esse sunt eum corporis. Autem sunt et. Earum consectetur alias enim officiis nesciunt.',
+ beforeMore:
+ 'Architecto quasi consequuntur. Ut sint perspiciatis dolor non iure et ut. Reiciendis id minus perferendis vero.',
+ },
+ databaseId: 1,
+ date: '2022-11-02',
+ featuredImage: null,
+ info: {
+ wordsCount: 400,
+ },
+ modified: '2022-11-02',
+ seo: {
+ metaDesc: 'Repudiandae autem numquam.',
+ title: 'similique atque corporis',
+ },
+ slug: '/post-1',
+ title: 'Post 1',
+ },
+ {
+ acfPosts: null,
+ author: {
+ node: {
+ name: 'Alisha.Dare45',
+ },
+ },
+ commentCount: null,
+ contentParts: {
+ afterMore:
+ 'Accusantium voluptatem ullam. Culpa et qui voluptatibus earum commodi expedita dolor. Aut suscipit corporis exercitationem tempora sapiente. Deleniti velit assumenda voluptatum et rem inventore soluta hic distinctio. Excepturi dolorum maxime voluptas. Ducimus et aut quia ex.',
+ beforeMore:
+ 'Et illo voluptates. Nihil sed error. Quas et similique incidunt quae in rem omnis. Odit distinctio magni et qui tempora pariatur eius perferendis.',
+ },
+ databaseId: 2,
+ date: '2022-11-03',
+ featuredImage: {
+ node: {
+ altText: null,
+ mediaDetails: {
+ height: 480,
+ width: 640,
+ },
+ sourceUrl: 'https://picsum.photos/640/480',
+ title: null,
+ },
+ },
+ info: {
+ wordsCount: 520,
+ },
+ modified: '2022-11-04',
+ seo: {
+ metaDesc: 'Veritatis deleniti et cum modi id necessitatibus dolores.',
+ title: 'numquam nihil voluptas',
+ },
+ slug: '/post-2',
+ title: 'Post 2',
+ },
+ {
+ acfPosts: {
+ postsInThematic: [
+ {
+ databaseId: 2,
+ slug: '/thematic-1',
+ title: 'Thematic 1',
+ },
+ ],
+ postsInTopic: null,
+ },
+ author: {
+ node: {
+ name: 'Alisha.Dare45',
+ },
+ },
+ commentCount: 1,
+ contentParts: {
+ afterMore:
+ 'Animi facere velit in voluptate facere non repellat magni. Aut est dicta et mollitia blanditiis dolores. Est minima voluptatibus eveniet.',
+ beforeMore:
+ 'Consequatur odit voluptatum est est accusantium. Nobis aspernatur qui. Magni ut facere laudantium voluptatem autem quia voluptas.',
+ },
+ databaseId: 3,
+ date: '2022-11-06',
+ featuredImage: {
+ node: {
+ altText: 'qui officia est',
+ mediaDetails: {
+ height: 480,
+ width: 640,
+ },
+ sourceUrl: 'https://picsum.photos/640/480',
+ title: null,
+ },
+ },
+ info: {
+ wordsCount: 320,
+ },
+ modified: '2022-11-06',
+ seo: {
+ metaDesc:
+ 'Ut deserunt qui reprehenderit ut veritatis consequatur quia corporis.',
+ title: 'laboriosam incidunt enim',
+ },
+ slug: '/post-3',
+ title: 'Post 3',
+ },
+ {
+ acfPosts: {
+ postsInThematic: [
+ {
+ databaseId: 3,
+ slug: '/thematic-2',
+ title: 'Thematic 2',
+ },
+ {
+ databaseId: 4,
+ slug: '/thematic-3',
+ title: 'Thematic 3',
+ },
+ ],
+ postsInTopic: [
+ {
+ databaseId: 2,
+ featuredImage: null,
+ slug: '/topic-1',
+ title: 'Topic 1',
+ },
+ ],
+ },
+ author: {
+ node: {
+ name: 'Alisha.Dare45',
+ },
+ },
+ commentCount: 5,
+ contentParts: {
+ afterMore:
+ 'Consequuntur inventore labore enim rerum ut. Ut et sit tempora provident. Aliquid nihil dolorem dolorum assumenda doloremque perspiciatis similique debitis voluptas.',
+ beforeMore:
+ 'Adipisci velit voluptatum unde consequatur amet. In aliquam animi qui non ut.',
+ },
+ databaseId: 4,
+ date: '2022-11-08',
+ featuredImage: {
+ node: {
+ altText: 'est dolorum maxime',
+ mediaDetails: {
+ height: 480,
+ width: 640,
+ },
+ sourceUrl: 'https://picsum.photos/640/480',
+ title: 'nostrum quisquam officiis',
+ },
+ },
+ info: {
+ wordsCount: 650,
+ },
+ modified: '2022-11-11',
+ seo: {
+ metaDesc: 'In ipsam pariatur laboriosam aut alias molestiae.',
+ title: 'fugit et sunt',
+ },
+ slug: '/post-4',
+ title: 'Post 4',
+ },
+];
diff --git a/tests/msw/handlers/index.ts b/tests/msw/handlers/index.ts
new file mode 100644
index 0000000..decbc9f
--- /dev/null
+++ b/tests/msw/handlers/index.ts
@@ -0,0 +1,3 @@
+import { postsHandlers } from './posts';
+
+export const handlers = [...postsHandlers];
diff --git a/tests/msw/handlers/posts/index.ts b/tests/msw/handlers/posts/index.ts
new file mode 100644
index 0000000..3a49e13
--- /dev/null
+++ b/tests/msw/handlers/posts/index.ts
@@ -0,0 +1,15 @@
+import { lastPostCursorHandler } from './last-post-cursor.handler';
+import { postHandler } from './post.handler';
+import { postsCountHandler } from './posts-count.handler';
+import { postsListHandler } from './posts-list.handler';
+import { postsSlugsHandler } from './posts-slugs.handler';
+import { recentPostsHandler } from './recent-posts.handler';
+
+export const postsHandlers = [
+ lastPostCursorHandler,
+ postHandler,
+ postsCountHandler,
+ postsListHandler,
+ postsSlugsHandler,
+ recentPostsHandler,
+];
diff --git a/tests/msw/handlers/posts/last-post-cursor.handler.ts b/tests/msw/handlers/posts/last-post-cursor.handler.ts
new file mode 100644
index 0000000..2f4b648
--- /dev/null
+++ b/tests/msw/handlers/posts/last-post-cursor.handler.ts
@@ -0,0 +1,33 @@
+import { type ExecutionResult, graphql as executeGraphql } from 'graphql';
+import { HttpResponse, graphql } from 'msw';
+import type { LastPostCursorResponse } from '../../../../src/services/graphql';
+import { wpPostsFixture } from '../../../fixtures';
+import { getConnection } from '../../../utils/graphql';
+import { schema } from '../../schema';
+
+export const lastPostCursorHandler = graphql.query<
+ LastPostCursorResponse,
+ Record<'first', number>
+>('LastPostCursor', async ({ query, variables }) => {
+ const pageParams = new URLSearchParams(window.location.search);
+ const isError = pageParams.get('error') === 'true';
+
+ if (isError) return HttpResponse.json({ data: { posts: null } });
+
+ const { data, errors } = (await executeGraphql({
+ schema,
+ source: query,
+ variableValues: variables,
+ rootValue: {
+ posts({ first }: typeof variables) {
+ return getConnection({
+ after: null,
+ data: wpPostsFixture,
+ first,
+ });
+ },
+ },
+ })) as ExecutionResult<LastPostCursorResponse>;
+
+ return HttpResponse.json({ data, errors });
+});
diff --git a/tests/msw/handlers/posts/post.handler.ts b/tests/msw/handlers/posts/post.handler.ts
new file mode 100644
index 0000000..4abdfed
--- /dev/null
+++ b/tests/msw/handlers/posts/post.handler.ts
@@ -0,0 +1,21 @@
+import { type ExecutionResult, graphql as executeGraphql } from 'graphql';
+import { HttpResponse, graphql } from 'msw';
+import type { PostResponse } from '../../../../src/services/graphql';
+import { wpPostsFixture } from '../../../fixtures';
+import { schema } from '../../schema';
+
+export const postHandler = graphql.query<PostResponse, Record<'slug', string>>(
+ 'Post',
+ async ({ query, variables }) => {
+ const { data, errors } = (await executeGraphql({
+ schema,
+ source: query,
+ variableValues: variables,
+ rootValue: {
+ post: wpPostsFixture.find((wpPost) => wpPost.slug === variables.slug),
+ },
+ })) as ExecutionResult<PostResponse>;
+
+ return HttpResponse.json({ data, errors });
+ }
+);
diff --git a/tests/msw/handlers/posts/posts-count.handler.ts b/tests/msw/handlers/posts/posts-count.handler.ts
new file mode 100644
index 0000000..95fa105
--- /dev/null
+++ b/tests/msw/handlers/posts/posts-count.handler.ts
@@ -0,0 +1,51 @@
+import { type ExecutionResult, graphql as executeGraphql } from 'graphql';
+import { HttpResponse, graphql } from 'msw';
+import type { PostsCountResponse } from '../../../../src/services/graphql';
+import type { GraphQLPostWhere } from '../../../../src/types';
+import { wpPostsFixture } from '../../../fixtures';
+import { getConnection } from '../../../utils/graphql';
+import { schema } from '../../schema';
+
+export const postsCountHandler = graphql.query<
+ PostsCountResponse,
+ GraphQLPostWhere
+>('PostsCount', async ({ query, variables }) => {
+ const pageParams = new URLSearchParams(window.location.search);
+ const isError = pageParams.get('error') === 'true';
+
+ if (isError) return HttpResponse.json({ data: { posts: null } });
+
+ const { data, errors } = (await executeGraphql({
+ schema,
+ source: query,
+ variableValues: variables,
+ rootValue: {
+ posts({ authorName, search, title }: typeof variables) {
+ const filteredPostsByAuthor = authorName
+ ? wpPostsFixture.filter((post) =>
+ post.author.node.name.includes(authorName)
+ )
+ : wpPostsFixture;
+ const filteredPostsByTitle = title
+ ? filteredPostsByAuthor.filter((post) => post.title.includes(title))
+ : filteredPostsByAuthor;
+ const filteredPosts = search
+ ? filteredPostsByTitle.filter(
+ (post) =>
+ post.title.includes(search) ||
+ post.contentParts.afterMore.includes(search) ||
+ post.contentParts.beforeMore.includes(search)
+ )
+ : filteredPostsByTitle;
+
+ return getConnection({
+ after: null,
+ data: filteredPosts,
+ first: undefined,
+ });
+ },
+ },
+ })) as ExecutionResult<PostsCountResponse>;
+
+ return HttpResponse.json({ data, errors });
+});
diff --git a/tests/msw/handlers/posts/posts-list.handler.ts b/tests/msw/handlers/posts/posts-list.handler.ts
new file mode 100644
index 0000000..7f8daf6
--- /dev/null
+++ b/tests/msw/handlers/posts/posts-list.handler.ts
@@ -0,0 +1,50 @@
+import { type ExecutionResult, graphql as executeGraphql } from 'graphql';
+import { HttpResponse, graphql } from 'msw';
+import type {
+ FetchPostsListInput,
+ PostsListResponse,
+} from '../../../../src/services/graphql';
+import { wpPostsFixture } from '../../../fixtures';
+import { getConnection } from '../../../utils/graphql';
+import { schema } from '../../schema';
+
+export const postsListHandler = graphql.query<
+ PostsListResponse,
+ FetchPostsListInput
+>('PostsList', async ({ query, variables }) => {
+ const pageParams = new URLSearchParams(window.location.search);
+ const isError = pageParams.get('error') === 'true';
+
+ if (isError) return HttpResponse.json({ data: { posts: null } });
+
+ const { data, errors } = (await executeGraphql({
+ schema,
+ source: query,
+ variableValues: variables,
+ rootValue: {
+ posts({ after, first, where }: typeof variables) {
+ const { authorName, search, title } = where ?? {};
+ const filteredPostsByAuthor = authorName
+ ? wpPostsFixture.filter((post) =>
+ post.author.node.name.includes(authorName)
+ )
+ : wpPostsFixture;
+ const filteredPostsByTitle = title
+ ? filteredPostsByAuthor.filter((post) => post.title.includes(title))
+ : filteredPostsByAuthor;
+ const filteredPosts = search
+ ? filteredPostsByTitle.filter(
+ (post) =>
+ post.title.includes(search) ||
+ post.contentParts.afterMore.includes(search) ||
+ post.contentParts.beforeMore.includes(search)
+ )
+ : filteredPostsByTitle;
+
+ return getConnection({ after, data: filteredPosts, first });
+ },
+ },
+ })) as ExecutionResult<PostsListResponse>;
+
+ return HttpResponse.json({ data, errors });
+});
diff --git a/tests/msw/handlers/posts/posts-slugs.handler.ts b/tests/msw/handlers/posts/posts-slugs.handler.ts
new file mode 100644
index 0000000..9aadddb
--- /dev/null
+++ b/tests/msw/handlers/posts/posts-slugs.handler.ts
@@ -0,0 +1,26 @@
+import { type ExecutionResult, graphql as executeGraphql } from 'graphql';
+import { HttpResponse, graphql } from 'msw';
+import type { PostsSlugsResponse } from '../../../../src/services/graphql';
+import { wpPostsFixture } from '../../../fixtures';
+import { schema } from '../../schema';
+
+export const postsSlugsHandler = graphql.query<
+ PostsSlugsResponse,
+ Record<'first', number>
+>('PostsSlugs', async ({ query, variables }) => {
+ const pageParams = new URLSearchParams(window.location.search);
+ const isError = pageParams.get('error') === 'true';
+
+ if (isError) return HttpResponse.json({ data: { posts: null } });
+
+ const { data, errors } = (await executeGraphql({
+ schema,
+ source: query,
+ variableValues: variables,
+ rootValue: {
+ posts: { nodes: wpPostsFixture },
+ },
+ })) as ExecutionResult<PostsSlugsResponse>;
+
+ return HttpResponse.json({ data, errors });
+});
diff --git a/tests/msw/handlers/posts/recent-posts.handler.ts b/tests/msw/handlers/posts/recent-posts.handler.ts
new file mode 100644
index 0000000..34e0efb
--- /dev/null
+++ b/tests/msw/handlers/posts/recent-posts.handler.ts
@@ -0,0 +1,50 @@
+import { type ExecutionResult, graphql as executeGraphql } from 'graphql';
+import { HttpResponse, graphql } from 'msw';
+import type {
+ FetchPostsListInput,
+ RecentPostsResponse,
+} from '../../../../src/services/graphql';
+import { wpPostsFixture } from '../../../fixtures';
+import { getConnection } from '../../../utils/graphql';
+import { schema } from '../../schema';
+
+export const recentPostsHandler = graphql.query<
+ RecentPostsResponse,
+ FetchPostsListInput
+>('RecentPosts', async ({ query, variables }) => {
+ const pageParams = new URLSearchParams(window.location.search);
+ const isError = pageParams.get('error') === 'true';
+
+ if (isError) return HttpResponse.json({ data: { posts: null } });
+
+ const { data, errors } = (await executeGraphql({
+ schema,
+ source: query,
+ variableValues: variables,
+ rootValue: {
+ posts({ after, first, where }: typeof variables) {
+ const { authorName, search, title } = where ?? {};
+ const filteredPostsByAuthor = authorName
+ ? wpPostsFixture.filter((post) =>
+ post.author.node.name.includes(authorName)
+ )
+ : wpPostsFixture;
+ const filteredPostsByTitle = title
+ ? filteredPostsByAuthor.filter((post) => post.title.includes(title))
+ : filteredPostsByAuthor;
+ const filteredPosts = search
+ ? filteredPostsByTitle.filter(
+ (post) =>
+ post.title.includes(search) ||
+ post.contentParts.afterMore.includes(search) ||
+ post.contentParts.beforeMore.includes(search)
+ )
+ : filteredPostsByTitle;
+
+ return getConnection({ after, data: filteredPosts, first });
+ },
+ },
+ })) as ExecutionResult<RecentPostsResponse>;
+
+ return HttpResponse.json({ data, errors });
+});
diff --git a/tests/msw/index.ts b/tests/msw/index.ts
index 997ae40..29504a4 100644
--- a/tests/msw/index.ts
+++ b/tests/msw/index.ts
@@ -1,3 +1,4 @@
import { setupServer } from 'msw/node';
+import { handlers } from './handlers';
-export const mswServer = setupServer(...[]);
+export const mswServer = setupServer(...handlers);
diff --git a/tests/msw/schema/types/index.ts b/tests/msw/schema/types/index.ts
index ea749be..163955b 100644
--- a/tests/msw/schema/types/index.ts
+++ b/tests/msw/schema/types/index.ts
@@ -6,6 +6,11 @@ import { thematicTypes } from './thematic.types';
import { topicTypes } from './topic.types';
const rootQueryType = `type Query {
+ post(
+ asPreview: Boolean
+ id: ID!
+ idType: PostIdType
+ ): Post
posts(
after: String
before: String
diff --git a/tests/msw/schema/types/post.types.ts b/tests/msw/schema/types/post.types.ts
index 04c4f37..11c514c 100644
--- a/tests/msw/schema/types/post.types.ts
+++ b/tests/msw/schema/types/post.types.ts
@@ -22,6 +22,13 @@ type Post {
title(format: PostObjectFieldFormatEnum): String
}
+enum PostIdType {
+ DATABASE_ID
+ ID
+ SLUG
+ URI
+}
+
enum PostStatusEnum {
ACF_DISABLED
AUTO_DRAFT
@@ -66,6 +73,7 @@ type RootQueryToPostConnectionPageInfo {
type RootQueryToPostConnection {
edges: [RootQueryToPostConnectionEdge!]!
+ nodes: [Post!]!
pageInfo: RootQueryToPostConnectionPageInfo!
}`;