mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-12-14 17:02:49 +03:00
console: add hook useOperationsFromQueryCollection
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/5606 GitOrigin-RevId: eab15cb6aa928c9a471100252b85a4ce85e25e05
This commit is contained in:
parent
a35bd278ad
commit
4ad498cd22
@ -263,4 +263,12 @@ export namespace MetadataSelector {
|
||||
|
||||
export const getAllDriversList = (m: MetadataResponse) =>
|
||||
m.metadata?.sources.map(s => ({ source: s.name, kind: s.kind }));
|
||||
|
||||
export const getOperationsFromQueryCollection =
|
||||
(queryCollectionName: string) => (m: MetadataResponse) => {
|
||||
const queryCollectionDefinition = m.metadata?.query_collections?.find(
|
||||
qs => qs.name === queryCollectionName
|
||||
);
|
||||
return queryCollectionDefinition?.definition?.queries ?? [];
|
||||
};
|
||||
}
|
||||
|
@ -0,0 +1 @@
|
||||
export * from './useOperationsFromQueryCollection';
|
@ -0,0 +1,10 @@
|
||||
import { rest } from 'msw';
|
||||
import { metadata } from './metadata';
|
||||
|
||||
const baseUrl = 'http://localhost:8080';
|
||||
|
||||
export const handlers = (url = baseUrl) => [
|
||||
rest.post(`${url}/v1/metadata`, (req, res, ctx) => {
|
||||
return res(ctx.json(metadata));
|
||||
}),
|
||||
];
|
@ -0,0 +1,42 @@
|
||||
import { MetadataResponse } from '@/features/MetadataAPI';
|
||||
|
||||
export const metadata: MetadataResponse = {
|
||||
resource_version: 48,
|
||||
metadata: {
|
||||
version: 3,
|
||||
sources: [],
|
||||
remote_schemas: [],
|
||||
inherited_roles: [],
|
||||
query_collections: [
|
||||
{
|
||||
name: 'allowed-queries',
|
||||
definition: {
|
||||
queries: [
|
||||
{
|
||||
name: 'MyQuery',
|
||||
query: 'query MyQuery {\n user {\n id\n }\n}\n',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
allowlist: [
|
||||
{
|
||||
collection: 'allowed-queries',
|
||||
scope: {
|
||||
global: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
export const metadata_with_no_query_collections: MetadataResponse = {
|
||||
resource_version: 48,
|
||||
metadata: {
|
||||
version: 3,
|
||||
sources: [],
|
||||
remote_schemas: [],
|
||||
inherited_roles: [],
|
||||
},
|
||||
};
|
@ -0,0 +1,41 @@
|
||||
import { ReactQueryDecorator } from '@/storybook/decorators/react-query';
|
||||
import { ReduxDecorator } from '@/storybook/decorators/redux-decorator';
|
||||
import ReactJson from 'react-json-view';
|
||||
import { Meta, Story } from '@storybook/react';
|
||||
import React from 'react';
|
||||
|
||||
import { useOperationsFromQueryCollection } from './useOperationsFromQueryCollection';
|
||||
import { handlers } from './mocks/handlers.mock';
|
||||
|
||||
function UseOperationsFromQueryCollection() {
|
||||
const operations = useOperationsFromQueryCollection('allowed-queries');
|
||||
|
||||
const error = operations.error;
|
||||
|
||||
return (
|
||||
<div>
|
||||
{operations.isSuccess ? (
|
||||
<ReactJson collapsed src={operations.data} />
|
||||
) : (
|
||||
'no response'
|
||||
)}
|
||||
|
||||
{error ? <ReactJson src={error} /> : null}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export const Primary: Story = () => {
|
||||
return <UseOperationsFromQueryCollection />;
|
||||
};
|
||||
|
||||
export default {
|
||||
title: 'hooks/useOperationsFromQueryCollection',
|
||||
decorators: [
|
||||
ReduxDecorator({ tables: { currentDataSource: 'default' } }),
|
||||
ReactQueryDecorator(),
|
||||
],
|
||||
parameters: {
|
||||
msw: handlers(),
|
||||
},
|
||||
} as Meta;
|
@ -0,0 +1,59 @@
|
||||
import { setupServer } from 'msw/node';
|
||||
import { rest } from 'msw';
|
||||
import { renderHook } from '@testing-library/react-hooks';
|
||||
import { metadata, metadata_with_no_query_collections } from './mocks/metadata';
|
||||
import { useOperationsFromQueryCollection } from './useOperationsFromQueryCollection';
|
||||
import { wrapper } from '../../../../hooks/__tests__/common/decorator';
|
||||
|
||||
const server = setupServer();
|
||||
|
||||
beforeAll(() => server.listen());
|
||||
afterAll(() => server.close());
|
||||
|
||||
describe('useOperationsFromQueryCollection with valid data', () => {
|
||||
beforeEach(() => {
|
||||
server.use(
|
||||
rest.post('/v1/metadata', (req, res, ctx) =>
|
||||
res(ctx.status(200), ctx.json(metadata))
|
||||
)
|
||||
);
|
||||
});
|
||||
test('When useOperationsFromQueryCollection hook is called with query collection Name, then a valid list of operations are returned', async () => {
|
||||
const { result, waitForValueToChange } = renderHook(
|
||||
() => useOperationsFromQueryCollection('allowed-queries'),
|
||||
{ wrapper }
|
||||
);
|
||||
|
||||
await waitForValueToChange(() => result.current.isSuccess);
|
||||
|
||||
const operations = result.current.data!;
|
||||
|
||||
expect(operations).toHaveLength(1);
|
||||
expect(operations[0].name).toEqual('MyQuery');
|
||||
expect(operations[0].query).toEqual(
|
||||
'query MyQuery {\n user {\n id\n }\n}\n'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('useOperationsFromQueryCollection with no query collections', () => {
|
||||
beforeEach(() => {
|
||||
server.use(
|
||||
rest.post('/v1/metadata', (req, res, ctx) =>
|
||||
res(ctx.status(200), ctx.json(metadata_with_no_query_collections))
|
||||
)
|
||||
);
|
||||
});
|
||||
test('When useOperationsFromQueryCollection is called with an invalid query collection, then empty array should be returned', async () => {
|
||||
const { result, waitForValueToChange } = renderHook(
|
||||
() => useOperationsFromQueryCollection('allowed-queries'),
|
||||
{ wrapper }
|
||||
);
|
||||
|
||||
await waitForValueToChange(() => result.current.isSuccess);
|
||||
|
||||
const operations = result.current.data!;
|
||||
|
||||
expect(operations).toHaveLength(0);
|
||||
});
|
||||
});
|
@ -0,0 +1,6 @@
|
||||
import { MetadataSelector, useMetadata } from '@/features/MetadataAPI';
|
||||
|
||||
export const useOperationsFromQueryCollection = (queryCollectionName: string) =>
|
||||
useMetadata(
|
||||
MetadataSelector.getOperationsFromQueryCollection(queryCollectionName)
|
||||
);
|
@ -742,9 +742,17 @@ export interface QueryCollection {
|
||||
/**
|
||||
* https://hasura.io/docs/latest/graphql/core/api-reference/schema-metadata-api/query-collections.html#add-collection-to-allowlist-syntax
|
||||
*/
|
||||
|
||||
type AllowListScope =
|
||||
| {
|
||||
global: false;
|
||||
roles: string[];
|
||||
}
|
||||
| { global: true };
|
||||
export interface AllowList {
|
||||
/** Name of a query collection to be added to the allow-list */
|
||||
collection: CollectionName;
|
||||
scope?: AllowListScope;
|
||||
}
|
||||
|
||||
// //////////////////////////////
|
||||
|
Loading…
Reference in New Issue
Block a user