Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add cypress tests for collections #5748

Open
wants to merge 53 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
e4b09bd
add query builder for laboratory
dimaMachina Jun 26, 2024
3bdcab2
temp
dimaMachina Jun 26, 2024
a455613
fix
dimaMachina Jun 28, 2024
aa5ecb8
fix
dimaMachina Jun 28, 2024
db6f984
pnpm
dimaMachina Jun 28, 2024
1362231
Merge branch 'main' into add-graphiql-explorer2
dimaMachina Jun 28, 2024
24c1f7f
Merge branch 'main' into add-graphiql-explorer2
dimaMachina Jul 1, 2024
97414e1
use stable version of `@graphiql/plugin-explorer`, update graphiql
dimaMachina Jul 1, 2024
06c2ecc
Merge branch 'main' into explorer3
dimaMachina Aug 19, 2024
5c8b2f0
refactor use-operation-collections-plugin.tsx
dimaMachina Aug 19, 2024
1e1dd05
more
dimaMachina Aug 19, 2024
6c6fc1d
more refactoring
dimaMachina Aug 19, 2024
0b48243
update explorer
dimaMachina Aug 20, 2024
7f0025e
undo rename to have less diff changes
dimaMachina Aug 20, 2024
23fe786
- [ ] remove custom prebuild `rss-generator.ts` script
dimaMachina Aug 20, 2024
fc3966c
fix types
dimaMachina Aug 20, 2024
9276cb7
move `theme.config.tsx` to src
dimaMachina Aug 20, 2024
770a158
more product updates work
dimaMachina Aug 20, 2024
3f17764
prettify
dimaMachina Aug 20, 2024
06d5b96
more
dimaMachina Aug 20, 2024
816f92a
more
dimaMachina Aug 20, 2024
257860c
prettier
dimaMachina Aug 20, 2024
f06fed4
grammarly
dimaMachina Aug 20, 2024
e9ffc80
prettify
dimaMachina Aug 20, 2024
2110c7d
add eslint-disable-next-line
dimaMachina Aug 20, 2024
6fbdd04
update date
dimaMachina Aug 20, 2024
f942172
polish
dimaMachina Aug 20, 2024
0c3a9f9
apply review
dimaMachina Aug 21, 2024
d20f454
replace I with we
dimaMachina Aug 21, 2024
d3a66bc
remove mention of `plugin` in `Operations collections plugin`
dimaMachina Aug 21, 2024
bb00d01
use Laurin's query builder suggestion
dimaMachina Aug 21, 2024
36f8c32
polish graphiql v4 alpha
dimaMachina Aug 21, 2024
dd5b588
polish
dimaMachina Aug 21, 2024
1510a01
mention link to graphiql
dimaMachina Aug 21, 2024
527373b
apply Kamil suggestions
dimaMachina Aug 21, 2024
14e8cf0
Merge branch 'main' into add-graphiql-explorer2
dimaMachina Oct 9, 2024
736b77c
Merge branch 'explorer3' into laboratory-product-update
dimaMachina Oct 9, 2024
aff9468
apply Saihaj review changes and polish after new landing page merge
dimaMachina Oct 9, 2024
2469276
Merge branch 'main' into laboratory-product-update
dimaMachina Oct 11, 2024
a54b13d
remove old look of operations collections
dimaMachina Oct 11, 2024
3f5a2d6
all in one
dimaMachina Oct 11, 2024
28342ba
#2 preflight scripts (db + cypress e2e tests) (#5622)
dimaMachina Oct 11, 2024
7bda2e3
Merge branch 'main' into preflight-script
dimaMachina Oct 11, 2024
016d007
Merge branch 'main' into docs-preflight
dimaMachina Oct 14, 2024
2cb4e2d
Merge branch 'main' into preflight-script
kamilkisiela Oct 16, 2024
c2f62db
aa
dimaMachina Oct 18, 2024
1a8b261
Merge branch 'main' into preflight-script
dimaMachina Oct 24, 2024
4e4bdde
refactor after merging with main
dimaMachina Oct 24, 2024
df46a0f
Merge branch 'preflight-script' into docs-preflight
dimaMachina Oct 24, 2024
00a6c20
[skip ci]
dimaMachina Oct 24, 2024
ee89ae2
prettier
dimaMachina Oct 24, 2024
2288f8c
Merge branch 'preflight-script' into docs-preflight
dimaMachina Oct 24, 2024
a1a3e82
add cypress tests for laboratory collections
dimaMachina Oct 24, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
238 changes: 236 additions & 2 deletions cypress.config.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
// eslint-disable-next-line import/no-extraneous-dependencies -- cypress SHOULD be a dev dependency
import fs from 'node:fs';
// eslint-disable-next-line import/no-extraneous-dependencies -- cypress SHOULD be a dev dependency
import { defineConfig } from 'cypress';
// eslint-disable-next-line import/no-extraneous-dependencies
import pg from 'pg';

