-
Notifications
You must be signed in to change notification settings - Fork 89
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: new graphql method on the client, wrapping graphql calls for th…
…e gapi endpoint
- Loading branch information
Showing
11 changed files
with
302 additions
and
87 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
import { beforeAll, beforeEach, describe, expect, it, vi } from 'vitest'; | ||
import createFetchMock from 'vitest-fetch-mock'; | ||
|
||
describe('test graphql wrapper', () => { | ||
const query = ` | ||
query { | ||
PageItem(id: "home") { | ||
name | ||
content { | ||
_uid | ||
component | ||
} | ||
} | ||
} | ||
`; | ||
|
||
const accessToken = 'test-access-token'; | ||
const version = 'draft'; | ||
const variables = { id: '123' }; | ||
|
||
beforeAll(() => { | ||
const fetchMocker = createFetchMock(vi); | ||
// sets globalThis.fetch and globalThis.fetchMock to our mocked version | ||
fetchMocker.enableMocks(); | ||
}); | ||
|
||
beforeEach(() => { | ||
fetch.resetMocks(); | ||
}); | ||
|
||
it('should return data when the request is successful', async () => { | ||
fetch.mockResponseOnce(JSON.stringify({ data: { test: 'test' } })); | ||
|
||
const { graph } = await import('./graphql-wrapper'); | ||
const response = await graph(query, accessToken, version, variables); | ||
|
||
expect(response).toEqual({ data: { test: 'test' } }); | ||
}); | ||
|
||
it('should throw an error when the request fails', async () => { | ||
fetch.mockRejectOnce(new Error('test error')); | ||
|
||
const { graph } = await import('./graphql-wrapper'); | ||
|
||
try { | ||
await graph(query, accessToken, version, variables); | ||
} | ||
catch (error) { | ||
expect(error.message).toBe('GraphQL request failed: test error'); | ||
} | ||
}); | ||
|
||
it('should throw an error when the response status is not ok', async () => { | ||
fetch.mockResponseOnce(JSON.stringify({ data: { test: 'test' } }), { status: 401 }); | ||
|
||
const { graph } = await import('./graphql-wrapper'); | ||
|
||
try { | ||
await graph(query, accessToken, version, variables); | ||
} | ||
catch (error) { | ||
expect(error.message).toBe('GraphQL request failed with status 401'); | ||
} | ||
}); | ||
|
||
it('should throw an error when the response is not JSON', async () => { | ||
fetch.mockResponseOnce('not json', { status: 200 }); | ||
|
||
const { graph } = await import('./graphql-wrapper'); | ||
|
||
try { | ||
await graph(query, accessToken, version, variables); | ||
} | ||
catch (error) { | ||
expect(error.message).toContain('Unexpected token'); | ||
} | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import { STORYBLOK_GRAPQL_API } from './constants'; | ||
|
||
/** | ||
* Wrapper for Storyblok GraphQL API | ||
* | ||
* @param query string | ||
* @param accessToken string | ||
* @param version 'draft' | 'published' | ||
* @param variables Record<string, unknown> | ||
* @returns Promise<{ data: object }> | ||
* | ||
* @throws Error | ||
*/ | ||
export async function graph( | ||
query: string, | ||
accessToken: string, | ||
version: 'draft' | 'published' = 'draft', | ||
variables?: Record<string, unknown>, | ||
): Promise<{ data: object }> { | ||
let response; | ||
try { | ||
response = await fetch(STORYBLOK_GRAPQL_API, { | ||
method: 'POST', | ||
headers: { | ||
'Content-Type': 'application/json', | ||
'token': accessToken, | ||
'version': version, | ||
}, | ||
body: JSON.stringify({ query, variables }), | ||
}); | ||
} | ||
catch (error) { | ||
throw new Error(`GraphQL request failed: ${error instanceof Error ? error.message : 'Unknown error'}`); | ||
} | ||
|
||
if (!response.ok) { | ||
throw new Error(`GraphQL request failed with status ${response.status}`); | ||
} | ||
|
||
return response.json(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
import type { | ||
CachedVersions, | ||
ComponentResolverFn, | ||
ISbContentMangmntAPI, | ||
ISbCustomFetch, | ||
ISbResponseData, | ||
ISbResult, | ||
ISbStories, | ||
ISbStoriesParams, | ||
ISbStory, | ||
ISbStoryParams, | ||
LinksType, | ||
RelationsType, | ||
RichTextResolver, | ||
} from './interfaces'; | ||
|
||
export interface IStoryblok { | ||
relations: RelationsType; | ||
links: LinksType; | ||
richTextResolver: RichTextResolver; | ||
resolveNestedRelations: boolean; | ||
|
||
// Sets the component resolver for rich text | ||
setComponentResolver: (resolver: ComponentResolverFn) => void; | ||
|
||
// Fetches a single story by slug | ||
get: (slug: string, params?: ISbStoriesParams, fetchOptions?: ISbCustomFetch) => Promise<ISbResult>; | ||
|
||
// Fetches all stories matching the given parameters | ||
getAll: (slug: string, params: ISbStoriesParams, entity?: string, fetchOptions?: ISbCustomFetch) => Promise<any[]>; | ||
|
||
// Creates a new story | ||
post: (slug: string, params: ISbStoriesParams | ISbContentMangmntAPI, fetchOptions?: ISbCustomFetch) => Promise<ISbResponseData>; | ||
|
||
// Updates an existing story | ||
put: (slug: string, params: ISbStoriesParams | ISbContentMangmntAPI, fetchOptions?: ISbCustomFetch) => Promise<ISbResponseData>; | ||
|
||
// Deletes a story | ||
delete: (slug: string, params: ISbStoriesParams | ISbContentMangmntAPI, fetchOptions?: ISbCustomFetch) => Promise<ISbResponseData>; | ||
|
||
// Fetches multiple stories | ||
getStories: (params: ISbStoriesParams, fetchOptions?: ISbCustomFetch) => Promise<ISbStories>; | ||
|
||
// Fetches a single story by slug | ||
getStory: (slug: string, params: ISbStoryParams, fetchOptions?: ISbCustomFetch) => Promise<ISbStory>; | ||
|
||
// Wrapper for GraphQL queries | ||
graphql: (query: string, version: 'draft' | 'published', variables?: Record<string, unknown>) => Promise<{ data: object }>; | ||
|
||
// Ejects the interceptor from the fetch client | ||
ejectInterceptor: () => void; | ||
|
||
// Flushes all caches | ||
flushCache: () => Promise<this>; | ||
|
||
// Returns all cached versions (cv) | ||
cacheVersions: () => CachedVersions; | ||
|
||
// Returns the current cache version (cv) | ||
cacheVersion: () => number; | ||
|
||
// Sets the cache version (cv) | ||
setCacheVersion: (cv: number) => void; | ||
|
||
// Clears the cache version | ||
clearCacheVersion: () => void; | ||
} |
Oops, something went wrong.