diff --git a/CHANGELOG.md b/CHANGELOG.md index c12593b1a33..f03ddc14ffe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ - server: `introspect_remote_schema` API now returns original remote schema instead of customized schema - server: prevent empty subscription roots in the schema (#6898) - console: support tracking of functions with return a single row +- console: add GraphQL customisation under Remote schema edit tab ## v2.0.9 diff --git a/console/cypress/integration/remote-schemas/edit-schema/spec.ts b/console/cypress/integration/remote-schemas/edit-schema/spec.ts new file mode 100644 index 00000000000..146cc56384e --- /dev/null +++ b/console/cypress/integration/remote-schemas/edit-schema/spec.ts @@ -0,0 +1,105 @@ +import { getElementFromAlias } from '../../../helpers/eventHelpers'; + +type CustomizationSettingsType = { + root_fields_namespace: string; + type_names: { + prefix: string; + suffix: string; + mapping: Record; + }; + field_names: { + parent_type: string; + prefix: string; + suffix: string; + mapping: Record; + }[]; +}; +export const modifyCustomization = ( + customizationSettings: CustomizationSettingsType | undefined +) => { + cy.get(getElementFromAlias('remote-schema-edit-modify-btn')) + .should('exist') + .click(); + cy.get(getElementFromAlias('remote-schema-customization-editor-expand-btn')) + .should('exist') + .click(); + + // add root field name + cy.get(getElementFromAlias('remote-schema-customization-root-field-input')) + .clear() + .type(customizationSettings?.root_fields_namespace || ''); + + cy.get( + getElementFromAlias('remote-schema-customization-type-name-prefix-input') + ) + .clear() + .type(customizationSettings?.type_names.prefix || ''); + + cy.get( + getElementFromAlias('remote-schema-customization-type-name-suffix-input') + ) + .clear() + .type(customizationSettings?.type_names.suffix || ''); + + // add type name + let key = Object.keys(customizationSettings?.type_names?.mapping || {})[0]; + cy.get( + getElementFromAlias('remote-schema-customization-type-name-lhs-input') + ).select(key); + cy.get( + getElementFromAlias('remote-schema-customization-type-name-0-rhs-input') + ) + .clear() + .type(customizationSettings?.type_names?.mapping[key] || ''); + + cy.get(getElementFromAlias('remote-schema-editor')).should('exist').click(); + + cy.get(getElementFromAlias('remote-schema-customization-open-field-mapping')) + .should('exist') + .click(); + + // click the field mapping button + cy.get( + getElementFromAlias( + 'remote-schema-customization-field-type-parent-type-input' + ) + ).select(customizationSettings?.field_names[0].parent_type || ''); + + cy.get( + getElementFromAlias( + 'remote-schema-customization-field-type-field-prefix-input' + ) + ) + .clear() + .type(customizationSettings?.field_names[0].prefix || ''); + + cy.get( + getElementFromAlias( + 'remote-schema-customization-field-type-field-suffix-input' + ) + ) + .clear() + .type(customizationSettings?.field_names[0].suffix || ''); + + // remote-schema-customization-field-type-lhs-input + key = Object.keys(customizationSettings?.field_names[0].mapping || {})[0]; + cy.get( + getElementFromAlias('remote-schema-customization-field-type-lhs-input') + ).select(key); + // remote-schema-customization-field-type-rhs-input + cy.get( + getElementFromAlias('remote-schema-customization-field-type-0-rhs-input') + ) + .clear() + .type(customizationSettings?.field_names[0].mapping[key] || ''); + + cy.get(getElementFromAlias('remote-schema-editor')).should('exist').click(); + + cy.get(getElementFromAlias('add-field-customization')) + .should('exist') + .click(); + + cy.get(getElementFromAlias('remote-schema-edit-save-btn')) + .should('exist') + .click(); +}; diff --git a/console/cypress/integration/remote-schemas/edit-schema/test.ts b/console/cypress/integration/remote-schemas/edit-schema/test.ts new file mode 100644 index 00000000000..e3d7c288b44 --- /dev/null +++ b/console/cypress/integration/remote-schemas/edit-schema/test.ts @@ -0,0 +1,107 @@ +/* eslint no-unused-vars: 0 */ +/* eslint import/prefer-default-export: 0 */ +import { testMode } from '../../../helpers/common'; +import { expectNotif } from '../../data/manage-database/common.spec'; +import { setMetaData } from '../../validators/validators'; +import { modifyCustomization } from './spec'; + +// const visitRoute = () => { +// describe('Setup route', () => { +// it('Visit the index route', () => { +// // Visit the index route +// cy.visit('/remote-schemas/manage/schemas'); +// // Get and set validation metadata +// setMetaData(); +// }); +// }); +// }; + +const createRemoteSchema = (remoteSchemaName: string) => { + const postBody = { + type: 'add_remote_schema', + args: { + name: remoteSchemaName, + definition: { + url: 'https://graphql-pokemon2.vercel.app', + forward_client_headers: true, + timeout_seconds: 60, + }, + }, + }; + cy.request('POST', 'http://localhost:8080/v1/metadata', postBody).then( + response => { + expect(response.body).to.have.property('message', 'success'); // true + } + ); +}; + +const removeRemoteSchema = (remoteSchemaName: string) => { + const postBody = { + type: 'remove_remote_schema', + args: { + name: remoteSchemaName, + }, + }; + cy.request('POST', 'http://localhost:8080/v1/metadata', postBody).then( + response => { + expect(response.body).to.have.property('message', 'success'); // true + } + ); +}; + +const editSchemaTests = () => { + describe('Modify an existing remote schema', () => { + describe('Create a remote schema for testing', () => { + it('add a remote schema via the API', () => { + createRemoteSchema('test_remote_schema'); + }); + }); + + describe('Edit the remote schema settings', () => { + it('Visit the modify page', () => { + cy.visit('/remote-schemas/manage/test_remote_schema/modify'); + setMetaData(); + }); + + it('Modify the remote schema settings', () => { + modifyCustomization({ + root_fields_namespace: 'test_root_namespace', + type_names: { + prefix: 'test_prefix', + suffix: 'test_suffix', + mapping: { + Pokemon: 'renamed_type_name_mapping', + }, + }, + field_names: [ + { + parent_type: 'PokemonDimension', + prefix: 'test_parent_type_prefix', + suffix: 'test_parent_type_suffix', + mapping: { + minimum: 'test_field_name', + }, + }, + ], + }); + }); + + it('expect success notification', () => { + expectNotif('success', { + title: 'Remote schema modified', + }); + }); + }); + + describe('Remove remote schema', () => { + it('Remove the remote schema via the API', () => { + removeRemoteSchema('test_remote_schema'); + }); + }); + }); +}; + +if (testMode !== 'cli') { + // setup(); + editSchemaTests(); +} diff --git a/console/src/components/Services/RemoteSchema/Add/addRemoteSchemaReducer.js b/console/src/components/Services/RemoteSchema/Add/addRemoteSchemaReducer.js index 6a19662b16f..9b71d99b851 100644 --- a/console/src/components/Services/RemoteSchema/Add/addRemoteSchemaReducer.js +++ b/console/src/components/Services/RemoteSchema/Add/addRemoteSchemaReducer.js @@ -21,6 +21,7 @@ const ENV_URL_CHANGED = '@addRemoteSchema/ENV_URL_CHANGED'; const NAME_CHANGED = '@addRemoteSchema/NAME_CHANGED'; const TIMEOUT_CONF_CHANGED = '@addRemoteSchema/TIMEOUT_CONF_CHANGED'; const COMMENT_CHANGED = '@addRemoteSchema/COMMENT_CHANGED'; +const CUSTOMIZATION_CHANGED = '@addRemoteSchema/CUSTOMIZATION_CHANGED'; // const HEADER_CHANGED = '@addRemoteSchema/HEADER_CHANGED'; const ADDING_REMOTE_SCHEMA = '@addRemoteSchema/ADDING_REMOTE_SCHEMA'; const ADD_REMOTE_SCHEMA_FAIL = '@addRemoteSchema/ADD_REMOTE_SCHEMA_FAIL'; @@ -48,6 +49,7 @@ const inputEventMap = { manualUrl: MANUAL_URL_CHANGED, timeoutConf: TIMEOUT_CONF_CHANGED, comment: COMMENT_CHANGED, + customization: CUSTOMIZATION_CHANGED, }; /* Action creators */ @@ -251,6 +253,7 @@ const modifyRemoteSchema = () => (dispatch, getState) => { timeout_seconds: timeoutSeconds, forward_client_headers: currState.forwardClientHeaders, headers: getReqHeader(getState().remoteSchemas.headerData.headers), + customization: currState.customization, }; const remoteSchemaComment = currState?.comment; @@ -281,6 +284,7 @@ const modifyRemoteSchema = () => (dispatch, getState) => { timeout_seconds: oldTimeout, headers: currState.editState.originalHeaders, forward_client_headers: currState.editState.originalForwardClientHeaders, + currState: currState.editState.oldCustomization, }; if (!currState.editState.originalUrl) { @@ -360,6 +364,11 @@ const addRemoteSchemaReducer = (state = addState, action) => { ...state, comment: action.data, }; + case CUSTOMIZATION_CHANGED: + return { + ...state, + customization: action.data, + }; case ADDING_REMOTE_SCHEMA: return { ...state, @@ -404,6 +413,7 @@ const addRemoteSchemaReducer = (state = addState, action) => { : '60', forwardClientHeaders: action.data.definition.forward_client_headers, comment: action.data?.comment || '', + customization: action.data.definition?.customization, editState: { ...state, isModify: false, @@ -414,6 +424,7 @@ const addRemoteSchemaReducer = (state = addState, action) => { originalForwardClientHeaders: action.data.definition.forward_client_headers || false, originalComment: action.data?.comment || '', + originalCustomization: action.data.definition?.customization, }, isFetching: false, isFetchError: null, diff --git a/console/src/components/Services/RemoteSchema/Common/Common.js b/console/src/components/Services/RemoteSchema/Common/Common.js index ac7b5e2abf9..850899611b4 100644 --- a/console/src/components/Services/RemoteSchema/Common/Common.js +++ b/console/src/components/Services/RemoteSchema/Common/Common.js @@ -10,6 +10,7 @@ import { } from '../Add/addRemoteSchemaReducer'; import CommonHeader from '../../../Common/Layout/ReusableHeader/Header'; +import GraphQLCustomizationEdit from './GraphQLCustomization/GraphQLCustomizationEdit'; class Common extends React.Component { getPlaceHolderText(valType) { @@ -24,6 +25,10 @@ class Common extends React.Component { this.props.dispatch(inputChange(fieldName, e.target.value)); } + handleCustomizationInputChange(updateValue) { + this.props.dispatch(inputChange('customization', updateValue)); + } + toggleUrlParam(e) { const field = e.target.getAttribute('value'); this.props.dispatch(inputChange(field, '')); @@ -44,7 +49,9 @@ class Common extends React.Component { forwardClientHeaders, comment, isNew = false, + customization, } = this.props; + const { isModify } = this.props.editState; const isDisabled = !isNew && !isModify; @@ -252,6 +259,32 @@ class Common extends React.Component { data-test="remote-schema-comment" /> +
+ {/* */} + {isNew ? null : ( + <> +
+ GraphQL Customizations{' '} + + Individual Types and Fields will be editable after saving. + + } + > +