const isCI = Boolean(process.env.CI);

export type Token = {
sAccessToken: string;
sFrontToken: string;
sRefreshToken: string;
};

export default defineConfig({
video: isCI,
screenshotOnRunFailure: isCI,
Expand All @@ -13,7 +21,233 @@ export default defineConfig({
POSTGRES_URL: 'postgresql://postgres:postgres@localhost:5432/registry',
},
e2e: {
setupNodeEvents(on) {
setupNodeEvents(on, config) {
async function connectDB(query: string) {
const dbUrl = new URL(config.env.POSTGRES_URL);
const client = new pg.Client({
user: dbUrl.username,
password: dbUrl.password,
host: dbUrl.hostname,
database: dbUrl.pathname.slice(1),
port: Number(dbUrl.port),
ssl: false,
});
await client.connect();
const res = await client.query(query);
await client.end();
return res.rows;
}

on('task', {
connectDB,
async deleteUser(email = '[email protected]') {
const [user] = await connectDB(`SELECT *
FROM users
WHERE email = '${email}';`);
if (user) {
await connectDB(`
BEGIN;

DELETE FROM organizations WHERE user_id = '${user.id}';
DELETE FROM users WHERE id = '${user.id}';
DELETE FROM supertokens_emailpassword_user_to_tenant WHERE email = '${email}';

COMMIT;
`);
}

return true;
},
async createUser({
email = '[email protected]',
password = 'qwerty123',
firstName = 'Dima',
lastName = 'Test',
}: {
email?: string;
password?: string;
firstName?: string;
lastName?: string;
} = {}) {
const response = await fetch('http://localhost:3001/auth-api/signup', {
method: 'POST',
headers: {
'content-type': 'application/json',
},
body: JSON.stringify({
formFields: [
{ id: 'email', value: email },
{ id: 'password', value: password },
{ id: 'firstName', value: firstName },
{ id: 'lastName', value: lastName },
],
}),
});
const data = await response.json();
if (response.status !== 200 || data.status === 'FIELD_ERROR') {
throw new Error(
`${response.status}: ${response.statusText}\n\n${JSON.stringify(data, null, 2)}`,
);
}
const result: Token = {
sAccessToken: response.headers.get('st-access-token')!,
sFrontToken: response.headers.get('front-token')!,
sRefreshToken: response.headers.get('st-refresh-token')!,
};
return result;
},
async login() {
const response = await fetch('http://localhost:3001/auth-api/signin', {
method: 'POST',
headers: {
'content-type': 'application/json',
},
body: JSON.stringify({
formFields: [
{ id: 'email', value: '[email protected]' },
{ id: 'password', value: 'qwerty123' },
],
}),
});
const data = await response.json();
if (response.status !== 200) {
throw new Error(
`${response.status}: ${response.statusText}\n\n${JSON.stringify(data, null, 2)}`,
);
}

const result: Token = {
sAccessToken: response.headers.get('st-access-token')!,
sFrontToken: response.headers.get('front-token')!,
sRefreshToken: response.headers.get('st-refresh-token')!,
};
return result;
},
async createOrganization(token) {
const response = await fetch('http://localhost:3001/graphql', {
method: 'POST',
headers: {
authorization: `Bearer ${token}`,
'content-type': 'application/json',
},
body: JSON.stringify({
operationName: 'CreateOrganizationMutation',
variables: { input: { slug: 'foo' } },
query: /* GraphQL */ `
mutation CreateOrganizationMutation($input: CreateOrganizationInput!) {
createOrganization(input: $input) {
ok {
createdOrganizationPayload {
organization {
id
slug
}
}
}
error {
message
}
}
}
`,
}),
});
const { data, errors = [] } = await response.json();
const error = data?.createOrganization.error;
if (error) {
errors.push(error);
}
if (!data || errors.length) {
throw new Error((errors as Error[]).map(error => error.message).join('\n'));
}
return data;
},
async createProject(token) {
const response = await fetch('http://localhost:3001/graphql', {
method: 'POST',
headers: {
authorization: `Bearer ${token}`,
'content-type': 'application/json',
},
body: JSON.stringify({
operationName: 'CreateProject',
query: /* GraphQL */ `
mutation CreateProject($input: CreateProjectInput!) {
createProject(input: $input) {
ok {
createdProject {
id
slug
}
}
error {
message
}
}
}
`,
variables: {
input: {
slug: 'my-new-project',
organizationSlug: 'foo',
type: 'SINGLE',
},
},
}),
});
const { data, errors = [] } = await response.json();
const error = data?.createProject.error;
if (error) {
errors.push(error);
}
if (!data || errors.length) {
throw new Error((errors as Error[]).map(error => error.message).join('\n'));
}
return data;
},
async createCollection(token) {
const response = await fetch('http://localhost:3001/graphql', {
method: 'POST',
headers: {
authorization: `Bearer ${token}`,
'content-type': 'application/json',
},
body: JSON.stringify({
operationName: 'CreateCollection',
query: /* GraphQL */ `
mutation CreateCollection($selector: TargetSelectorInput!, $input: CreateDocumentCollectionInput!) {
createDocumentCollection(selector: $selector, input: $input) {
error {
message
}
}
}
`,
variables: {
input: {
description: 'Test Description',
name: 'Test Collection',
},
selector: {
organizationSlug: 'foo',
projectSlug: 'my-new-project',
targetSlug: 'development',
},
},
}),
});
const { data, errors = [] } = await response.json();
const error = data?.createDocumentCollection.error;
if (error) {
errors.push(error);
}
if (!data || errors.length) {
throw new Error((errors as Error[]).map(error => error.message).join('\n'));
}
return data;
},
});

on('after:spec', (_, results) => {
if (results && results.video) {
// Do we have failures for any retry attempts?
Expand Down
51 changes: 51 additions & 0 deletions cypress/e2e/collections.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { Token } from '../../cypress.config';

beforeEach(() => {
cy.task('deleteUser');
cy.task<Token>('createUser').then(result => {
cy.task('createOrganization', result.sAccessToken);
cy.task('createProject', result.sAccessToken);
cy.setCookie('sRefreshToken', result.sRefreshToken);
cy.setCookie('sAccessToken', result.sAccessToken);
});
cy.visit('/foo/my-new-project/development/laboratory');
});

describe('Laboratory Collections', () => {
it('should show toast when there is no collections', () => {
cy.dataCy('save-operation').click();
cy.dataCy('save-operation-as').click();
cy.get('.Toastify').contains('Please create a collection first.');
});

it('should create a collection', () => {
const collectionName = 'Test Collection';
cy.dataCy('create-collection').click();
cy.dataCy('collection-name').type(collectionName);
cy.dataCy('collection-description').type('Test Description');
cy.dataCy('save-collection').click();
cy.get('.graphiql-plugin').contains(collectionName);
});

it('should save operation to collection', () => {
cy.getCookie('sAccessToken').then(result => {
cy.task('createCollection', result.value);
});
cy.reload();
cy.get('.graphiql-query-editor .graphiql-editor textarea').type('{CMD}{A}{Backspace}', {
force: true,
});
cy.get('.graphiql-query-editor .graphiql-editor textarea').type('{\nfoo', {
force: true,
});
const operationName = 'Test Operation';
cy.dataCy('save-operation').click();
cy.dataCy('save-operation-as').click();
cy.dataCy('operation-name').type(operationName);
cy.dataCy('collections-select').click();
cy.dataCy('collections-select-item').first().click();
cy.dataCy('confirm').click();
cy.get('.graphiql-plugin').contains(operationName);
cy.get('body').contains('Operation "Test Operation" added to collection "Test Collection"');
});
});
Loading
Loading