Skip to content

Commit d6d02df

Browse files
use a common component for Links and Emails inputs
1 parent 8aec454 commit d6d02df

File tree

413 files changed

+7115
-3677
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

413 files changed

+7115
-3677
lines changed

.github/workflows/playwright.yml.bak

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
name: Playwright Tests
2+
on:
3+
push:
4+
branches: [ main, master ]
5+
pull_request:
6+
branches: [ main, master ]
7+
jobs:
8+
test:
9+
timeout-minutes: 60
10+
runs-on: ubuntu-latest
11+
steps:
12+
- uses: actions/checkout@v4
13+
- uses: actions/setup-node@v4
14+
with:
15+
node-version: lts/*
16+
- name: Install dependencies
17+
run: npm install -g yarn && yarn
18+
- name: Install Playwright Browsers
19+
run: yarn playwright install --with-deps
20+
- name: Run Playwright tests
21+
run: yarn test:e2e companies
22+
- uses: actions/upload-artifact@v4
23+
if: always()
24+
with:
25+
name: playwright-report
26+
path: playwright-report/
27+
retention-days: 30

.gitignore

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,5 @@ dist
2626
storybook-static
2727
*.tsbuildinfo
2828
.eslintcache
29-
.cache
3029
.nyc_output
30+
test-results/

nx.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
},
3333
"start": {
3434
"cache": true,
35-
"dependsOn": ["^typecheck","^build"]
35+
"dependsOn": ["^build"]
3636
},
3737
"lint": {
3838
"executor": "@nx/eslint:lint",

package.json

+1-2
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,6 @@
7171
"apollo-server-express": "^3.12.0",
7272
"apollo-upload-client": "^17.0.0",
7373
"archiver": "^7.0.1",
74-
"aws-sdk": "^2.1658.0",
7574
"axios": "^1.6.2",
7675
"bcrypt": "^5.1.1",
7776
"better-sqlite3": "^9.2.2",
@@ -190,7 +189,6 @@
190189
"tslib": "^2.3.0",
191190
"tsup": "^8.2.4",
192191
"type-fest": "4.10.1",
193-
"typeorm": "patch:[email protected]#./packages/twenty-server/patches/typeorm+0.3.20.patch",
194192
"typescript": "5.3.3",
195193
"use-context-selector": "^2.0.0",
196194
"use-debounce": "^10.0.0",
@@ -223,6 +221,7 @@
223221
"@nx/storybook": "18.3.3",
224222
"@nx/vite": "18.3.3",
225223
"@nx/web": "18.3.3",
224+
"@playwright/test": "^1.46.0",
226225
"@sentry/types": "^7.109.0",
227226
"@storybook/addon-actions": "^7.6.3",
228227
"@storybook/addon-coverage": "^1.0.0",

packages/twenty-chrome-extension/src/generated/graphql.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -7455,7 +7455,7 @@ export type Workspace = {
74557455
billingSubscriptions?: Maybe<Array<BillingSubscription>>;
74567456
createdAt: Scalars['DateTime'];
74577457
currentBillingSubscription?: Maybe<BillingSubscription>;
7458-
currentCacheVersion?: Maybe<Scalars['String']>;
7458+
metadataVersion?: Maybe<Scalars['String']>;
74597459
deletedAt?: Maybe<Scalars['DateTime']>;
74607460
displayName?: Maybe<Scalars['String']>;
74617461
domainName?: Maybe<Scalars['String']>;
+21-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,22 @@
11
# Note that provide always without trailing forward slash to have expected behaviour
2-
FRONTEND_BASE_URL="http://localhost:3001"
2+
FRONTEND_BASE_URL=http://localhost:3001
3+
CI_DEFAULT_BASE_URL=https://demo.twenty.com
4+
DEFAULT_LOGIN=[email protected]
5+
NEW_WORKSPACE_LOGIN=[email protected]
6+
DEMO_DEFAULT_LOGIN=[email protected]
7+
DEFAULT_PASSWORD=Applecar2025
8+
WEBSITE_URL=https://twenty.com
9+
10+
# === DO NOT USE, WORK IN PROGRESS ===
11+
# This URL must have trailing forward slash as all REST API endpoints have object after it
12+
# Documentation for REST API: https://twenty.com/developers/rest-api/core#/
13+
# REST_API_BASE_URL=http://localhost:3000/rest/
14+
15+
# Documentation for GraphQL API: https://twenty.com/developers/graphql/core
16+
# GRAPHQL_BASE_URL=http://localhost:3000/graphql
17+
18+
# Without this key, all API tests will fail, to generate this key
19+
# Log in to Twenty workspace, go to Settings > Developers, generate new key and paste it here
20+
# In order to use it, header Authorization: Bearer token must be used
21+
# This key works for both REST and GraphQL API
22+
# API_DEV_KEY=fill_with_proper_key
+10-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
1-
node_modules/
2-
/test-results/
3-
/playwright-report/
4-
/blob-report/
5-
/playwright/.cache/
1+
test-results/
2+
playwright-report/
3+
blob-report/
4+
playwright/.cache/
5+
run_results/
6+
playwright-report/.last-run.json
7+
results/
8+
run_results/.playwright-artifacts-0/
9+
run_results/.playwright-artifacts-1/
10+
.auth/

packages/twenty-e2e-testing/README.md

+9-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# Twenty e2e Testing
22

3-
## Install
3+
## Prerequisite
44

5-
Don't forget to install the browsers before launching the tests :
5+
Installing the browsers:
66

77
```
88
yarn playwright install
@@ -35,3 +35,10 @@ yarn run test:e2e <filename>
3535
```
3636
yarn run test:e2e:debug
3737
```
38+
39+
## Q&A
40+
41+
#### Why there's `path.resolve()` everywhere?
42+
That's thanks to differences in root directory when running tests using commands and using IDE. When running tests with commands,
43+
the root directory is `twenty/packages/twenty-e2e-testing`, for IDE it depends on how someone sets the configuration. This way, it
44+
ensures that no matter which IDE or OS Shell is used, the result will be the same.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import {
2+
Reporter,
3+
FullConfig,
4+
Suite,
5+
TestCase,
6+
TestResult,
7+
FullResult,
8+
} from '@playwright/test/reporter';
9+
10+
class CustomReporter implements Reporter {
11+
constructor(options: { customOption?: string } = {}) {
12+
console.log(
13+
`my-awesome-reporter setup with customOption set to ${options.customOption}`,
14+
);
15+
}
16+
17+
onBegin(config: FullConfig, suite: Suite) {
18+
console.log(`Starting the run with ${suite.allTests().length} tests`);
19+
}
20+
21+
onTestBegin(test: TestCase) {
22+
console.log(`Starting test ${test.title}`);
23+
}
24+
25+
onTestEnd(test: TestCase, result: TestResult) {
26+
console.log(`Finished test ${test.title}: ${result.status}`);
27+
}
28+
29+
onEnd(result: FullResult) {
30+
console.log(`Finished the run: ${result.status}`);
31+
}
32+
}
33+
export default CustomReporter;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { exec } from 'child_process';
2+
3+
export async function sh(cmd) {
4+
return new Promise((resolve, reject) => {
5+
exec(cmd, (err, stdout, stderr) => {
6+
if (err) {
7+
reject(err);
8+
} else {
9+
resolve({ stdout, stderr });
10+
}
11+
});
12+
});
13+
}

packages/twenty-e2e-testing/e2e/companies.spec.ts

-14
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { test as base } from '@playwright/test';
2+
import path from 'path';
3+
4+
const date = new Date();
5+
6+
export const test = base.extend<{ screenshotHook: void }>({
7+
screenshotHook: [
8+
async ({ page, browserName }, use, workerInfo) => {
9+
// here everything is the same as beforeEach()
10+
// goto is to go to website as login setup saves the cookies of logged-in user, not the state of browser
11+
await page.goto('/');
12+
await use(); // here is the code of test
13+
// here everything is the same as afterEach()
14+
// automatic fixture of making screenshot after each test
15+
await page.screenshot({
16+
path: path.resolve(
17+
__dirname,
18+
'..',
19+
'..',
20+
'results',
21+
'screenshots',
22+
`${workerInfo.project.name}`,
23+
browserName,
24+
`${date.toISOString()}.png`,
25+
),
26+
});
27+
},
28+
{ auto: true }, // automatic fixture runs with every test
29+
],
30+
});
31+
32+
export { expect } from '@playwright/test';
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,85 @@
11
import { defineConfig, devices } from '@playwright/test';
2-
32
import { config } from 'dotenv';
3+
import path from 'path';
4+
45
config();
56

7+
/* === Run your local dev server before starting the tests === */
8+
69
/**
710
* See https://playwright.dev/docs/test-configuration.
8-
* See https://playwright.dev/docs/trace-viewer to Collect trace when retrying the failed test
911
*/
1012
export default defineConfig({
11-
testDir: 'e2e',
12-
/* Run tests in files in parallel */
13-
fullyParallel: true,
14-
reporter: 'html',
15-
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
13+
testDir: '.',
14+
outputDir: 'run_results/', // directory for screenshots and videos
15+
snapshotPathTemplate: '{testDir}/__screenshots__/{testFilePath}/{arg}{ext}', // just in case, do not delete it
16+
fullyParallel: true, // false only for specific tests, overwritten in specific projects or global setups of projects
17+
forbidOnly: !!process.env.CI,
18+
retries: process.env.CI ? 2 : 0,
19+
workers: process.env.CI ? 1 : undefined, // undefined = amount of projects * amount of tests
20+
timeout: 30 * 1000, // timeout can be changed
1621
use: {
17-
/* Base URL to use in actions like `await page.goto('/')`. */
18-
baseURL: process.env.FRONTEND_BASE_URL ?? 'http://localhost:3001',
22+
baseURL: process.env.CI
23+
? process.env.CI_DEFAULT_BASE_URL
24+
: (process.env.FRONTEND_BASE_URL ?? 'http://localhost:3001'),
25+
trace: 'retain-on-failure', // trace takes EVERYTHING from page source, records every single step, should be used only when normal debugging won't work
26+
screenshot: 'on', // either 'on' here or in different method in modules, if 'on' all screenshots are overwritten each time the test is run
27+
headless: true, // instead of changing it to false, run 'yarn test:e2e:debug' or 'yarn test:e2e:ui'
28+
testIdAttribute: 'data-testid', // taken from Twenty source
29+
viewport: { width: 1920, height: 1080 }, // most laptops use this resolution
30+
launchOptions: {
31+
slowMo: 500, // time in milliseconds between each step, better to use it than explicitly define timeout in tests
32+
},
1933
},
20-
21-
/* Configure projects for major browsers */
34+
expect: {
35+
timeout: 5000,
36+
},
37+
reporter: [['html', { open: 'never' }]],
2238
projects: [
39+
{
40+
name: 'Login setup',
41+
testMatch: /login\.setup\.ts/, // finds all tests matching this regex, in this case only 1 test should be found
42+
},
2343
{
2444
name: 'chromium',
25-
use: { ...devices['Desktop Chrome'] },
45+
use: {
46+
...devices['Desktop Chrome'],
47+
storageState: path.resolve(__dirname, '.auth', 'user.json'), // takes saved cookies from directory
48+
},
49+
dependencies: ['Login setup'], // forces to run login setup before running tests from this project - CASE SENSITIVE
2650
},
27-
2851
{
2952
name: 'firefox',
30-
use: { ...devices['Desktop Firefox'] },
53+
use: {
54+
...devices['Desktop Firefox'],
55+
storageState: path.resolve(__dirname, '.auth', 'user.json'),
56+
},
57+
dependencies: ['Login setup'],
3158
},
3259

33-
{
34-
name: 'webkit',
35-
use: { ...devices['Desktop Safari'] },
36-
},
60+
//{
61+
// name: 'webkit',
62+
// use: { ...devices['Desktop Safari'] },
63+
//},
3764

38-
{
39-
name: 'Google Chrome',
40-
use: { ...devices['Desktop Chrome'], channel: 'chrome' },
41-
},
65+
/* Test against mobile viewports. */
66+
// {
67+
// name: 'Mobile Chrome',
68+
// use: { ...devices['Pixel 5'] },
69+
// },
70+
// {
71+
// name: 'Mobile Safari',
72+
// use: { ...devices['iPhone 12'] },
73+
// },
74+
75+
/* Test against branded browsers. */
76+
//{
77+
// name: 'Microsoft Edge',
78+
// use: { ...devices['Desktop Edge'], channel: 'msedge' },
79+
//},
80+
//{
81+
// name: 'Google Chrome',
82+
// use: { ...devices['Desktop Chrome'], channel: 'chrome' },
83+
//},
4284
],
4385
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { test, expect } from '../lib/fixtures/screenshot';
2+
import { config } from 'dotenv';
3+
import path = require('path');
4+
config({ path: path.resolve(__dirname, '..', '.env') });
5+
6+
test.describe('Basic check', () => {
7+
test('Checking if table in Companies is visible', async ({ page }) => {
8+
await expect(page.getByTestId('tooltip').nth(0)).toHaveText('Companies');
9+
await expect(page.getByTestId('tooltip').nth(0)).toBeVisible();
10+
expect(page.url()).toContain('/companies');
11+
await expect(page.locator('table')).toBeVisible();
12+
await expect(page.locator('tbody > tr')).toHaveCount(13); // shouldn't be hardcoded in case of tests on demo
13+
});
14+
15+
test('', async ({ page }) => {
16+
await page.getByRole('link', { name: 'Opportunities' }).click();
17+
await expect(page.locator('table')).toBeVisible();
18+
});
19+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { test as setup, expect } from '@playwright/test';
2+
import path from 'path';
3+
4+
setup('Login test', async ({ page }) => {
5+
await page.goto('/');
6+
await page.getByRole('button', { name: 'Continue With Email' }).click();
7+
await page.getByPlaceholder('Email').fill(process.env.DEFAULT_LOGIN);
8+
await page.getByRole('button', { name: 'Continue', exact: true }).click();
9+
await page.getByPlaceholder('Password').fill(process.env.DEFAULT_PASSWORD);
10+
await page.getByRole('button', { name: 'Sign in' }).click();
11+
await expect(page.getByText('Welcome to Twenty')).not.toBeVisible();
12+
13+
// End of authentication steps.
14+
15+
await page.context().storageState({
16+
path: path.resolve(__dirname, '..', '.auth', 'user.json'),
17+
});
18+
});

0 commit comments

Comments
 (0)