mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-12-15 01:12:56 +03:00
test(console): Skip a lot of flaky E2E tests
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/5535 GitOrigin-RevId: 0544edf4d8fdd1a6a8cc326a8b107ee47d2389c3
This commit is contained in:
parent
d5af9dfa05
commit
5764174087
@ -1,32 +0,0 @@
|
||||
import { defineConfig } from 'cypress';
|
||||
|
||||
import * as customTasks from './cypress/support/tasks';
|
||||
|
||||
export default defineConfig({
|
||||
env: {
|
||||
BASE_URL: 'http://localhost:3000',
|
||||
TEST_MODE: 'parallel',
|
||||
MIGRATE_URL: 'http://localhost:9693/apis/migrate',
|
||||
},
|
||||
viewportWidth: 1280,
|
||||
viewportHeight: 720,
|
||||
chromeWebSecurity: false,
|
||||
video: false,
|
||||
projectId: '5yiuic',
|
||||
e2e: {
|
||||
// We've imported your old cypress plugins here.
|
||||
// You may want to clean this up later by importing these.
|
||||
setupNodeEvents(on, config) {
|
||||
on('task', {
|
||||
...customTasks,
|
||||
});
|
||||
|
||||
return config;
|
||||
},
|
||||
baseUrl: 'http://localhost:3000',
|
||||
specPattern: [
|
||||
'cypress/e2e/**/*test.{js,jsx,ts,tsx}',
|
||||
'cypress/support/**/*unit.test.{js,ts}',
|
||||
],
|
||||
},
|
||||
});
|
@ -4,7 +4,6 @@ import * as customTasks from './cypress/support/tasks';
|
||||
|
||||
export default defineConfig({
|
||||
env: {
|
||||
BASE_URL: 'http://localhost:3000',
|
||||
TEST_MODE: 'parallel',
|
||||
MIGRATE_URL: 'http://localhost:9693/apis/migrate',
|
||||
},
|
||||
@ -13,7 +12,6 @@ export default defineConfig({
|
||||
chromeWebSecurity: false,
|
||||
video: false,
|
||||
projectId: '5yiuic',
|
||||
retries: 1,
|
||||
numTestsKeptInMemory: 10,
|
||||
e2e: {
|
||||
// We've imported your old cypress plugins here.
|
||||
|
@ -4,7 +4,9 @@ import { setMetaData } from '../validators/validators';
|
||||
import { getIndexRoute } from '../../helpers/dataHelpers';
|
||||
|
||||
const setup = () => {
|
||||
describe('Setup route', () => {
|
||||
// Temporarily skipped because of its flakiness, see: https://github.com/hasura/graphql-engine-mono/issues/5433
|
||||
// TODO: Fix and restore it
|
||||
describe.skip('Setup route', () => {
|
||||
it('Visit the index route', () => {
|
||||
cy.visit(getIndexRoute());
|
||||
setMetaData();
|
||||
@ -14,9 +16,20 @@ const setup = () => {
|
||||
|
||||
export const runActionsTests = () => {
|
||||
describe('onboarding', () => {
|
||||
it('should show onboarding guide', viewOnboarding);
|
||||
it('should hide when user click on Hide Now', hideNow);
|
||||
it('should hide forever when user click on Dont Show again', dontShowAgain);
|
||||
// Temporarily skipped because of its flakiness, see: https://github.com/hasura/graphql-engine-mono/issues/5433
|
||||
// TODO: Fix and restore it
|
||||
it.skip('should show onboarding guide', viewOnboarding);
|
||||
|
||||
// Temporarily skipped because of its flakiness, see: https://github.com/hasura/graphql-engine-mono/issues/5433
|
||||
// TODO: Fix and restore it
|
||||
it.skip('should hide when user click on Hide Now', hideNow);
|
||||
|
||||
// Temporarily skipped because of its flakiness, see: https://github.com/hasura/graphql-engine-mono/issues/5433
|
||||
// TODO: Fix and restore it
|
||||
it.skip(
|
||||
'should hide forever when user click on Dont Show again',
|
||||
dontShowAgain
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -1,172 +0,0 @@
|
||||
import { testMode } from '../../../helpers/common';
|
||||
|
||||
import { logMetadataRequests } from './utils/requests/logMetadataRequests';
|
||||
import { loginActionMustNotExist } from './utils/testState/loginActionMustNotExist';
|
||||
|
||||
// NOTE: This test suite does not include cases for relationships, headers and the codegen part
|
||||
|
||||
if (testMode !== 'cli') {
|
||||
describe('Mutation Actions', () => {
|
||||
before(() => {
|
||||
loginActionMustNotExist();
|
||||
logMetadataRequests();
|
||||
|
||||
cy.visit('/actions/manage/actions');
|
||||
});
|
||||
|
||||
after(() => {
|
||||
// Cleanup after the whole test file run
|
||||
|
||||
// Ensure the application is not there when manually deleting the created action to avoid any
|
||||
// potential client-side error that makes the test fail
|
||||
cy.visitEmptyPage();
|
||||
|
||||
// Delete the created action, if any
|
||||
loginActionMustNotExist();
|
||||
});
|
||||
|
||||
it('When the users create, edit, and delete a Mutation Action, everything should work', () => {
|
||||
cy.log('**------------------------------**');
|
||||
cy.log('**------------------------------**');
|
||||
cy.log('**------------------------------**');
|
||||
cy.log('**--- Step 1: Mutation Action creation**');
|
||||
cy.log('**------------------------------**');
|
||||
cy.log('**------------------------------**');
|
||||
cy.log('**------------------------------**');
|
||||
|
||||
// --------------------
|
||||
cy.log('**--- Click on the Create button of the Actions panel**');
|
||||
cy.getBySel('data-create-actions').click();
|
||||
|
||||
// Assign an alias to the most unclear selectors for future references
|
||||
cy.get('textarea').eq(0).as('actionDefinitionTextarea');
|
||||
cy.get('textarea').eq(1).as('typeConfigurationTextarea');
|
||||
|
||||
// --------------------
|
||||
cy.log('**--- Type in the Action Definition textarea**');
|
||||
cy.get('@actionDefinitionTextarea').clearConsoleTextarea().type(
|
||||
`type Mutation {
|
||||
login (username: String!, password: String!): LoginResponse
|
||||
}`,
|
||||
{ force: true, delay: 0 }
|
||||
);
|
||||
|
||||
// --------------------
|
||||
cy.log('**--- Type in the Type Configuration textarea**');
|
||||
cy.get('@typeConfigurationTextarea').clearConsoleTextarea().type(
|
||||
`type LoginResponse {
|
||||
accessToken: String!
|
||||
}`,
|
||||
{ force: true, delay: 0 }
|
||||
);
|
||||
|
||||
cy.log('**--- Type in the Webhook Handler field**');
|
||||
cy.getBySel('action-create-handler-input')
|
||||
.clearConsoleTextarea()
|
||||
.type('https://hasura-actions-demo.glitch.me/login', {
|
||||
delay: 0,
|
||||
parseSpecialCharSequences: false,
|
||||
});
|
||||
|
||||
// Due to the double server/cli mode behavior, we do not assert about the XHR request payload here
|
||||
|
||||
// --------------------
|
||||
cy.log('**--- Click the Create button**');
|
||||
cy.getBySel('create-action-btn').click();
|
||||
|
||||
// Due to the double server/cli mode behavior, we do not assert about the XHR request payload here
|
||||
|
||||
// --------------------
|
||||
cy.log('**--- Check if the success notification is visible**');
|
||||
cy.get(
|
||||
'.notification',
|
||||
// The custom timeout aims to replace the lack of waiting for the outgoing request
|
||||
{ timeout: 10000 }
|
||||
)
|
||||
.should('be.visible')
|
||||
.and('contain', 'Created action successfully');
|
||||
|
||||
// TODO: check if it exists in the database? Other tests do that
|
||||
|
||||
cy.log('**------------------------------**');
|
||||
cy.log('**------------------------------**');
|
||||
cy.log('**------------------------------**');
|
||||
cy.log('**--- Step 2: Permission add**');
|
||||
cy.log('**------------------------------**');
|
||||
cy.log('**------------------------------**');
|
||||
cy.log('**------------------------------**');
|
||||
|
||||
// --------------------
|
||||
cy.log('**--- Go the the action page**');
|
||||
cy.getBySel('actions-table-links').within(() => {
|
||||
cy.getBySel('login').click();
|
||||
});
|
||||
|
||||
// --------------------
|
||||
cy.log('**--- Click the Permissions tab**');
|
||||
cy.getBySel('actions-permissions').click();
|
||||
|
||||
// --------------------
|
||||
cy.log('**--- Enter a new role**');
|
||||
cy.getBySel('role-textbox').type('manager');
|
||||
cy.getBySel('manager-Permission').click();
|
||||
|
||||
// --------------------
|
||||
cy.log('**--- Click Save Permissions**');
|
||||
cy.getBySel('save-permissions-for-action').click();
|
||||
|
||||
// Due to the double server/cli mode behavior, we do not assert about the XHR request payload here
|
||||
|
||||
// --------------------
|
||||
cy.log('**--- Check if the success notification is visible**');
|
||||
cy.get(
|
||||
'.notification',
|
||||
// The custom timeout aims to replace the lack of waiting for the outgoing request
|
||||
{ timeout: 10000 }
|
||||
)
|
||||
.should('be.visible')
|
||||
.and('contain', 'Permission saved successfully');
|
||||
|
||||
// TODO: check if it exists in the database? Other tests do that
|
||||
|
||||
cy.log('**------------------------------**');
|
||||
cy.log('**------------------------------**');
|
||||
cy.log('**------------------------------**');
|
||||
cy.log('**--- Step 3: Mutation Action delete**');
|
||||
cy.log('**------------------------------**');
|
||||
cy.log('**------------------------------**');
|
||||
cy.log('**------------------------------**');
|
||||
|
||||
// --------------------
|
||||
cy.log('**--- Go the the action page**');
|
||||
cy.getBySel('actions-table-links').within(() => {
|
||||
cy.getBySel('login').click();
|
||||
});
|
||||
|
||||
// --------------------
|
||||
cy.log('**--- Set the prompt value**');
|
||||
cy.window().then(win => cy.stub(win, 'prompt').returns('login'));
|
||||
|
||||
cy.log('**--- Click the Delete button**');
|
||||
cy.getBySel('delete-action').click();
|
||||
|
||||
// --------------------
|
||||
cy.log('**--- Check the prompt has been called**');
|
||||
cy.window().its('prompt').should('be.called');
|
||||
|
||||
// Due to the double server/cli mode behavior, we do not assert about the XHR request payload here
|
||||
|
||||
// --------------------
|
||||
cy.log('**--- Check if the success notification is visible**');
|
||||
cy.get(
|
||||
'.notification',
|
||||
// The custom timeout aims to replace the lack of waiting for the outgoing request
|
||||
{ timeout: 10000 }
|
||||
)
|
||||
.should('be.visible')
|
||||
.and('contain', 'Action deleted successfully');
|
||||
|
||||
// TODO: check if it does not exist in the database? Other tests do that
|
||||
});
|
||||
});
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
/**
|
||||
* Freeze and check the request and response payloads.
|
||||
*
|
||||
* TODO: properly type the interception.
|
||||
*/
|
||||
export function checkRequestBodies(
|
||||
interception: any,
|
||||
options = { checkResourceVersion: true }
|
||||
) {
|
||||
const { checkResourceVersion } = options;
|
||||
|
||||
const {
|
||||
// The resource_version must be removed before snapshotting the request payload
|
||||
// because it is always different. It's going to be asserted in isolation
|
||||
resource_version,
|
||||
...requestBody
|
||||
} = interception.request.body;
|
||||
|
||||
cy.log('**--- Assert about the request**');
|
||||
|
||||
if (checkResourceVersion) {
|
||||
expect(resource_version, 'resource_version').to.be.a('number');
|
||||
}
|
||||
|
||||
cy.wrap({
|
||||
requestBody,
|
||||
statusCode: interception.response?.statusCode,
|
||||
responseBody: interception.response?.body,
|
||||
}).snapshot();
|
||||
}
|
@ -1,36 +0,0 @@
|
||||
interface SingleMetadataRequest {
|
||||
type: string;
|
||||
// There are a lot of other fields, but tracking them is not important for the purpose of this module
|
||||
}
|
||||
|
||||
interface BulkMetadataRequest {
|
||||
type: 'bulk';
|
||||
args: SingleMetadataRequest[];
|
||||
}
|
||||
|
||||
type MetadataRequest = SingleMetadataRequest | BulkMetadataRequest;
|
||||
|
||||
/*
|
||||
* Log all the requests outgoing to the Metadata endpoint.
|
||||
* This is useful to have a glance of the requests that are going to the server.
|
||||
*/
|
||||
export function logMetadataRequests() {
|
||||
cy.intercept('POST', 'http://localhost:8080/v1/metadata', req => {
|
||||
const noArgs = !req.body.args;
|
||||
|
||||
if (noArgs) return;
|
||||
|
||||
const requestBody = req.body as MetadataRequest;
|
||||
|
||||
if (requestBody.type === 'bulk') {
|
||||
const request = requestBody as BulkMetadataRequest;
|
||||
Cypress.log({ message: '*--- Bulk request*' });
|
||||
|
||||
request.args.forEach(arg =>
|
||||
Cypress.log({ message: `*--- Request: ${arg.type}*` })
|
||||
);
|
||||
} else {
|
||||
Cypress.log({ message: `*--- Request: ${requestBody.type}*` });
|
||||
}
|
||||
});
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
/**
|
||||
* Delete the Action straight from the server.
|
||||
*/
|
||||
export function deleteLoginAction() {
|
||||
Cypress.log({ message: '**--- Action delete: start**' });
|
||||
|
||||
return cy
|
||||
.request('POST', 'http://localhost:8080/v1/metadata', {
|
||||
type: 'drop_action',
|
||||
args: { name: 'login' },
|
||||
})
|
||||
.then(() => Cypress.log({ message: '**--- Action delete: end**' }));
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
/**
|
||||
* Read the Metadata straight from the server.
|
||||
*/
|
||||
export function readMetadata() {
|
||||
Cypress.log({ message: '**--- Metadata read: start**' });
|
||||
|
||||
return cy
|
||||
.request('POST', 'http://localhost:8080/v1/metadata', {
|
||||
args: {},
|
||||
type: 'export_metadata',
|
||||
})
|
||||
.then(_response => {
|
||||
Cypress.log({ message: '**--- Metadata read: end**' });
|
||||
});
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
import { readMetadata } from '../services/readMetadata';
|
||||
import { deleteLoginAction } from '../services/deleteLoginAction';
|
||||
|
||||
/**
|
||||
* Ensure the Action does not exist.
|
||||
*/
|
||||
export function loginActionMustNotExist() {
|
||||
Cypress.log({ message: '**--- Action check: start**' });
|
||||
|
||||
readMetadata().then(response => {
|
||||
const actionExists = !!response.body.actions?.find(
|
||||
// TODO: properly type it
|
||||
action => action.name === 'login'
|
||||
);
|
||||
|
||||
if (actionExists) {
|
||||
Cypress.log({ message: '**--- The Action must be deleted**' }),
|
||||
deleteLoginAction();
|
||||
}
|
||||
});
|
||||
}
|
@ -6,7 +6,9 @@ import { addNumbersActionMustNotExist } from './utils/testState/addNumbersAction
|
||||
// NOTE: This test suite does not include cases for relationships, headers and the codegen part
|
||||
|
||||
if (testMode !== 'cli') {
|
||||
describe('Query Actions', () => {
|
||||
// Temporarily skipped because of its flakiness, see: https://github.com/hasura/graphql-engine-mono/issues/5433
|
||||
// TODO: Fix and restore it
|
||||
describe.skip('Query Actions', () => {
|
||||
before(() => {
|
||||
addNumbersActionMustNotExist();
|
||||
logMetadataRequests();
|
||||
@ -45,21 +47,25 @@ if (testMode !== 'cli') {
|
||||
|
||||
// --------------------
|
||||
cy.log('**--- Type in the Action Definition textarea**');
|
||||
cy.get('@actionDefinitionTextarea').clearConsoleTextarea().type(
|
||||
`type Query {
|
||||
cy.get('@actionDefinitionTextarea')
|
||||
.clearConsoleTextarea()
|
||||
.type(
|
||||
`type Query {
|
||||
addNumbers (numbers: [Int]): AddResult
|
||||
}`,
|
||||
{ force: true, delay: 0 }
|
||||
);
|
||||
{ force: true, delay: 0 }
|
||||
);
|
||||
|
||||
// --------------------
|
||||
cy.log('**--- Type in the Type Configuration textarea**');
|
||||
cy.get('@typeConfigurationTextarea').clearConsoleTextarea().type(
|
||||
`type AddResult {
|
||||
cy.get('@typeConfigurationTextarea')
|
||||
.clearConsoleTextarea()
|
||||
.type(
|
||||
`type AddResult {
|
||||
sum: Int
|
||||
}`,
|
||||
{ force: true, delay: 0 }
|
||||
);
|
||||
{ force: true, delay: 0 }
|
||||
);
|
||||
|
||||
// --------------------
|
||||
cy.log('**--- Type in the Webhook Handler field**');
|
||||
@ -80,15 +86,7 @@ if (testMode !== 'cli') {
|
||||
|
||||
// --------------------
|
||||
cy.log('**--- Check if the success notification is visible**');
|
||||
cy.get(
|
||||
'.notification',
|
||||
// The custom timeout aims to replace the lack of waiting for the outgoing request
|
||||
{ timeout: 10000 }
|
||||
)
|
||||
.should('be.visible')
|
||||
.and('contain', 'Created action successfully');
|
||||
|
||||
// TODO: check if it exists in the database? Other tests do that
|
||||
cy.expectSuccessNotificationWithTitle('Created action successfully');
|
||||
|
||||
cy.log('**------------------------------**');
|
||||
cy.log('**------------------------------**');
|
||||
@ -133,15 +131,7 @@ if (testMode !== 'cli') {
|
||||
|
||||
// --------------------
|
||||
cy.log('**--- Check if the success notification is visible**');
|
||||
cy.get(
|
||||
'.notification',
|
||||
// The custom timeout aims to replace the lack of waiting for the outgoing request
|
||||
{ timeout: 10000 }
|
||||
)
|
||||
.should('be.visible')
|
||||
.and('contain', 'Permission saved successfully');
|
||||
|
||||
// TODO: check if it exists in the database? Other tests do that
|
||||
cy.expectSuccessNotificationWithTitle('Permission saved successfully');
|
||||
|
||||
cy.log('**------------------------------**');
|
||||
cy.log('**------------------------------**');
|
||||
@ -168,15 +158,7 @@ if (testMode !== 'cli') {
|
||||
|
||||
// --------------------
|
||||
cy.log('**--- Check if the success notification is visible**');
|
||||
cy.get(
|
||||
'.notification',
|
||||
// The custom timeout aims to replace the lack of waiting for the outgoing request
|
||||
{ timeout: 10000 }
|
||||
)
|
||||
.should('be.visible')
|
||||
.and('contain', 'Action deleted successfully');
|
||||
|
||||
// TODO: check if it does not exist in the database? Other tests do that
|
||||
cy.expectSuccessNotificationWithTitle('Action deleted successfully');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -14,8 +14,8 @@ export function addNumbersActionMustNotExist() {
|
||||
);
|
||||
|
||||
if (actionExists) {
|
||||
Cypress.log({ message: '**--- The Action must be deleted**' }),
|
||||
deleteAddNumbersAction();
|
||||
Cypress.log({ message: '**--- The Action must be deleted**' });
|
||||
deleteAddNumbersAction();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -2,7 +2,6 @@ import { testMode } from '../../../helpers/common';
|
||||
|
||||
import { logMetadataRequests } from './utils/requests/logMetadataRequests';
|
||||
import { loginActionMustNotExist } from './utils/testState/loginActionMustNotExist';
|
||||
import { waitForPostCreationRequests } from './utils/requests/waitForPostCreationRequests';
|
||||
|
||||
if (testMode !== 'cli') {
|
||||
describe('Actions with Transform', () => {
|
||||
@ -18,10 +17,7 @@ if (testMode !== 'cli') {
|
||||
loginActionMustNotExist();
|
||||
});
|
||||
|
||||
// TODO: This test is slow because it tests not only the happy path but also the error cases of
|
||||
// the Request Options Transform. Checking the error paths through an E2E test is a bad practice.
|
||||
|
||||
it('When the users create, edit, and delete a Action with Transform, everything should work', () => {
|
||||
it('When the users create, and delete a Action with Transform, everything should work', () => {
|
||||
cy.log('**------------------------------**');
|
||||
cy.log('**------------------------------**');
|
||||
cy.log('**------------------------------**');
|
||||
@ -40,28 +36,32 @@ if (testMode !== 'cli') {
|
||||
|
||||
// --------------------
|
||||
cy.log('**--- Type in the Action Definition textarea**');
|
||||
cy.get('@actionDefinitionTextarea').clearConsoleTextarea().type(
|
||||
`type Mutation {
|
||||
cy.get('@actionDefinitionTextarea')
|
||||
.clearConsoleTextarea()
|
||||
.type(
|
||||
`type Mutation {
|
||||
login (username: String!, password: String!): LoginResponse
|
||||
}`,
|
||||
{ force: true, delay: 0 }
|
||||
);
|
||||
{ force: true, delay: 0 }
|
||||
);
|
||||
|
||||
// --------------------
|
||||
cy.log('**--- Type in the Type Configuration textarea**');
|
||||
cy.get('@typeConfigurationTextarea').clearConsoleTextarea().type(
|
||||
`type LoginResponse {
|
||||
cy.get('@typeConfigurationTextarea')
|
||||
.clearConsoleTextarea()
|
||||
.type(
|
||||
`type LoginResponse {
|
||||
accessToken: String!
|
||||
}`,
|
||||
{ force: true, delay: 0 }
|
||||
);
|
||||
{ force: true, delay: 0 }
|
||||
);
|
||||
|
||||
// --------------------
|
||||
cy.log('**--- Click the Add Request Options Transform button**');
|
||||
cy.contains('Add Request Options Transform').click();
|
||||
|
||||
cy.log('**------------------------------**');
|
||||
cy.log('**--- Step 1.1: Invalid URL error**');
|
||||
cy.log('**--- Step 1.1: Add URL**');
|
||||
cy.log('**------------------------------**');
|
||||
|
||||
cy.get('[data-cy="Change Request Options"]').within(() => {
|
||||
@ -71,22 +71,11 @@ if (testMode !== 'cli') {
|
||||
|
||||
// --------------------
|
||||
cy.log('**--- Type in the Request URL Template field**');
|
||||
cy.get('[placeholder="URL Template (Optional)..."]').type('users');
|
||||
|
||||
// Due to the double server/cli mode behavior, we do not assert about the XHR request payload here
|
||||
|
||||
// --------------------
|
||||
cy.log('**--- Look for the "Invalid URL" error**');
|
||||
cy.contains(
|
||||
'TransformationError: Invalid URL: http://host.docker.internal:3000users',
|
||||
// Pleas note that the custom timeout is not checked explicitly checked, but asserting on
|
||||
// the payload (see the next cy.intercept) means asserting on it too
|
||||
{ timeout: 10000 }
|
||||
).should('be.visible');
|
||||
cy.get('[placeholder="URL Template (Optional)..."]').type('/users');
|
||||
});
|
||||
|
||||
cy.log('**------------------------------**');
|
||||
cy.log('**--- Step 1.2: Missing Env Var error**');
|
||||
cy.log('**--- Step 1.2: Add Env Var**');
|
||||
cy.log('**------------------------------**');
|
||||
|
||||
// --------------------
|
||||
@ -98,27 +87,6 @@ if (testMode !== 'cli') {
|
||||
parseSpecialCharSequences: false,
|
||||
});
|
||||
|
||||
cy.get('[data-cy="Change Request Options"]').within(() => {
|
||||
// --------------------
|
||||
cy.log('**--- Type in the Request URL Template field**');
|
||||
cy.get('[placeholder="URL Template (Optional)..."]')
|
||||
.clearConsoleTextarea()
|
||||
.type('/users');
|
||||
|
||||
// Due to the double server/cli mode behavior, we do not assert about the XHR request payload here
|
||||
|
||||
// --------------------
|
||||
cy.log('**--- Look for "Missing Env Var" error**');
|
||||
cy.getBySel('transform-requestUrl-error')
|
||||
.as('missingWebhookError')
|
||||
.should('be.visible')
|
||||
.and('contain', 'not-found: Missing Env Var: MY_WEBHOOK');
|
||||
});
|
||||
|
||||
cy.log('**------------------------------**');
|
||||
cy.log('**--- Step 1.2: Env Var add**');
|
||||
cy.log('**------------------------------**');
|
||||
|
||||
// --------------------
|
||||
cy.log('**--- Click the Show Sample Context button**');
|
||||
cy.contains('Show Sample Context').click();
|
||||
@ -133,17 +101,6 @@ if (testMode !== 'cli') {
|
||||
delay: 1,
|
||||
});
|
||||
|
||||
// Due to the double server/cli mode behavior, we do not assert about the XHR request payload here
|
||||
|
||||
// --------------------
|
||||
cy.log('**--- Check the error disappeared**');
|
||||
cy.get(
|
||||
'@missingWebhookError',
|
||||
// Pleas note that the custom timeout is not checked explicitly checked, but asserting on
|
||||
// the payload (see the next cy.intercept) means asserting on it too
|
||||
{ timeout: 10000 }
|
||||
).should('not.exist');
|
||||
|
||||
// --------------------
|
||||
cy.get('[data-cy="Change Request Options"]').within(() => {
|
||||
cy.log('**--- Check the Preview of the Request URL Template**');
|
||||
@ -154,7 +111,7 @@ if (testMode !== 'cli') {
|
||||
});
|
||||
|
||||
cy.log('**------------------------------**');
|
||||
cy.log('**--- Step 1.3: Invalid Path error**');
|
||||
cy.log('**--- Step 1.3: Add path**');
|
||||
cy.log('**------------------------------**');
|
||||
|
||||
// --------------------
|
||||
@ -166,24 +123,6 @@ if (testMode !== 'cli') {
|
||||
parseSpecialCharSequences: false,
|
||||
});
|
||||
|
||||
cy.get('[data-cy="Change Request Options"]').within(() => {
|
||||
// --------------------
|
||||
cy.log('**--- Type in the Request URL Template field**');
|
||||
cy.get('[placeholder="URL Template (Optional)..."]')
|
||||
.clearConsoleTextarea()
|
||||
.type('{{$url}}/users', { parseSpecialCharSequences: false });
|
||||
});
|
||||
|
||||
// Due to the double server/cli mode behavior, we do not assert about the XHR request payload here
|
||||
|
||||
// --------------------
|
||||
cy.log('**--- Look for "Invalid Path" error**');
|
||||
|
||||
cy.getBySel('transform-requestUrl-error')
|
||||
.as('invalidPathError')
|
||||
.should('be.visible')
|
||||
.and('contain', 'Invalid Path: "$url"');
|
||||
|
||||
cy.log('**------------------------------**');
|
||||
cy.log('**--- Step 1.4: Query Params add**');
|
||||
cy.log('**------------------------------**');
|
||||
@ -210,28 +149,17 @@ if (testMode !== 'cli') {
|
||||
}
|
||||
);
|
||||
|
||||
// Due to the double server/cli mode behavior, we do not assert about the XHR request payload here
|
||||
|
||||
// --------------------
|
||||
cy.log('**--- Check the error disappeared**');
|
||||
cy.get(
|
||||
'@invalidPathError',
|
||||
// Pleas note that the custom timeout is not checked explicitly checked, but asserting on
|
||||
// the payload (see the next cy.intercept) means asserting on it too
|
||||
{ timeout: 10000 }
|
||||
).should('not.exist');
|
||||
|
||||
// --------------------
|
||||
cy.get('[data-cy="Change Request Options"]').within(() => {
|
||||
cy.log('**--- Check the Preview of the Request URL Template**');
|
||||
cy.getBySel('transform-requestUrl-preview').should(
|
||||
cy.findByLabelText('Preview').should(
|
||||
'have.value',
|
||||
'https://hasura-actions-demo.glitch.me/login?name=login&id=5'
|
||||
);
|
||||
});
|
||||
|
||||
cy.log('**------------------------------**');
|
||||
cy.log('**--- Step 1.5: Invalid Path error**');
|
||||
cy.log('**--- Step 1.5: Add Payload Transform**');
|
||||
cy.log('**------------------------------**');
|
||||
|
||||
// --------------------
|
||||
@ -243,139 +171,81 @@ if (testMode !== 'cli') {
|
||||
// Assign an alias to the most unclear selectors for future references
|
||||
cy.get('textarea').eq(1).as('payloadTransformRequestBody');
|
||||
|
||||
// --------------------
|
||||
cy.log('**--- Type in the Payload Transform Request Body textarea**');
|
||||
cy.get('@payloadTransformRequestBody')
|
||||
.clearConsoleTextarea()
|
||||
// this second attempt tries to workaround a problem between Cypress and our text area.
|
||||
// In case the problem arises with other tests, it would be better off moving the double
|
||||
// clear to the clearConsoleTextarea command itself
|
||||
.wait(200)
|
||||
.clearConsoleTextarea()
|
||||
.type(
|
||||
`{
|
||||
"userInfo": {
|
||||
"name": {{$input.username}}
|
||||
`,
|
||||
{ force: true, delay: 1, parseSpecialCharSequences: false }
|
||||
);
|
||||
|
||||
// Due to the double server/cli mode behavior, we do not assert about the XHR request payload here
|
||||
|
||||
// --------------------
|
||||
cy.log('**--- Look for the "Invalid path" error**');
|
||||
cy.contains(
|
||||
`Invalid Path: "$input.username"`,
|
||||
// Pleas note that the custom timeout is not checked explicitly checked, but asserting on
|
||||
// the payload (see the next cy.intercept) means asserting on it too
|
||||
{ timeout: 10000 }
|
||||
)
|
||||
.as('invalidPathError')
|
||||
.should('be.visible');
|
||||
|
||||
cy.log('**------------------------------**');
|
||||
cy.log('**--- Step 1.6: Request Body add:**');
|
||||
cy.log('**------------------------------**');
|
||||
|
||||
// --------------------
|
||||
cy.log('**--- Type in the Payload Transform Request Body textarea**');
|
||||
cy.get('@payloadTransformRequestBody').clearConsoleTextarea().type(
|
||||
`{
|
||||
"userInfo": {
|
||||
"name": {{$body.input.username}},
|
||||
"password": {{$body.input.password}},
|
||||
"type": {{$body.action.name}}
|
||||
`,
|
||||
// delay is set to 1 because setting it to 0 causes the test to fail because writes
|
||||
// something like
|
||||
// "name": {{$body.input.username}}name
|
||||
// in the textarea (the closing "name" is a mistake)
|
||||
{ force: true, delay: 1, parseSpecialCharSequences: false }
|
||||
);
|
||||
|
||||
// Due to the double server/cli mode behavior, we do not assert about the XHR request payload here
|
||||
|
||||
// --------------------
|
||||
cy.log('**--- Check the error disappeared**');
|
||||
cy.get(
|
||||
'@invalidPathError',
|
||||
// Pleas note that the custom timeout is not checked explicitly checked, but asserting on
|
||||
// the payload (see the next cy.intercept) means asserting on it too
|
||||
{ timeout: 10000 }
|
||||
).should('not.exist');
|
||||
// delay is set to 1 because setting it to 0 causes the test to fail because writes
|
||||
// something like
|
||||
// "name": {{$body.input.username}}name
|
||||
// in the textarea (the closing "name" is a mistake)
|
||||
{ force: true, delay: 1, parseSpecialCharSequences: false }
|
||||
);
|
||||
});
|
||||
|
||||
// --------------------
|
||||
cy.log('**--- Click the Create button**');
|
||||
cy.getBySel('create-action-btn').click();
|
||||
|
||||
// Due to the double server/cli mode behavior, we do not assert about the XHR request payload here
|
||||
|
||||
// --------------------
|
||||
cy.log('**--- Check if the success notification is visible**');
|
||||
cy.get(
|
||||
'.notification',
|
||||
// The custom timeout aims to replace the lack of waiting for the outgoing request
|
||||
{ timeout: 10000 }
|
||||
)
|
||||
.should('be.visible')
|
||||
.and('contain', 'Created action successfully');
|
||||
cy.expectSuccessNotificationWithTitle('Created action successfully');
|
||||
|
||||
// TODO: check if it exists in the database? Other tests do that
|
||||
// -------------------------------------------------------------------------
|
||||
// see: https://github.com/hasura/graphql-engine-mono/issues/5433
|
||||
// The "Action change" part has been removed since it caused Cypress to crash
|
||||
// TODO: identify the crashing reason
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
cy.log('**------------------------------**');
|
||||
cy.log('**------------------------------**');
|
||||
cy.log('**------------------------------**');
|
||||
cy.log('**--- Step 2: Action change**');
|
||||
cy.log('**------------------------------**');
|
||||
cy.log('**------------------------------**');
|
||||
cy.log('**------------------------------**');
|
||||
// cy.log('**------------------------------**');
|
||||
// cy.log('**------------------------------**');
|
||||
// cy.log('**------------------------------**');
|
||||
// cy.log('**--- Step 2: Action change**');
|
||||
// cy.log('**------------------------------**');
|
||||
// cy.log('**------------------------------**');
|
||||
// cy.log('**------------------------------**');
|
||||
|
||||
// --------------------
|
||||
cy.log('**--- Wait all the requests to be settled**');
|
||||
waitForPostCreationRequests();
|
||||
// // --------------------
|
||||
// cy.log('**--- Wait all the requests to be settled**');
|
||||
// waitForPostCreationRequests();
|
||||
|
||||
cy.get('[data-cy="Change Request Options"]').within(() => {
|
||||
// --------------------
|
||||
cy.log('**--- Choose GET**');
|
||||
cy.contains('GET').click();
|
||||
// cy.get('[data-cy="Change Request Options"]').within(() => {
|
||||
// // --------------------
|
||||
// cy.log('**--- Choose GET**');
|
||||
// cy.contains('GET').click();
|
||||
|
||||
// --------------------
|
||||
cy.log('**--- Type in the Request URL Template field**');
|
||||
// // --------------------
|
||||
// cy.log('**--- Type in the Request URL Template field**');
|
||||
|
||||
cy.get('[placeholder="URL Template (Optional)..."]')
|
||||
.clearConsoleTextarea()
|
||||
.type('/{{$body.action.name}}/actions', {
|
||||
delay: 0,
|
||||
parseSpecialCharSequences: false,
|
||||
});
|
||||
// cy.get('[placeholder="URL Template (Optional)..."]')
|
||||
// .clearConsoleTextarea()
|
||||
// .type('/{{$body.action.name}}/actions', {
|
||||
// delay: 0,
|
||||
// parseSpecialCharSequences: false,
|
||||
// });
|
||||
|
||||
// --------------------
|
||||
cy.log('**--- Click on the first Remove Query Param button**');
|
||||
cy.getBySel('transform-query-params-kv-remove-button-0').click();
|
||||
});
|
||||
// // --------------------
|
||||
// cy.log('**--- Click on the first Remove Query Param button**');
|
||||
// cy.getBySel('transform-query-params-kv-remove-button-0').click();
|
||||
// });
|
||||
|
||||
// --------------------
|
||||
cy.log('**--- Click the Remove Payload Transform button**');
|
||||
cy.contains('Remove Payload Transform').click();
|
||||
// // --------------------
|
||||
// cy.log('**--- Click the Remove Payload Transform button**');
|
||||
// cy.contains('Remove Payload Transform').click();
|
||||
|
||||
// --------------------
|
||||
cy.log('**--- Click on the Save button**');
|
||||
cy.getBySel('save-modify-action-changes').click();
|
||||
// // --------------------
|
||||
// cy.log('**--- Click on the Save button**');
|
||||
// cy.getBySel('save-modify-action-changes').click();
|
||||
|
||||
// Due to the double server/cli mode behavior, we do not assert about the XHR request payload here
|
||||
|
||||
// --------------------
|
||||
cy.log('**--- Check if the success notification is visible**');
|
||||
cy.get(
|
||||
'.notification',
|
||||
// The custom timeout aims to replace the lack of waiting for the outgoing request
|
||||
{ timeout: 10000 }
|
||||
)
|
||||
.should('be.visible')
|
||||
.and('contain', 'Action saved successfully');
|
||||
|
||||
// TODO: check if it exists in the database? Other tests do that
|
||||
// // --------------------
|
||||
// cy.log('**--- Check if the success notification is visible**');
|
||||
// cy.expectSuccessNotificationWithTitle('Action saved successfully');
|
||||
|
||||
cy.log('**------------------------------**');
|
||||
cy.log('**------------------------------**');
|
||||
@ -385,17 +255,6 @@ if (testMode !== 'cli') {
|
||||
cy.log('**------------------------------**');
|
||||
cy.log('**------------------------------**');
|
||||
|
||||
// --------------------
|
||||
cy.log('**--- Reload the page**');
|
||||
// The purpose is to avoid the following notification when the Delete button will be clicked
|
||||
// -------------
|
||||
// Metadata is Out-of-Date
|
||||
// The operation failed as the metadata on the server is newer than what is currently loaded on the console. The metadata has to be re-fetched to continue editing it.
|
||||
// Do you want fetch the latest metadata?
|
||||
// Fetch metadata (button)
|
||||
// -------------
|
||||
cy.reload();
|
||||
|
||||
// --------------------
|
||||
cy.log('**--- Go the the action page**');
|
||||
cy.getBySel('actions-table-links').within(() => {
|
||||
@ -413,19 +272,9 @@ if (testMode !== 'cli') {
|
||||
cy.log('**--- Check the prompt has been called**');
|
||||
cy.window().its('prompt').should('be.called');
|
||||
|
||||
// Due to the double server/cli mode behavior, we do not assert about the XHR request payload here
|
||||
|
||||
// --------------------
|
||||
cy.log('**--- Check if the success notification is visible**');
|
||||
cy.get(
|
||||
'.notification',
|
||||
// The custom timeout aims to replace the lack of waiting for the outgoing request
|
||||
{ timeout: 10000 }
|
||||
)
|
||||
.should('be.visible')
|
||||
.and('contain', 'Action deleted successfully');
|
||||
|
||||
// TODO: check if it does not exist in the database? Other tests do that
|
||||
cy.expectSuccessNotificationWithTitle('Action deleted successfully');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -1,104 +0,0 @@
|
||||
/**
|
||||
* Wait for a bunch of requests to be settled before proceeding with the test.
|
||||
*
|
||||
* Alternatively, https://github.com/bahmutov/cypress-network-idle could be used
|
||||
*
|
||||
* This is a workaround for "element is 'detached' from the DOM" Cypress' error (see the issue
|
||||
* linked below). Since the UI gets re-rendered because of the requests, this utility ensures that
|
||||
* all the requests parallelly made by the UI are settled before proceeding with the test. Hance, it
|
||||
* ensure the UI won't re-render during the next interaction.
|
||||
*
|
||||
* What are the requests that must be awaited? By looking at the Cypress Test Runner, they are the
|
||||
* following, made parallelly or in a rapid series.
|
||||
* 1. export_metadata
|
||||
* 2. export_metadata
|
||||
* 3. export_metadata
|
||||
* 4. test_webhook_transform
|
||||
* 5. test_webhook_transform
|
||||
* 6. test_webhook_transform
|
||||
* 7. test_webhook_transform
|
||||
* At the moment of writing, I'm not sure the number of requests are fixed or not. If they are fixed,
|
||||
* using the cy.intercept `times` options would result in a more expressive and less convoluted code.
|
||||
*
|
||||
* To give you an overall idea, this is a timeline of the requests
|
||||
*
|
||||
* all requests start all requests end
|
||||
* | | | |
|
||||
* |--🚦🔴--1--2--3--4--5--6--7----------------------------1--2--3--4--5--6-7--🚦🟢--|
|
||||
*
|
||||
*
|
||||
* ATTENTION: Despite the defensive approach and the flakiness-removal purpose, this function could
|
||||
* introduced even more flakiness because of its empiric approach. In case of failures, it must be
|
||||
* carefully evaluated when/if keeping it or thinking about a better approach.
|
||||
* In generale, this solution does not scale, at should not be spread among the tests.
|
||||
*
|
||||
* @see https://github.com/cypress-io/cypress/issues/7306
|
||||
* @see https://glebbahmutov.com/blog/detached/
|
||||
* @see https://github.com/bahmutov/cypress-network-idle
|
||||
*/
|
||||
export function waitForPostCreationRequests() {
|
||||
let waitCompleted = false;
|
||||
|
||||
cy.log('*--- All requests must be settled*');
|
||||
|
||||
const pendingRequests = new Map();
|
||||
cy.intercept('POST', 'http://localhost:8080/v1/metadata', req => {
|
||||
if (waitCompleted) return;
|
||||
|
||||
Cypress.log({ message: '*--- Request pending*' });
|
||||
|
||||
pendingRequests.set(req, true);
|
||||
|
||||
req.continue(() => {
|
||||
Cypress.log({ message: '*--- Request settled*' });
|
||||
|
||||
pendingRequests.delete(req);
|
||||
});
|
||||
});
|
||||
|
||||
Cypress.log({ message: '*--- Waiting for the first request to start*' });
|
||||
|
||||
// Check if at least one request has been caught. This check must protect from the following case
|
||||
//
|
||||
// check requests start test failure, the requests got the UI re-rendered
|
||||
// | | |
|
||||
// |--🚦🔴----⚠️---🚦🟢-------1-2-3-4-5-6-7-1----------💥
|
||||
//
|
||||
// where checking that "there are no pending requests" falls in the false positive case where
|
||||
// there are no pending requests because no one started at all.
|
||||
//
|
||||
// The check runs every millisecond to be 100% sure that no request can escape (ex. because of a
|
||||
// super fast server). A false-negative case represented here
|
||||
//
|
||||
// requests start requests end check check test failure, no first request caught
|
||||
// | | | | | | |
|
||||
// |--🚦🔴--1-2-3-4-5-6-7-1-2-3-4-5-6-7--⚠️------------------⚠️------------------💥
|
||||
cy.waitUntil(() => pendingRequests.size > 0, {
|
||||
timeout: 5000, // 5 seconds is the default Cypress wait for a request to start
|
||||
interval: 1,
|
||||
errorMsg: 'No first request caught',
|
||||
});
|
||||
|
||||
Cypress.log({ message: '*--- Waiting for all the requests to start*' });
|
||||
|
||||
// Let pass some time to collect all the requests. Otherwise, it could detect that the first
|
||||
// request complete and go on with the test, even if another one will be performed in a while.
|
||||
//
|
||||
// This fixed wait protects from the following timeline
|
||||
//
|
||||
// 1st request start first request end other requests start test failure, the requests got the UI re-rendered
|
||||
// | | | |
|
||||
// |--🚦🔴---1---------------------1----🚦🟢----------------2-3-4-5-6-7-1----------💥
|
||||
//
|
||||
// Obviously, it is an empiric waiting, that also slows down the test.
|
||||
cy.wait(500);
|
||||
|
||||
Cypress.log({ message: '*--- Waiting for all the requests to be settled*' });
|
||||
|
||||
cy.waitUntil(() => pendingRequests.size === 0, {
|
||||
timeout: 30000, // 30 seconds is the default Cypress wait for the request to complete
|
||||
errorMsg: 'Some requests are not settled yet',
|
||||
}).then(() => {
|
||||
waitCompleted = true;
|
||||
});
|
||||
}
|
@ -14,8 +14,8 @@ export function loginActionMustNotExist() {
|
||||
);
|
||||
|
||||
if (actionExists) {
|
||||
Cypress.log({ message: '**--- The Action must be deleted**' }),
|
||||
deleteLoginAction();
|
||||
Cypress.log({ message: '**--- The Action must be deleted**' });
|
||||
deleteLoginAction();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -1,122 +0,0 @@
|
||||
import { readMetadata } from '../services/readMetadata';
|
||||
import { deleteLoginAction } from '../services/deleteLoginAction';
|
||||
|
||||
/**
|
||||
* Ensure the V1 Action exists.
|
||||
*/
|
||||
export function v1LoginActionMustExist() {
|
||||
Cypress.log({ message: '**--- Action check: start**' });
|
||||
|
||||
readMetadata().then(response => {
|
||||
const actionExists = !!response.body.actions?.find(
|
||||
// TODO: properly type it
|
||||
action => action.name === 'TODO:'
|
||||
);
|
||||
|
||||
if (actionExists) {
|
||||
Cypress.log({ message: '**--- The action exists**' });
|
||||
Cypress.log({ message: '**--- Action check: end**' });
|
||||
return;
|
||||
}
|
||||
|
||||
Cypress.log({ message: '**--- The action does not exist**' });
|
||||
|
||||
cy.request('POST', 'http://localhost:8080/v1/metadata', {
|
||||
type: 'bulk',
|
||||
source: 'default',
|
||||
args: [
|
||||
{
|
||||
type: 'set_custom_types',
|
||||
args: {
|
||||
scalars: [],
|
||||
input_objects: [
|
||||
{
|
||||
name: 'SampleInput',
|
||||
description: null,
|
||||
fields: [
|
||||
{
|
||||
name: 'username',
|
||||
type: 'String!',
|
||||
description: null,
|
||||
},
|
||||
{
|
||||
name: 'password',
|
||||
type: 'String!',
|
||||
description: null,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
objects: [
|
||||
{
|
||||
name: 'SampleOutput',
|
||||
description: null,
|
||||
fields: [
|
||||
{
|
||||
name: 'accessToken',
|
||||
type: 'String!',
|
||||
description: null,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'LoginResponse',
|
||||
fields: [
|
||||
{
|
||||
name: 'accessToken',
|
||||
type: 'String!',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
enums: [],
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'create_action',
|
||||
args: {
|
||||
name: 'v1Login',
|
||||
definition: {
|
||||
arguments: [
|
||||
{
|
||||
name: 'arg1',
|
||||
type: 'SampleInput!',
|
||||
description: null,
|
||||
},
|
||||
],
|
||||
kind: 'synchronous',
|
||||
output_type: 'SampleOutput',
|
||||
handler: 'http://host.docker.internal:3000',
|
||||
type: 'mutation',
|
||||
headers: [],
|
||||
timeout: null,
|
||||
request_transform: {
|
||||
version: 1,
|
||||
template_engine: 'Kriti',
|
||||
method: 'GET',
|
||||
url: '{{$base_url}}/users',
|
||||
query_params: {},
|
||||
body:
|
||||
'{\n "users": {\n "name": {{$body.input.arg1.username}}\n }\n}',
|
||||
content_type: 'application/json',
|
||||
},
|
||||
},
|
||||
comment: null,
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
.then(response => {
|
||||
expect(response.body, 'Response body exists').to.not.be.null;
|
||||
expect(response.body, 'Response body is an array').to.be.a('array');
|
||||
expect(
|
||||
response.body[0],
|
||||
'Response body contains success'
|
||||
).to.have.property('message', 'success');
|
||||
})
|
||||
.then(() => {
|
||||
Cypress.log({ message: '**--- The action has been created**' });
|
||||
Cypress.log({ message: '**--- Action check: end**' });
|
||||
});
|
||||
});
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
import { readMetadata } from '../services/readMetadata';
|
||||
import { deleteV1LoginAction } from '../services/deleteV1LoginAction';
|
||||
|
||||
/**
|
||||
* Ensure the Action does not exist.
|
||||
*/
|
||||
export function v1LoginActionMustNotExist() {
|
||||
Cypress.log({ message: '**--- Action check: start**' });
|
||||
|
||||
readMetadata().then(response => {
|
||||
const actionExists = !!response.body.actions?.find(
|
||||
// TODO: properly type it
|
||||
action => action.name === 'v1Login'
|
||||
);
|
||||
|
||||
if (actionExists) {
|
||||
Cypress.log({ message: '**--- The Action must be deleted**' }),
|
||||
deleteV1LoginAction();
|
||||
}
|
||||
});
|
||||
}
|
@ -1,100 +0,0 @@
|
||||
import { testMode } from '../../../helpers/common';
|
||||
|
||||
import { logMetadataRequests } from './utils/requests/logMetadataRequests';
|
||||
import { v1LoginActionMustExist } from './utils/testState/v1LoginActionMustExist';
|
||||
import { v1LoginActionMustNotExist } from './utils/testState/v1LoginActionMustNotExist';
|
||||
|
||||
if (testMode !== 'cli') {
|
||||
describe('V1 Actions with Transform', () => {
|
||||
before(() => {
|
||||
v1LoginActionMustExist();
|
||||
logMetadataRequests();
|
||||
|
||||
cy.visit('/actions/manage/v1Login/modify');
|
||||
});
|
||||
|
||||
after(() => {
|
||||
// Delete the created action, if any
|
||||
v1LoginActionMustNotExist();
|
||||
});
|
||||
|
||||
it('When the users edit a V1 Action with Transform, everything should work', () => {
|
||||
cy.log('**------------------------------**');
|
||||
cy.log('**------------------------------**');
|
||||
cy.log('**------------------------------**');
|
||||
cy.log('**--- Step 3: Mutation Action delete**');
|
||||
cy.log('**------------------------------**');
|
||||
cy.log('**------------------------------**');
|
||||
cy.log('**------------------------------**');
|
||||
|
||||
cy.get('[data-cy="Change Request Options"]').within(() => {
|
||||
// --------------------
|
||||
cy.log('**--- Choose POST**');
|
||||
cy.contains('POST').click();
|
||||
|
||||
// --------------------
|
||||
cy.log('**--- Type in the Request URL Template field**');
|
||||
cy.get('[placeholder="URL Template (Optional)..."]').type(
|
||||
'/{{$body.action.name}}/actions',
|
||||
{
|
||||
delay: 0,
|
||||
parseSpecialCharSequences: false,
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
// --------------------
|
||||
cy.log('**--- Click on the Save button**');
|
||||
cy.getBySel('save-modify-action-changes').click();
|
||||
|
||||
// --------------------
|
||||
cy.log('**--- Check if the success notification is visible**');
|
||||
cy.get(
|
||||
'.notification',
|
||||
// The custom timeout aims to replace the lack of waiting for the outgoing request
|
||||
{ timeout: 10000 }
|
||||
)
|
||||
.should('be.visible')
|
||||
.and('contain', 'Action saved successfully');
|
||||
|
||||
cy.log('**------------------------------**');
|
||||
cy.log('**------------------------------**');
|
||||
cy.log('**------------------------------**');
|
||||
cy.log('**--- Step 2: Action delete**');
|
||||
cy.log('**------------------------------**');
|
||||
cy.log('**------------------------------**');
|
||||
cy.log('**------------------------------**');
|
||||
|
||||
// --------------------
|
||||
cy.log('**--- Go the the action page**');
|
||||
cy.getBySel('actions-table-links').within(() => {
|
||||
cy.getBySel('v1Login').click();
|
||||
});
|
||||
|
||||
// --------------------
|
||||
cy.log('**--- Set the prompt value**');
|
||||
cy.window().then(win => cy.stub(win, 'prompt').returns('v1Login'));
|
||||
|
||||
cy.log('**--- Click the Delete button**');
|
||||
cy.getBySel('delete-action').click();
|
||||
|
||||
// --------------------
|
||||
cy.log('**--- Check the prompt has been called**');
|
||||
cy.window().its('prompt').should('be.called');
|
||||
|
||||
// Due to the double server/cli mode behavior, we do not assert about the XHR request payload here
|
||||
|
||||
// --------------------
|
||||
cy.log('**--- Check if the success notification is visible**');
|
||||
cy.get(
|
||||
'.notification',
|
||||
// The custom timeout aims to replace the lack of waiting for the outgoing request
|
||||
{ timeout: 10000 }
|
||||
)
|
||||
.should('be.visible')
|
||||
.and('contain', 'Action deleted successfully');
|
||||
|
||||
// TODO: check if it does not exist in the database? Other tests do that
|
||||
});
|
||||
});
|
||||
}
|
@ -12,7 +12,9 @@ import { setMetaData } from '../../validators/validators';
|
||||
import { testMode } from '../../../helpers/common';
|
||||
|
||||
const setup = () => {
|
||||
describe('Setup route', () => {
|
||||
// Temporarily skipped because of its flakiness, see: https://github.com/hasura/graphql-engine-mono/issues/5433
|
||||
// TODO: Fix and restore it
|
||||
describe.skip('Setup route', () => {
|
||||
it('Visit the index route', () => {
|
||||
// Visit the index route
|
||||
cy.visit('/');
|
||||
@ -23,7 +25,9 @@ const setup = () => {
|
||||
};
|
||||
|
||||
export const runApiExplorerTests = () => {
|
||||
describe('API Explorer', () => {
|
||||
// Temporarily skipped because of its flakiness, see: https://github.com/hasura/graphql-engine-mono/issues/5433
|
||||
// TODO: Fix and restore it
|
||||
describe.skip('API Explorer', () => {
|
||||
it('Create test table', createTestTable);
|
||||
it('Insert row into test table', insertValue);
|
||||
it('Open API Explorer', openAPIExplorer);
|
||||
|
@ -62,9 +62,8 @@ const checkQuerySuccess = () => {
|
||||
const checkOrder = (order: string) => {
|
||||
// Utility function to get right element
|
||||
|
||||
const curElement = cy.get('[role=row]');
|
||||
if (order === 'asc') {
|
||||
curElement.each(($el, index) => {
|
||||
cy.get('[role=row]').each(($el, index) => {
|
||||
if (index !== 0) {
|
||||
cy.wrap($el)
|
||||
.find('[role=gridcell]')
|
||||
@ -75,7 +74,7 @@ const checkOrder = (order: string) => {
|
||||
}
|
||||
});
|
||||
} else {
|
||||
curElement.each(($el, index) => {
|
||||
cy.get('[role=row]').each(($el, index) => {
|
||||
if (index !== 0) {
|
||||
cy.wrap($el)
|
||||
.find('[role=gridcell]')
|
||||
|
@ -24,7 +24,9 @@ import { setMetaData } from '../../validators/validators';
|
||||
import { getIndexRoute } from '../../../helpers/dataHelpers';
|
||||
|
||||
const setup = () => {
|
||||
describe('Setup route', () => {
|
||||
// Temporarily skipped because of its flakiness, see: https://github.com/hasura/graphql-engine-mono/issues/5433
|
||||
// TODO: Fix and restore it
|
||||
describe.skip('Setup route', () => {
|
||||
it('Visit the index route', () => {
|
||||
cy.visit(getIndexRoute());
|
||||
// Get and set validation metadata
|
||||
@ -34,7 +36,9 @@ const setup = () => {
|
||||
};
|
||||
|
||||
export const runInsertBrowseTests = () => {
|
||||
describe('Table: Browse and Insert', () => {
|
||||
// Temporarily skipped because of its flakiness, see: https://github.com/hasura/graphql-engine-mono/issues/5433
|
||||
// TODO: Fix and restore it
|
||||
describe.skip('Table: Browse and Insert', () => {
|
||||
it('Create a table with fields of all data types', passBICreateTable);
|
||||
it('Search for tables', passSearchTables);
|
||||
it('Check Insert Route', checkInsertRoute);
|
||||
|
@ -14,7 +14,9 @@ import {
|
||||
} from './postgres.spec';
|
||||
|
||||
const connectPgDatabaseFormTests = () => {
|
||||
describe('Add a database via connect form', () => {
|
||||
// Temporarily skipped because of its flakiness, see: https://github.com/hasura/graphql-engine-mono/issues/5433
|
||||
// TODO: Fix and restore it
|
||||
describe.skip('Add a database via connect form', () => {
|
||||
describe('can successfully add', () => {
|
||||
describe('a postgres database', () => {
|
||||
it('using a connection string', () => {
|
||||
@ -135,7 +137,9 @@ const connectPgDatabaseFormTests = () => {
|
||||
};
|
||||
|
||||
const manageDatabasesPageTests = () => {
|
||||
describe('Connected Databases list page', () => {
|
||||
// Temporarily skipped because of its flakiness, see: https://github.com/hasura/graphql-engine-mono/issues/5433
|
||||
// TODO: Fix and restore it
|
||||
describe.skip('Connected Databases list page', () => {
|
||||
it('can successfully remove db', () => {
|
||||
cy.log('**--- Create database**');
|
||||
createDB('db_for_removal');
|
||||
|
@ -299,9 +299,8 @@ export const passVFilterQueryEq = () => {
|
||||
|
||||
const checkOrder = (order: string) => {
|
||||
// Utility function to get right element
|
||||
const curElement = cy.get('[role=row]');
|
||||
if (order === 'asc') {
|
||||
curElement.each(($el, index) => {
|
||||
cy.get('[role=row]').each(($el, index) => {
|
||||
if (index === 1) {
|
||||
cy.wrap($el).find('[role=gridcell]').first().next().next().contains(2);
|
||||
}
|
||||
@ -315,7 +314,7 @@ const checkOrder = (order: string) => {
|
||||
}
|
||||
});
|
||||
} else {
|
||||
curElement.each(($el, index) => {
|
||||
cy.get('[role=row]').each(($el, index) => {
|
||||
if (index === 2) {
|
||||
cy.wrap($el).find('[role=gridcell]').first().next().next().contains(2);
|
||||
}
|
||||
|
@ -17,7 +17,9 @@ import { setMetaData } from '../../validators/validators';
|
||||
import { getIndexRoute } from '../../../helpers/dataHelpers';
|
||||
|
||||
const setup = () => {
|
||||
describe('Setup route', () => {
|
||||
// Temporarily skipped because of its flakiness, see: https://github.com/hasura/graphql-engine-mono/issues/5433
|
||||
// TODO: Fix and restore it
|
||||
describe.skip('Setup route', () => {
|
||||
it('Visit the index route', () => {
|
||||
// Visit the index route
|
||||
cy.visit(getIndexRoute());
|
||||
@ -28,7 +30,9 @@ const setup = () => {
|
||||
};
|
||||
|
||||
export const runMaterializedViewsTest = () => {
|
||||
describe('Materialized Views', () => {
|
||||
// Temporarily skipped because of its flakiness, see: https://github.com/hasura/graphql-engine-mono/issues/5433
|
||||
// TODO: Fix and restore it
|
||||
describe.skip('Materialized Views', () => {
|
||||
it('Create Tables', passVCreateTables);
|
||||
it('Add data to table', passVAddData);
|
||||
it('Create MaterializedView', passVCreateMaterializedViews);
|
||||
|
@ -15,7 +15,9 @@ import { setMetaData } from '../../validators/validators';
|
||||
import { getIndexRoute } from '../../../helpers/dataHelpers';
|
||||
|
||||
const setup = () => {
|
||||
describe('Check Data Tab', () => {
|
||||
// Temporarily skipped because of its flakiness, see: https://github.com/hasura/graphql-engine-mono/issues/5433
|
||||
// TODO: Fix and restore it
|
||||
describe.skip('Check Data Tab', () => {
|
||||
it('Visiting the data URL opens the correct route', () => {
|
||||
// Visit the index route
|
||||
cy.visit(getIndexRoute());
|
||||
@ -26,7 +28,9 @@ const setup = () => {
|
||||
};
|
||||
|
||||
export const runPermissionsTests = () => {
|
||||
describe('Permissions', () => {
|
||||
describe.skip('Permissions', () => {
|
||||
// Temporarily skipped because of its flakiness, see: https://github.com/hasura/graphql-engine-mono/issues/5433
|
||||
// TODO: Fix and restore it
|
||||
it('Create a table', passPTCreateTable);
|
||||
it('Create a view', passPVCreateView);
|
||||
it('Check permission route', passPTCheckRoute);
|
||||
|
@ -7,18 +7,15 @@ import {
|
||||
passRTAddSuggestedRel,
|
||||
failRTAddSuggestedRel,
|
||||
passRTRenameRelationship,
|
||||
passRSTAddRSRel,
|
||||
passRSTDeleteRSRel,
|
||||
passRSTSetup,
|
||||
passRSTReset,
|
||||
} from './spec';
|
||||
import { testMode } from '../../../helpers/common';
|
||||
import { setMetaData } from '../../validators/validators';
|
||||
import { getIndexRoute } from '../../../helpers/dataHelpers';
|
||||
import { postgres } from '../manage-database/postgres.spec';
|
||||
|
||||
const setup = () => {
|
||||
describe('Check Data Tab', () => {
|
||||
// Temporarily skipped because of its flakiness, see: https://github.com/hasura/graphql-engine-mono/issues/5433
|
||||
// TODO: Fix and restore it
|
||||
describe.skip('Check Data Tab', () => {
|
||||
it('Clicking on Data tab opens the correct route', () => {
|
||||
cy.visit(getIndexRoute());
|
||||
// Get and set validation metadata
|
||||
@ -28,7 +25,9 @@ const setup = () => {
|
||||
};
|
||||
|
||||
export const runRelationshipsTests = () => {
|
||||
describe('Relationships Tests', () => {
|
||||
// Temporarily skipped because of its flakiness, see: https://github.com/hasura/graphql-engine-mono/issues/5433
|
||||
// TODO: Fix and restore it
|
||||
describe.skip('Relationships Tests', () => {
|
||||
it('Create testing tables', passRTCreateTables);
|
||||
it('Add Manual Relationship Object', passRTAddManualObjRel);
|
||||
it('Add Manual Relationship Array', passRTAddManualArrayRel);
|
||||
@ -41,33 +40,7 @@ export const runRelationshipsTests = () => {
|
||||
});
|
||||
};
|
||||
|
||||
export const remoteRelationshipTests = () => {
|
||||
const drivers = [postgres];
|
||||
|
||||
describe('Remote schema relationships tests', () => {
|
||||
drivers.forEach(driver => {
|
||||
describe(`for ${driver.name}`, () => {
|
||||
// test setup
|
||||
before(() => {
|
||||
driver.helpers.createRemoteSchema('remote_rel_test_rs');
|
||||
});
|
||||
|
||||
it('Create testing tables', passRSTSetup);
|
||||
it('Adds a relationship', passRSTAddRSRel);
|
||||
it('Deletes a relationship', passRSTDeleteRSRel);
|
||||
it('Delete testing tables', passRSTReset);
|
||||
|
||||
// clean up
|
||||
after(() => {
|
||||
driver.helpers.deleteRemoteSchema('remote_rel_test_rs');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
if (testMode !== 'cli') {
|
||||
setup();
|
||||
runRelationshipsTests();
|
||||
remoteRelationshipTests();
|
||||
}
|
||||
|
@ -16,12 +16,10 @@ export const runSchemaSharingTests = () => {
|
||||
describe('template gallery', () => {
|
||||
it('display content', () => {
|
||||
cy.get('[data-test=table-links]').contains('default').click();
|
||||
const oneToOne = cy.get('table').contains('Relationships: One-to-One');
|
||||
oneToOne.click();
|
||||
cy.get('table').contains('Relationships: One-to-One').click();
|
||||
cy.contains('Install Template').click();
|
||||
cy.wait(1000);
|
||||
const installed = cy.get('[data-test=table-links]').contains('_onetoone');
|
||||
installed.click();
|
||||
cy.get('[data-test=table-links]').contains('_onetoone').click();
|
||||
setPromptValue('_onetoone');
|
||||
cy.contains('_onetoone').parent().parent().contains('owner');
|
||||
cy.contains('_onetoone').parent().parent().contains('passport_info');
|
||||
|
@ -291,9 +291,8 @@ export const passVFilterQueryEq = () => {
|
||||
|
||||
const checkOrder = (order: string) => {
|
||||
// Utility function to get right element
|
||||
const curElement = cy.get('[role=row]');
|
||||
if (order === 'asc') {
|
||||
curElement.each(($el, index) => {
|
||||
cy.get('[role=row]').each(($el, index) => {
|
||||
if (index === 1) {
|
||||
cy.wrap($el).find('[role=gridcell]').first().next().next().contains(2);
|
||||
}
|
||||
@ -307,7 +306,7 @@ const checkOrder = (order: string) => {
|
||||
}
|
||||
});
|
||||
} else {
|
||||
curElement.each(($el, index) => {
|
||||
cy.get('[role=row]').each(($el, index) => {
|
||||
if (index === 2) {
|
||||
cy.wrap($el).find('[role=gridcell]').first().next().next().contains(2);
|
||||
}
|
||||
|
@ -17,7 +17,9 @@ import { setMetaData } from '../../validators/validators';
|
||||
import { getIndexRoute } from '../../../helpers/dataHelpers';
|
||||
|
||||
const setup = () => {
|
||||
describe('Setup route', () => {
|
||||
// Temporarily skipped because of its flakiness, see: https://github.com/hasura/graphql-engine-mono/issues/5433
|
||||
// TODO: Fix and restore it
|
||||
describe.skip('Setup route', () => {
|
||||
it('Visit the index route', () => {
|
||||
// Visit the index route
|
||||
cy.visit(getIndexRoute());
|
||||
@ -28,7 +30,9 @@ const setup = () => {
|
||||
};
|
||||
|
||||
export const runViewsTest = () => {
|
||||
describe('Views', () => {
|
||||
// Temporarily skipped because of its flakiness, see: https://github.com/hasura/graphql-engine-mono/issues/5433
|
||||
// TODO: Fix and restore it
|
||||
describe.skip('Views', () => {
|
||||
// NOTE: Ideally, we should be adding "should" at the beginning of
|
||||
// the test descriptions. It will sound like this when you read it.
|
||||
// eg. it should create test tables ...and so on
|
||||
|
@ -1,5 +1,4 @@
|
||||
/* eslint no-unused-vars: 0 */
|
||||
/* eslint import/prefer-default-export: 0 */
|
||||
import { testMode } from '../../../helpers/common';
|
||||
import { setMetaData } from '../../validators/validators';
|
||||
|
||||
@ -20,7 +19,9 @@ import {
|
||||
import { getIndexRoute } from '../../../helpers/dataHelpers';
|
||||
|
||||
const setup = () => {
|
||||
describe('Check Data Tab', () => {
|
||||
// Temporarily skipped because of its flakiness, see: https://github.com/hasura/graphql-engine-mono/issues/5433
|
||||
// TODO: Fix and restore it
|
||||
describe.skip('Check Data Tab', () => {
|
||||
it('Clicking on Data tab opens the correct route', () => {
|
||||
// Visit the index route
|
||||
cy.visit(getIndexRoute());
|
||||
@ -31,7 +32,9 @@ const setup = () => {
|
||||
};
|
||||
|
||||
export const runCreateTriggerTests = () => {
|
||||
describe('Create Trigger', () => {
|
||||
// Temporarily skipped because of its flakiness, see: https://github.com/hasura/graphql-engine-mono/issues/5433
|
||||
// TODO: Fix and restore it
|
||||
describe.skip('Create Trigger', () => {
|
||||
it('Create test table', passPTCreateTable);
|
||||
it(
|
||||
'Create trigger button opens the correct route',
|
||||
|
@ -1,5 +1,4 @@
|
||||
/* eslint no-unused-vars: 0 */
|
||||
/* eslint import/prefer-default-export: 0 */
|
||||
import { testMode } from '../../../helpers/common';
|
||||
import { setMetaData } from '../../validators/validators';
|
||||
|
||||
@ -21,7 +20,9 @@ import {
|
||||
} from './spec';
|
||||
|
||||
const setup = () => {
|
||||
describe('Setup route', () => {
|
||||
// Temporarily skipped because of its flakiness, see: https://github.com/hasura/graphql-engine-mono/issues/5433
|
||||
// TODO: Fix and restore it
|
||||
describe.skip('Setup route', () => {
|
||||
it('Visit the index route', () => {
|
||||
// Visit the index route
|
||||
cy.visit('/remote-schemas/manage/schemas');
|
||||
@ -32,7 +33,9 @@ const setup = () => {
|
||||
};
|
||||
|
||||
export const runCreateRemoteSchemaTableTests = () => {
|
||||
describe('Create Remote Schema', () => {
|
||||
// Temporarily skipped because of its flakiness, see: https://github.com/hasura/graphql-engine-mono/issues/5433
|
||||
// TODO: Fix and restore it
|
||||
describe.skip('Create Remote Schema', () => {
|
||||
it(
|
||||
'Add remote schema button opens the correct route',
|
||||
checkCreateRemoteSchemaRoute
|
||||
|
@ -1,5 +1,4 @@
|
||||
/* eslint no-unused-vars: 0 */
|
||||
/* eslint import/prefer-default-export: 0 */
|
||||
import { testMode } from '../../../helpers/common';
|
||||
import { setMetaData } from '../../validators/validators';
|
||||
import { modifyCustomization } from './spec';
|
||||
|
@ -1,11 +1,13 @@
|
||||
import { getElementFromAlias } from '../../../helpers/eventHelpers';
|
||||
import { replaceMetadata, resetMetadata } from '../../../helpers/metadata';
|
||||
import { postgres } from '../../data/manage-database/postgres.spec';
|
||||
// import { postgres } from '../../data/manage-database/postgres.spec';
|
||||
|
||||
describe('check if remote schema relationships are displayed properly', () => {
|
||||
// Temporarily skipped because of its flakiness, see: https://github.com/hasura/graphql-engine-mono/issues/5433
|
||||
// TODO: Fix and restore it
|
||||
describe.skip('check if remote schema relationships are displayed properly', () => {
|
||||
before(() => {
|
||||
// create a table called destination_table
|
||||
postgres.helpers.createTable('destination_table');
|
||||
// postgres.helpers.createTable('destination_table');
|
||||
|
||||
// load stuff into the metadata
|
||||
replaceMetadata({
|
||||
@ -119,6 +121,6 @@ describe('check if remote schema relationships are displayed properly', () => {
|
||||
resetMetadata();
|
||||
|
||||
// delete the table
|
||||
postgres.helpers.deleteTable('destination_table');
|
||||
// postgres.helpers.deleteTable('destination_table');
|
||||
});
|
||||
});
|
||||
|
@ -1,11 +1,13 @@
|
||||
import { getElementFromAlias } from '../../../helpers/eventHelpers';
|
||||
import { replaceMetadata, resetMetadata } from '../../../helpers/metadata';
|
||||
import { postgres } from '../../data/manage-database/postgres.spec';
|
||||
// import { postgres } from '../../data/manage-database/postgres.spec';
|
||||
|
||||
describe('check if remote schema to db relationships are created properly', () => {
|
||||
// Temporarily skipped because of its flakiness, see: https://github.com/hasura/graphql-engine-mono/issues/5433
|
||||
// TODO: Fix and restore it
|
||||
describe.skip('check if remote schema to db relationships are created properly', () => {
|
||||
before(() => {
|
||||
// create a table called destination_table
|
||||
postgres.helpers.createTable('destination_table');
|
||||
// postgres.helpers.createTable('destination_table');
|
||||
|
||||
// load stuff into the metadata
|
||||
replaceMetadata({
|
||||
@ -85,6 +87,6 @@ describe('check if remote schema to db relationships are created properly', () =
|
||||
resetMetadata();
|
||||
|
||||
// delete the table
|
||||
postgres.helpers.deleteTable('destination_table');
|
||||
// postgres.helpers.deleteTable('destination_table');
|
||||
});
|
||||
});
|
||||
|
@ -1,10 +1,12 @@
|
||||
import { getElementFromAlias } from '../../../helpers/eventHelpers';
|
||||
import { replaceMetadata, resetMetadata } from '../../../helpers/metadata';
|
||||
import type { HasuraMetadataV3 } from '../../../../src/metadata/types';
|
||||
|
||||
describe('check if remote schema to db relationships are created properly', () => {
|
||||
// Temporarily skipped because of its flakiness, see: https://github.com/hasura/graphql-engine-mono/issues/5433
|
||||
// TODO: Fix and restore it
|
||||
describe.skip('check if remote schema to db relationships are created properly', () => {
|
||||
before(() => {
|
||||
// load stuff into the metadata
|
||||
replaceMetadata({
|
||||
const body: HasuraMetadataV3 = {
|
||||
version: 3,
|
||||
sources: [
|
||||
{
|
||||
@ -46,7 +48,10 @@ describe('check if remote schema to db relationships are created properly', () =
|
||||
comment: '',
|
||||
},
|
||||
],
|
||||
});
|
||||
inherited_roles: [],
|
||||
};
|
||||
// load stuff into the metadata
|
||||
replaceMetadata(body);
|
||||
});
|
||||
|
||||
it('should create a new rs-to-rs relationship from source field', () => {
|
||||
|
@ -24,7 +24,6 @@
|
||||
// -- This is will overwrite an existing command --
|
||||
// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... })
|
||||
|
||||
import 'cypress-wait-until';
|
||||
import '@testing-library/cypress/add-commands';
|
||||
|
||||
import './visitEmptyPage';
|
||||
|
@ -7,7 +7,7 @@ import type {
|
||||
import { checkAndGetTestInfo } from './helpers/checkAndGetTestInfo';
|
||||
import { generateEmptyTestState } from './helpers/generateEmptyTestState';
|
||||
|
||||
let runningTestState: RunningTestsState = {};
|
||||
const runningTestState: RunningTestsState = {};
|
||||
|
||||
/**
|
||||
* A wrapper around `cy.intercept` that allows intercepting and recording the request/response series
|
||||
@ -58,7 +58,7 @@ function startContractIntercept(
|
||||
const fixtureName = createFixtureName(request);
|
||||
if (fixtureName.includes('\\') || fixtureName.includes('/')) {
|
||||
throw new Error(
|
||||
`createFixtureName cannot return names that includes / or \ like ${fixtureName}`
|
||||
`createFixtureName cannot return names that includes / or \\ like ${fixtureName}`
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,9 @@
|
||||
* thisTest: this.test,
|
||||
* // ...
|
||||
*/
|
||||
export function throwIfCalledInsideArrowFunction(thisTest: Mocha.Context | {}) {
|
||||
export function throwIfCalledInsideArrowFunction(
|
||||
thisTest: Mocha.Context | Record<string, unknown>
|
||||
) {
|
||||
if (Object.keys(thisTest).length === 0) {
|
||||
throw new Error(
|
||||
'interceptAndRecordContract did not receive `this` that refers to the test itself. Have you called interceptAndRecordContract inside an arrow function? If yes, transform function into a regular one'
|
||||
|
@ -1,39 +1,33 @@
|
||||
Cypress.Commands.add('expectSuccessNotification', () => {
|
||||
const el = cy.get('.notification-success');
|
||||
el.should('be.visible');
|
||||
cy.get('.notification-success').should('be.visible');
|
||||
});
|
||||
|
||||
Cypress.Commands.add('expectSuccessNotificationWithTitle', (title: string) => {
|
||||
const el = cy.get('.notification-success');
|
||||
el.should('be.visible');
|
||||
el.should('contain', title);
|
||||
cy.get('.notification-success').should('be.visible').should('contain', title);
|
||||
});
|
||||
|
||||
Cypress.Commands.add(
|
||||
'expectSuccessNotificationWithMessage',
|
||||
(message: string) => {
|
||||
const el = cy.get('.notification-success');
|
||||
el.should('be.visible');
|
||||
el.should('contain', message);
|
||||
cy.get('.notification-success')
|
||||
.should('be.visible')
|
||||
.should('contain', message);
|
||||
}
|
||||
);
|
||||
|
||||
Cypress.Commands.add('expectErrorNotification', () => {
|
||||
const el = cy.get('.notification-error');
|
||||
el.should('be.visible');
|
||||
cy.get('.notification-error').should('be.visible');
|
||||
});
|
||||
|
||||
Cypress.Commands.add('expectErrorNotificationWithTitle', (title: string) => {
|
||||
const el = cy.get('.notification-error');
|
||||
el.should('be.visible');
|
||||
el.should('contain', title);
|
||||
cy.get('.notification-error').should('be.visible').should('contain', title);
|
||||
});
|
||||
|
||||
Cypress.Commands.add(
|
||||
'expectErrorNotificationWithMessage',
|
||||
(message: string) => {
|
||||
const el = cy.get('.notification-error');
|
||||
el.should('be.visible');
|
||||
el.should('contain', message);
|
||||
cy.get('.notification-error')
|
||||
.should('be.visible')
|
||||
.should('contain', message);
|
||||
}
|
||||
);
|
||||
|
@ -1,4 +1,4 @@
|
||||
import nodePath from 'node:path';
|
||||
import * as nodePath from 'node:path';
|
||||
|
||||
interface Options {
|
||||
path: string[];
|
||||
|
@ -1,4 +1,4 @@
|
||||
import fs from 'fs';
|
||||
import * as fs from 'fs';
|
||||
|
||||
interface Options {
|
||||
dir: string;
|
||||
|
@ -1,4 +1,4 @@
|
||||
import nodePath from 'node:path';
|
||||
import * as nodePath from 'node:path';
|
||||
|
||||
interface Options {
|
||||
path: string;
|
||||
|
@ -1,4 +1,4 @@
|
||||
import fs from 'fs';
|
||||
import * as fs from 'fs';
|
||||
|
||||
interface Options {
|
||||
file: string;
|
||||
|
@ -6,7 +6,7 @@
|
||||
"baseUrl": "../node_modules",
|
||||
"target": "es5",
|
||||
"lib": ["es2015", "dom"],
|
||||
"types": ["cypress", "cypress-wait-until", "@testing-library/cypress"]
|
||||
"types": ["cypress", "@testing-library/cypress"]
|
||||
},
|
||||
"include": ["**/*.ts"]
|
||||
}
|
||||
|
14
console/package-lock.json
generated
14
console/package-lock.json
generated
@ -181,7 +181,7 @@
|
||||
"concurrently": "5.2.0",
|
||||
"cross-env": "7.0.2",
|
||||
"css-loader": "3.5.3",
|
||||
"cypress": "^10.3.0",
|
||||
"cypress": "^10.4.0",
|
||||
"cypress-wait-until": "^1.7.2",
|
||||
"dedent": "0.7.0",
|
||||
"dotenv": "5.0.1",
|
||||
@ -17814,9 +17814,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/cypress": {
|
||||
"version": "10.3.0",
|
||||
"resolved": "https://registry.npmjs.org/cypress/-/cypress-10.3.0.tgz",
|
||||
"integrity": "sha512-txkQWKzvBVnWdCuKs5Xc08gjpO89W2Dom2wpZgT9zWZT5jXxqPIxqP/NC1YArtkpmp3fN5HW8aDjYBizHLUFvg==",
|
||||
"version": "10.4.0",
|
||||
"resolved": "https://registry.npmjs.org/cypress/-/cypress-10.4.0.tgz",
|
||||
"integrity": "sha512-OM7F8MRE01SHQRVVzunid1ZK1m90XTxYnl+7uZfIrB4CYqUDCrZEeSyCXzIbsS6qcaijVCAhqDL60SxG8N6hew==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
@ -55571,9 +55571,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"cypress": {
|
||||
"version": "10.3.0",
|
||||
"resolved": "https://registry.npmjs.org/cypress/-/cypress-10.3.0.tgz",
|
||||
"integrity": "sha512-txkQWKzvBVnWdCuKs5Xc08gjpO89W2Dom2wpZgT9zWZT5jXxqPIxqP/NC1YArtkpmp3fN5HW8aDjYBizHLUFvg==",
|
||||
"version": "10.4.0",
|
||||
"resolved": "https://registry.npmjs.org/cypress/-/cypress-10.4.0.tgz",
|
||||
"integrity": "sha512-OM7F8MRE01SHQRVVzunid1ZK1m90XTxYnl+7uZfIrB4CYqUDCrZEeSyCXzIbsS6qcaijVCAhqDL60SxG8N6hew==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@cypress/request": "^2.88.10",
|
||||
|
@ -27,8 +27,8 @@
|
||||
"--- TEST ------------------------------------------------": "",
|
||||
"test": "cypress run --spec 'cypress/integration/**/**/test.ts' --key $CYPRESS_KEY --parallel --record",
|
||||
"--- CYPRESS ------------------------------------------------": "",
|
||||
"cy:open": "cypress open --config-file cypress-local.config.ts",
|
||||
"cy:run": "cypress run --config-file cypress-local.config.ts",
|
||||
"cy:open": "cypress open",
|
||||
"cy:run": "cypress run",
|
||||
"cy:run:ci": "cypress run --key $CYPRESS_KEY --ci-build-id $BUILDKITE_BUILD_ID --parallel --record",
|
||||
"--- JEST ------------------------------------------------": "",
|
||||
"jest": "jest --setupFiles dotenv/config",
|
||||
@ -235,8 +235,7 @@
|
||||
"concurrently": "5.2.0",
|
||||
"cross-env": "7.0.2",
|
||||
"css-loader": "3.5.3",
|
||||
"cypress": "^10.3.0",
|
||||
"cypress-wait-until": "^1.7.2",
|
||||
"cypress": "^10.4.0",
|
||||
"dedent": "0.7.0",
|
||||
"dotenv": "5.0.1",
|
||||
"eslint": "6.8.0",
|
||||
|
@ -3,6 +3,7 @@
|
||||
exports[`update metadata in cache 1`] = `
|
||||
Object {
|
||||
"metadata": Object {
|
||||
"inherited_roles": Array [],
|
||||
"sources": Array [
|
||||
Object {
|
||||
"configuration": Object {
|
||||
|
@ -1,14 +1,13 @@
|
||||
import { allowedMetadataTypes } from '../../../MetadataAPI';
|
||||
import type { InsertBodyResult } from '../api';
|
||||
import { updateTablePermission } from '../cache';
|
||||
import { metadata } from '../../mocks/dataStubs';
|
||||
|
||||
const data = {
|
||||
type: 'bulk' as allowedMetadataTypes,
|
||||
source: 'default',
|
||||
const data: InsertBodyResult = {
|
||||
type: 'bulk',
|
||||
resource_version: 30,
|
||||
args: [
|
||||
{
|
||||
type: 'pg_create_insert_permission' as allowedMetadataTypes,
|
||||
type: 'pg_create_insert_permission',
|
||||
args: {
|
||||
table: {
|
||||
name: 'users',
|
||||
|
@ -108,7 +108,7 @@ interface CreateInsertBodyArgs extends CreateBodyArgs {
|
||||
existingPermissions: any;
|
||||
}
|
||||
|
||||
interface InsertBodyResult {
|
||||
export interface InsertBodyResult {
|
||||
type: allowedMetadataTypes;
|
||||
resource_version: number;
|
||||
args: Record<string, any>[];
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { HasuraMetadataV3 } from '@/metadata/types';
|
||||
import { MetadataResponse } from '../../MetadataAPI';
|
||||
|
||||
export const schemaList = {
|
||||
result_type: 'TuplesOk',
|
||||
@ -15,9 +15,10 @@ export const query = {
|
||||
],
|
||||
};
|
||||
|
||||
export const metadata = {
|
||||
export const metadata: MetadataResponse = {
|
||||
resource_version: 30,
|
||||
metadata: {
|
||||
inherited_roles: [],
|
||||
version: 3,
|
||||
sources: [
|
||||
{
|
||||
@ -67,5 +68,5 @@ export const metadata = {
|
||||
},
|
||||
},
|
||||
],
|
||||
} as HasuraMetadataV3,
|
||||
},
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user