1
import { useEnv } from '@directus/env';
2
import type { Request } from 'express';
3
import { afterEach, beforeAll, beforeEach, describe, expect, test, vi, type MockInstance } from 'vitest';
4
import { getCacheKey } from './get-cache-key.js';
5
import * as getGraphqlQueryUtil from './get-graphql-query-and-variables.js';
7
vi.mock('directus/version', () => ({ version: '1.2.3' }));
9
vi.mock('@directus/env');
11
const baseUrl = 'http://localhost';
12
const restUrl = `${baseUrl}/items/example`;
13
const graphQlUrl = `${baseUrl}/graphql`;
14
const accountability = { user: '00000000-0000-0000-0000-000000000000' };
19
name: 'as unauthenticated request',
20
params: { method, originalUrl: restUrl },
21
key: '20ada3d7cc37fb7e742d2a723f6f1d7a64686d2e',
24
name: 'as authenticated request',
25
params: { method, originalUrl: restUrl, accountability },
26
key: '79daba5bf38b6b80cb4bf4e2de95d6a8380f7927',
29
name: 'a request with a fields query',
30
params: { method, originalUrl: restUrl, sanitizedQuery: { fields: ['id', 'name'] } },
31
key: 'e1839f7379b39188622e797fdbe2e3e6d477cbdc',
34
name: 'a request with a filter query',
35
params: { method, originalUrl: restUrl, sanitizedQuery: { filter: { name: { _eq: 'test' } } } },
36
key: '0bcc9af5f628db85043133e59226b2de154d7183',
39
name: 'a GraphQL GET query request',
40
params: { method, originalUrl: graphQlUrl, query: { query: 'query { test { id } }' } },
41
key: '14bc276cf21e2d22334b84841533e2c8e1bba9bd',
44
name: 'a GraphQL POST query request',
45
params: { method: 'POST', originalUrl: graphQlUrl, body: { query: 'query { test { name } }' } },
46
key: 'c5bf03e138e0f7bbaa50dde9cad554bef47a81d2',
49
name: 'an authenticated GraphQL GET query request',
50
params: { method, originalUrl: graphQlUrl, accountability, query: { query: 'query { test { id } }' } },
51
key: '981f27be4c0cfed0b4eca6ac2514f6629aea6be1',
54
name: 'an authenticated GraphQL POST query request',
55
params: { method: 'POST', originalUrl: graphQlUrl, accountability, body: { query: 'query { test { name } }' } },
56
key: '358336a2c61f7ea2b41b5c1566bbebe692be601d',
60
const cases = requests.map(({ name, params, key }) => [name, params, key]);
63
vi.mocked(useEnv).mockReturnValue({});
70
describe('get cache key', () => {
71
describe('isGraphQl', () => {
72
let getGraphqlQuerySpy: MockInstance;
75
getGraphqlQuerySpy = vi.spyOn(getGraphqlQueryUtil, 'getGraphqlQueryAndVariables');
78
test.each(['/items/test', '/items/graphql', '/collections/test', '/collections/graphql'])(
79
'path "%s" should not be interpreted as a graphql query',
81
getCacheKey({ originalUrl: `${baseUrl}${path}` } as Request);
82
expect(getGraphqlQuerySpy).not.toHaveBeenCalled();
86
test.each(['/graphql', '/graphql/system'])('path "%s" should be interpreted as a graphql query', (path) => {
87
getCacheKey({ originalUrl: `${baseUrl}${path}` } as Request);
88
expect(getGraphqlQuerySpy).toHaveBeenCalledOnce();
92
test.each(cases)('should create a cache key for %s', (_, params, key) => {
93
expect(getCacheKey(params as unknown as Request)).toEqual(key);
96
test('should create a unique key for each request', () => {
97
const keys = cases.map(([, params]) => getCacheKey(params as unknown as Request));
98
const hasDuplicate = keys.some((key) => keys.indexOf(key) !== keys.lastIndexOf(key));
100
expect(hasDuplicate).toBeFalsy();
103
test('should create a unique key for GraphQL requests with different variables', () => {
104
const query = 'query Test ($name: String) { test (filter: { name: { _eq: $name } }) { id } }';
105
const operationName = 'test';
106
const variables1 = JSON.stringify({ name: 'test 1' });
107
const variables2 = JSON.stringify({ name: 'test 2' });
108
const req1: any = { method, originalUrl: graphQlUrl, query: { query, operationName, variables: variables1 } };
109
const req2: any = { method, originalUrl: graphQlUrl, query: { query, operationName, variables: variables2 } };
110
const postReq1: any = { method: 'POST', originalUrl: req1.originalUrl, body: req1.query };
111
const postReq2: any = { method: 'POST', originalUrl: req2.originalUrl, body: req2.query };
113
expect(getCacheKey(req1)).not.toEqual(getCacheKey(req2));
114
expect(getCacheKey(postReq1)).not.toEqual(getCacheKey(postReq2));
115
expect(getCacheKey(req1)).toEqual(getCacheKey(postReq1));
116
expect(getCacheKey(req2)).toEqual(getCacheKey(postReq2));