mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-12-14 17:02:49 +03:00
console: e2e snapshot testing for event triggers
This PR adds e2e snapshot testing for event triggers. We are testing it in 2 ways - 1. testing the shortest possible path to create ET and then modifying it to the longest possible path - here we are testing the shortest path and see no extra fields are added to avoid regression. Then we modify the shortest path to the longest one and see nothing will break on the metadata side 2. testing the longest possible path to create ET and then modifying it to the shortest possible path - here we are testing the longest path and see if all the fields are passing to avoid regression. Then we modify the longest path to the shortest one and see nothing will break on the metadata side 3. More info in the [doc](https://docs.google.com/document/d/1NjZsvd6xOq90lNMai8nKBaWl-LqBWrkiZCHSQ7wusdE/edit) PR-URL: https://github.com/hasura/graphql-engine-mono/pull/8341 GitOrigin-RevId: f44d5297e70fe50fc4f2a2ac43a1707b71398ba1
This commit is contained in:
parent
c3451bd622
commit
6621dc6adb
@ -1,4 +1,4 @@
|
||||
const createTable = (tableName: string) => {
|
||||
export const createTable = (tableName: string) => {
|
||||
const postBody = {
|
||||
type: 'run_sql',
|
||||
args: {
|
||||
@ -14,7 +14,7 @@ const createTable = (tableName: string) => {
|
||||
}
|
||||
);
|
||||
};
|
||||
const deleteTable = (tableName: string) => {
|
||||
export const deleteTable = (tableName: string) => {
|
||||
const postBody = {
|
||||
type: 'run_sql',
|
||||
args: {
|
||||
|
@ -0,0 +1,74 @@
|
||||
exports[`Create event trigger with shortest possible path > When the users create, modify and delete an Event trigger, everything should work #0`] =
|
||||
{
|
||||
"definition": {
|
||||
"enable_manual": false,
|
||||
"insert": {
|
||||
"columns": "*"
|
||||
},
|
||||
"update": {
|
||||
"columns": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
},
|
||||
"headers": [
|
||||
{
|
||||
"name": "x-hasura-user-id",
|
||||
"value": "1234"
|
||||
}
|
||||
],
|
||||
"name": "event_trigger_test",
|
||||
"request_transform": {
|
||||
"body": {
|
||||
"action": "transform",
|
||||
"template": "{\n \"table\": {\n \"name\": {{$body.table.name}},\n \"schema\": {{$body.table.schema}}\n }\n}"
|
||||
},
|
||||
"method": "GET",
|
||||
"query_params": {
|
||||
"x-hasura-user-id": "my-user-id"
|
||||
},
|
||||
"request_headers": {
|
||||
"add_headers": {},
|
||||
"remove_headers": [
|
||||
"content-type"
|
||||
]
|
||||
},
|
||||
"template_engine": "Kriti",
|
||||
"url": "{{$base_url}}/transformUrl",
|
||||
"version": 2
|
||||
},
|
||||
"retry_conf": {
|
||||
"interval_sec": 5,
|
||||
"num_retries": 10,
|
||||
"timeout_sec": 70
|
||||
},
|
||||
"webhook": "http://httpbin.org/post"
|
||||
};
|
||||
|
||||
exports[`Create event trigger with logest possible path > When the users create, modify and delete an Event trigger, everything should work #0`] =
|
||||
{
|
||||
"definition": {
|
||||
"enable_manual": false,
|
||||
"insert": {
|
||||
"columns": "*"
|
||||
},
|
||||
"update": {
|
||||
"columns": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
},
|
||||
"headers": [
|
||||
{
|
||||
"name": "x-hasura-user-id",
|
||||
"value": "1234"
|
||||
}
|
||||
],
|
||||
"name": "event_trigger_test",
|
||||
"retry_conf": {
|
||||
"interval_sec": 5,
|
||||
"num_retries": 10,
|
||||
"timeout_sec": 70
|
||||
},
|
||||
"webhook": "http://httpbin.org/post"
|
||||
};
|
@ -0,0 +1,271 @@
|
||||
import { HasuraMetadataV3 } from '@hasura/console-legacy-ce';
|
||||
import { readMetadata } from '../actions/withTransform/utils/services/readMetadata';
|
||||
import { postgres } from '../data/manage-database/postgres.spec';
|
||||
|
||||
describe('Create event trigger with shortest possible path', () => {
|
||||
before(() => {
|
||||
// create a table first
|
||||
postgres.helpers.createTable('user_table');
|
||||
|
||||
// track the table
|
||||
cy.visit('/data/default/schema/public', {
|
||||
timeout: 10000,
|
||||
});
|
||||
cy.get('[data-test=add-track-table-user_table]', {
|
||||
timeout: 10000,
|
||||
}).click();
|
||||
});
|
||||
after(() => {
|
||||
// delete the table
|
||||
cy.log('**--- Delete the table');
|
||||
postgres.helpers.deleteTable('user_table');
|
||||
});
|
||||
|
||||
it('When the users create, modify and delete an Event trigger, everything should work', () => {
|
||||
cy.log('**------------------------------**');
|
||||
cy.log('**------------------------------**');
|
||||
cy.log('**------------------------------**');
|
||||
cy.log('**--- Step 1: Create an ET with shortest path**');
|
||||
cy.log('**------------------------------**');
|
||||
cy.log('**------------------------------**');
|
||||
cy.log('**------------------------------**');
|
||||
|
||||
cy.visit('/events/data/manage', {
|
||||
timeout: 10000,
|
||||
onBeforeLoad(win) {
|
||||
cy.stub(win, 'prompt').returns('event_trigger_test');
|
||||
},
|
||||
});
|
||||
|
||||
// --------------------
|
||||
cy.log('**--- Click on the Create button of the ET panel**');
|
||||
cy.get('[data-testid=data-create-trigger]').click();
|
||||
|
||||
// trigger name
|
||||
cy.log('**--- Type the event trigger name**');
|
||||
cy.findByPlaceholderText('trigger_name').type('event_trigger_test');
|
||||
|
||||
// select source
|
||||
cy.log('**--- Select the DB');
|
||||
cy.get('[name="source"]').select('default');
|
||||
|
||||
// select schema and table
|
||||
cy.log('**--- Select the schema and table');
|
||||
cy.get('[name="schema"]').select('public');
|
||||
cy.get('[name="tableName"]').select('user_table');
|
||||
|
||||
// select the trigger operation
|
||||
cy.log('**--- Select the ET operation');
|
||||
cy.get('[name=insert]').click();
|
||||
|
||||
// add webhook url
|
||||
cy.log('**--- Add webhook url');
|
||||
cy.get('[name=handler]').type('http://httpbin.org/post');
|
||||
|
||||
// click on create button to save ET
|
||||
cy.log('**--- Click on Create Event Trigger');
|
||||
cy.findByRole('button', { name: 'Create Event Trigger' }).click();
|
||||
|
||||
cy.log('**------------------------------**');
|
||||
cy.log('**------------------------------**');
|
||||
cy.log('**------------------------------**');
|
||||
cy.log('**--- Step 2: Modify an ET to longest path and save it**');
|
||||
cy.log('**------------------------------**');
|
||||
cy.log('**------------------------------**');
|
||||
cy.log('**------------------------------**');
|
||||
|
||||
// modfy the trigger operation
|
||||
cy.log(
|
||||
'**--- Click on Edit trigger operation and modfiy the trigger operation'
|
||||
);
|
||||
cy.findAllByRole('button', { name: 'Edit' }).eq(1).click();
|
||||
cy.get('[name=update]').click();
|
||||
cy.get('[name=column-id]').click();
|
||||
cy.findByRole('button', { name: 'Save' }).click();
|
||||
|
||||
// modify the retry config
|
||||
cy.log('**--- Click on Edit retry config and modify the config');
|
||||
cy.findAllByRole('button', { name: 'Edit' }).eq(1).click();
|
||||
cy.get('[name=num_retries]').clear().type('10');
|
||||
cy.get('[name=interval_sec]').clear().type('5');
|
||||
cy.get('[name=timeout_sec]').clear().type('70');
|
||||
cy.findByRole('button', { name: 'Save' }).click();
|
||||
|
||||
// add headers
|
||||
cy.log('**--- Click on Edit retry config and add header');
|
||||
cy.findAllByRole('button', { name: 'Edit' }).eq(2).click();
|
||||
cy.findByPlaceholderText('key').type('x-hasura-user-id');
|
||||
cy.findByPlaceholderText('value').type('1234');
|
||||
cy.findByRole('button', { name: 'Save' }).click();
|
||||
|
||||
// add Sample context
|
||||
cy.log('**--- Click on show sample context and fill the form');
|
||||
cy.findByText('Show Sample Context').click();
|
||||
cy.findByPlaceholderText('Key...').type('env-var');
|
||||
cy.findByPlaceholderText('Value...').type('env-var-value');
|
||||
|
||||
// add Request Options Transform
|
||||
cy.log('**--- Click on Add Request Options Transform and fill the form');
|
||||
cy.findByText('Add Request Options Transform').click();
|
||||
cy.get('[name=GET]').click();
|
||||
cy.get('[name=request_url]').type('/transformUrl');
|
||||
cy.findAllByPlaceholderText('Key...').eq(2).type('x-hasura-user-id');
|
||||
cy.findAllByPlaceholderText('Value...').eq(2).type('my-user-id');
|
||||
|
||||
// add Payload Transform
|
||||
cy.log('**--- Click on Add Payload Transform and fill the form');
|
||||
cy.findByText('Add Payload Transform').click();
|
||||
|
||||
// save the ET
|
||||
cy.log('**--- Click on Save Event trigger to modify the ET');
|
||||
cy.findByRole('button', { name: 'Save Event Trigger' }).click();
|
||||
|
||||
readMetadata().then((md: { body: HasuraMetadataV3 }) => {
|
||||
cy.wrap(
|
||||
(md.body.sources || [])
|
||||
.find(source => source.name === 'default')
|
||||
.tables.find(table => table?.table?.name === 'user_table')
|
||||
?.event_triggers?.[0]
|
||||
).toMatchSnapshot({ name: 'Modify the shotest path to longest' });
|
||||
});
|
||||
|
||||
// delete ET
|
||||
cy.findByRole('button', { name: 'Delete Event Trigger' }).click();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Create event trigger with logest possible path', () => {
|
||||
before(() => {
|
||||
// create a table first
|
||||
postgres.helpers.createTable('user_table');
|
||||
|
||||
// track the table
|
||||
cy.visit('/data/default/schema/public', {
|
||||
timeout: 10000,
|
||||
});
|
||||
cy.get('[data-test=add-track-table-user_table]', {
|
||||
timeout: 10000,
|
||||
}).click();
|
||||
});
|
||||
after(() => {
|
||||
// delete the table
|
||||
cy.log('**--- Delete the table');
|
||||
postgres.helpers.deleteTable('user_table');
|
||||
});
|
||||
it('When the users create, modify and delete an Event trigger, everything should work', () => {
|
||||
cy.log('**------------------------------**');
|
||||
cy.log('**------------------------------**');
|
||||
cy.log('**------------------------------**');
|
||||
cy.log('**--- Step 1: Create an ET with longest path**');
|
||||
cy.log('**------------------------------**');
|
||||
cy.log('**------------------------------**');
|
||||
cy.log('**------------------------------**');
|
||||
|
||||
cy.visit('/events/data/manage', {
|
||||
timeout: 10000,
|
||||
onBeforeLoad(win) {
|
||||
cy.stub(win, 'prompt').returns('event_trigger_test');
|
||||
},
|
||||
});
|
||||
|
||||
// --------------------
|
||||
cy.log('**--- Click on the Create button of the ET panel**');
|
||||
cy.get('[data-testid=data-create-trigger]').click();
|
||||
|
||||
// trigger name
|
||||
cy.log('**--- Type the event trigger name**');
|
||||
cy.findByPlaceholderText('trigger_name').type('event_trigger_test');
|
||||
|
||||
// select source
|
||||
cy.log('**--- Select the DB');
|
||||
cy.get('[name="source"]').select('default');
|
||||
|
||||
// select schema and table
|
||||
cy.log('**--- Select the schema and table');
|
||||
cy.get('[name="schema"]').select('public');
|
||||
cy.get('[name="tableName"]').select('user_table');
|
||||
|
||||
// select the trigger operation
|
||||
cy.log('**--- Select the ET operation');
|
||||
cy.get('[name=insert]').click();
|
||||
|
||||
// add webhook url
|
||||
cy.log('**--- Add webhook url');
|
||||
cy.get('[name=handler]').type('http://httpbin.org/post');
|
||||
|
||||
// toggle the adv setting, add retry config and headers
|
||||
cy.log('**--- Add retry config');
|
||||
cy.findByText('Advanced Settings').click();
|
||||
cy.get('[name=num_retries]').clear().type('10');
|
||||
cy.get('[name=interval_sec]').clear().type('5');
|
||||
cy.get('[name=timeout_sec]').clear().type('70');
|
||||
|
||||
// add headers
|
||||
cy.log('**--- Add header');
|
||||
cy.findByPlaceholderText('key').type('x-hasura-user-id');
|
||||
cy.findByPlaceholderText('value').type('1234');
|
||||
|
||||
// add Sample context
|
||||
cy.log('**--- Click on show sample context and fill the form');
|
||||
cy.findByText('Show Sample Context').click();
|
||||
cy.findByPlaceholderText('Key...').type('env-var');
|
||||
cy.findByPlaceholderText('Value...').type('env-var-value');
|
||||
|
||||
// add Request Options Transform
|
||||
cy.log('**--- Click on Add Request Options Transform and fill the form');
|
||||
cy.findByText('Add Request Options Transform').click();
|
||||
cy.get('[name=GET]').click();
|
||||
cy.get('[name=request_url]').type('/transformUrl');
|
||||
cy.findAllByPlaceholderText('Key...').eq(2).type('x-hasura-user-id');
|
||||
cy.findAllByPlaceholderText('Value...').eq(2).type('my-user-id');
|
||||
|
||||
// add Payload Transform
|
||||
cy.log('**--- Click on Add Payload Transform and fill the form');
|
||||
cy.findByText('Add Payload Transform').click();
|
||||
|
||||
// click on create button to save ET
|
||||
cy.log('**--- Click on Create Event Trigger');
|
||||
cy.get('[data-test=trigger-create]').click();
|
||||
|
||||
cy.log('**------------------------------**');
|
||||
cy.log('**------------------------------**');
|
||||
cy.log('**------------------------------**');
|
||||
cy.log('**--- Step 2: Modify an ET to shortest path and save it**');
|
||||
cy.log('**------------------------------**');
|
||||
cy.log('**------------------------------**');
|
||||
cy.log('**------------------------------**');
|
||||
|
||||
// modfy the trigger operation
|
||||
cy.log(
|
||||
'**--- Click on Edit trigger operation and modfiy the trigger operation'
|
||||
);
|
||||
cy.findAllByRole('button', { name: 'Edit' }).eq(1).click();
|
||||
cy.get('[name=update]').click();
|
||||
cy.get('[name=column-id]').click();
|
||||
cy.findByRole('button', { name: 'Save' }).click();
|
||||
|
||||
// remove Request Options Transform
|
||||
cy.log('**--- Click on Remove Request Options Transform');
|
||||
cy.findByText('Remove Request Options Transform').click();
|
||||
|
||||
// remove Payload Transform
|
||||
cy.log('**--- Click on Remove Payload Transform');
|
||||
cy.findByText('Remove Payload Transform').click();
|
||||
|
||||
// save the ET
|
||||
cy.log('**--- Click on Save Event trigger to modify the ET');
|
||||
cy.findByRole('button', { name: 'Save Event Trigger' }).click();
|
||||
|
||||
readMetadata().then((md: { body: HasuraMetadataV3 }) => {
|
||||
cy.wrap(
|
||||
(md.body.sources || [])
|
||||
.find(source => source.name === 'default')
|
||||
.tables.find(table => table?.table?.name === 'user_table')
|
||||
?.event_triggers?.[0]
|
||||
).toMatchSnapshot({ name: 'Modify the longest path to shortest path' });
|
||||
});
|
||||
|
||||
// delete ET
|
||||
cy.findByRole('button', { name: 'Delete Event Trigger' }).click();
|
||||
});
|
||||
});
|
@ -120,7 +120,6 @@ const ConfigureTransformation: React.FC<
|
||||
<Button
|
||||
color="white"
|
||||
size="sm"
|
||||
data-test="toggle-context-area"
|
||||
onClick={() => {
|
||||
toggleContextArea(!isContextAreaActive);
|
||||
}}
|
||||
@ -160,7 +159,6 @@ const ConfigureTransformation: React.FC<
|
||||
size="sm"
|
||||
icon={!isRequestUrlTransform ? <AddIcon /> : undefined}
|
||||
iconPosition="start"
|
||||
data-test="toggle-request-transform"
|
||||
onClick={() => {
|
||||
requestUrlTransformOnChange(!isRequestUrlTransform);
|
||||
resetSampleInput();
|
||||
@ -203,7 +201,6 @@ const ConfigureTransformation: React.FC<
|
||||
<Button
|
||||
color="white"
|
||||
size="sm"
|
||||
data-test="toggle-payload-transform"
|
||||
onClick={() => {
|
||||
requestPayloadTransformOnChange(!isRequestPayloadTransform);
|
||||
resetSampleInput();
|
||||
@ -245,7 +242,6 @@ const ConfigureTransformation: React.FC<
|
||||
<Button
|
||||
color="white"
|
||||
size="sm"
|
||||
data-test="toggle-response-transform"
|
||||
onClick={() => {
|
||||
responsePayloadTransformOnChange(
|
||||
!responseTransformState.isResponsePayloadTransform
|
||||
|
@ -44,7 +44,6 @@ const KeyValueInput: React.FC<KeyValueInputProps> = ({
|
||||
value={name}
|
||||
onChange={setPairKey}
|
||||
type="text"
|
||||
name="table_name"
|
||||
id="table_name"
|
||||
className={`w-full ${inputStyles}`}
|
||||
placeholder="Key..."
|
||||
@ -56,7 +55,6 @@ const KeyValueInput: React.FC<KeyValueInputProps> = ({
|
||||
value={value}
|
||||
onChange={setPairValue}
|
||||
type="text"
|
||||
name="table_name"
|
||||
id="table_name"
|
||||
className={`w-full ${inputStyles}`}
|
||||
placeholder="Value..."
|
||||
|
@ -121,6 +121,7 @@ const DDButton: React.FC<DropDownButtonProps> = props => {
|
||||
value={inputVal || ''}
|
||||
placeholder={inputPlaceHolder}
|
||||
data-test={`${testId}-input`}
|
||||
name={`${dataKey}[${dataIndex}]`}
|
||||
/>
|
||||
</InputGroup>
|
||||
);
|
||||
|
@ -83,8 +83,8 @@ const Headers: React.FC<HeadersListProps> = ({
|
||||
inputVal={value}
|
||||
id={`header-value-${i}`}
|
||||
inputPlaceHolder={type === 'env' ? 'HEADER_FROM_ENV' : 'value'}
|
||||
testId={`header-value-${i}`}
|
||||
disabled={disabled}
|
||||
testId={`header-value-${i}`}
|
||||
/>
|
||||
</div>
|
||||
{i < headers.length - 1 ? (
|
||||
|
@ -36,8 +36,6 @@ class Editor extends React.Component {
|
||||
const {
|
||||
readOnlyMode = false,
|
||||
isCollapsable,
|
||||
service,
|
||||
property,
|
||||
collapseButtonText,
|
||||
expandButtonText,
|
||||
} = this.props;
|
||||
@ -52,7 +50,6 @@ class Editor extends React.Component {
|
||||
mode="default"
|
||||
size="sm"
|
||||
className="mr-sm"
|
||||
data-test={`${service}-${isEditing ? 'close' : 'edit'}-${property}`}
|
||||
onClick={this.toggleEditor}
|
||||
disabled={readOnlyMode}
|
||||
>
|
||||
|
@ -94,7 +94,6 @@ const CreateETForm: React.FC<CreateETFormProps> = props => {
|
||||
/>
|
||||
<input
|
||||
type="text"
|
||||
data-test="trigger-name"
|
||||
placeholder="trigger_name"
|
||||
required
|
||||
pattern="^[A-Za-z]+[A-Za-z0-9_\\-]*$"
|
||||
@ -108,8 +107,8 @@ const CreateETForm: React.FC<CreateETFormProps> = props => {
|
||||
<select
|
||||
className={`${inputStyles} pl-md w-72`}
|
||||
onChange={handleDatabaseChange}
|
||||
data-test="select-source"
|
||||
value={source}
|
||||
name="source"
|
||||
>
|
||||
<option value="">Select database</option>
|
||||
{dataSourcesList
|
||||
@ -125,9 +124,9 @@ const CreateETForm: React.FC<CreateETFormProps> = props => {
|
||||
<div className="flex">
|
||||
<select
|
||||
onChange={handleSchemaChange}
|
||||
data-test="select-schema"
|
||||
className={`${inputStyles} w-72`}
|
||||
value={table.schema}
|
||||
name="schema"
|
||||
>
|
||||
<option value="">Select schema</option>
|
||||
{Object.keys(databaseInfo)
|
||||
@ -140,10 +139,10 @@ const CreateETForm: React.FC<CreateETFormProps> = props => {
|
||||
</select>
|
||||
<select
|
||||
onChange={handleTableChange}
|
||||
data-test="select-table"
|
||||
required
|
||||
className={`${inputStyles} w-72 ml-md`}
|
||||
value={table.name}
|
||||
name="tableName"
|
||||
>
|
||||
<option value="">Select table</option>
|
||||
{filterSchemas &&
|
||||
|
@ -149,6 +149,7 @@ export const OperationEditor: React.FC<OperationEditorProps> = props => {
|
||||
>
|
||||
<input
|
||||
type="checkbox"
|
||||
name={`column-${col.name}`}
|
||||
className={`!mr-xs cursor-pointer ${focusYellowRing} disabled:bg-gray-200 disabled:cursor-not-allowed disabled:text-gray-200 border-gray-200 rounded-sm bg-white`}
|
||||
checked={col.enabled}
|
||||
disabled={readOnly}
|
||||
|
Loading…
Reference in New Issue
Block a user