Add Activepieces integration for workflow automation
- Add Activepieces fork with SmoothSchedule custom piece - Create integrations app with Activepieces service layer - Add embed token endpoint for iframe integration - Create Automations page with embedded workflow builder - Add sidebar visibility fix for embed mode - Add list inactive customers endpoint to Public API - Include SmoothSchedule triggers: event created/updated/cancelled - Include SmoothSchedule actions: create/update/cancel events, list resources/services/customers 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
19
activepieces-fork/packages/tests-e2e/.env.e2e
Normal file
19
activepieces-fork/packages/tests-e2e/.env.e2e
Normal file
@@ -0,0 +1,19 @@
|
||||
AP_DEV_PIECES="store,webhook"
|
||||
AP_PIECES_SYNC_MODE=NONE
|
||||
AP_PIECES_SOURCE='FILE'
|
||||
AP_API_KEY=api-key
|
||||
AP_DB_TYPE=PGLITE
|
||||
AP_ENVIRONMENT=test
|
||||
AP_ENCRYPTION_KEY=7e19fad4c13eaea8f657afb12e8f9c40
|
||||
AP_FRONTEND_URL=http://localhost:4200
|
||||
AP_WEBHOOK_TIMEOUT_SECONDS=30
|
||||
AP_LOG_LEVEL=info
|
||||
AP_LOG_PRETTY=true
|
||||
AP_REDIS_TYPE=MEMORY
|
||||
AP_TELEMETRY_ENABLED=false
|
||||
AP_ENRICH_ERROR_CONTEXT=true
|
||||
AP_TRIGGER_DEFAULT_POLL_INTERVAL=1
|
||||
AP_CACHE_PATH=./dev/cache
|
||||
AP_EXECUTION_MODE=UNSANDBOXED
|
||||
AP_JWT_SECRET=secret
|
||||
AP_API_KEY="api-key"
|
||||
18
activepieces-fork/packages/tests-e2e/.eslintrc.json
Normal file
18
activepieces-fork/packages/tests-e2e/.eslintrc.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"extends": ["../../.eslintrc.json"],
|
||||
"ignorePatterns": ["!**/*"],
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
|
||||
"rules": {}
|
||||
},
|
||||
{
|
||||
"files": ["*.ts", "*.tsx"],
|
||||
"rules": {}
|
||||
},
|
||||
{
|
||||
"files": ["*.js", "*.jsx"],
|
||||
"rules": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
57
activepieces-fork/packages/tests-e2e/checkly.config.ts
Normal file
57
activepieces-fork/packages/tests-e2e/checkly.config.ts
Normal file
@@ -0,0 +1,57 @@
|
||||
import { defineConfig } from 'checkly'
|
||||
import { AlertEscalationBuilder, RetryStrategyBuilder } from 'checkly/constructs'
|
||||
|
||||
/**
|
||||
* See https://www.checklyhq.com/docs/cli/project-structure/
|
||||
*/
|
||||
const config = defineConfig({
|
||||
/* A human friendly name for your project */
|
||||
projectName: `E2E (${process.env.E2E_CONFIG_MODE})`,
|
||||
/** A logical ID that needs to be unique across your Checkly account,
|
||||
* See https://www.checklyhq.com/docs/cli/constructs/ to learn more about logical IDs.
|
||||
*/
|
||||
logicalId: `activepieces-e2e-tests-${process.env.E2E_CONFIG_MODE}`,
|
||||
/* An optional URL to your Git repo to be shown in your test sessions and resource activity log */
|
||||
/* repoUrl: 'https://github.com/checkly/checkly-cli', */
|
||||
/* Sets default values for Checks */
|
||||
checks: {
|
||||
/* A default for how often your Check should run in minutes */
|
||||
frequency: 10,
|
||||
/* Checkly data centers to run your Checks as monitors */
|
||||
locations: ['us-east-1', 'eu-west-1'],
|
||||
/** The Checkly Runtime identifier, determining npm packages and the Node.js version available at runtime.
|
||||
* See https://www.checklyhq.com/docs/cli/npm-packages/
|
||||
*/
|
||||
|
||||
runtimeId: '2024.09',
|
||||
/* Failed check runs will be retried before triggering alerts */
|
||||
retryStrategy: RetryStrategyBuilder.fixedStrategy({ baseBackoffSeconds: 60, maxRetries: 4, sameRegion: true }),
|
||||
/* A glob pattern that matches the Checks inside your repo, see https://www.checklyhq.com/docs/cli/using-check-test-match/ */
|
||||
checkMatch: '**/scenarios/**/*.check.ts',
|
||||
/* All checks will have this alert escalation policy defined */
|
||||
alertEscalationPolicy: AlertEscalationBuilder.runBasedEscalation(1),
|
||||
/* Global configuration option for Playwright-powered checks. See https://www.checklyhq.com/docs/browser-checks/playwright-test/#global-configuration */
|
||||
playwrightConfig: {
|
||||
use: {
|
||||
baseURL: 'https://cloud.activepieces.com',
|
||||
viewport: { width: 1280, height: 720 },
|
||||
}
|
||||
},
|
||||
browserChecks: {
|
||||
/* A glob pattern matches any Playwright .spec.ts files and automagically creates a Browser Check. This way, you
|
||||
* can just write native Playwright code. See https://www.checklyhq.com/docs/cli/using-check-test-match/
|
||||
* */
|
||||
testMatch: '**/scenarios/**/*.spec.ts',
|
||||
},
|
||||
},
|
||||
cli: {
|
||||
/* The default datacenter location to use when running npx checkly test */
|
||||
runLocation: 'eu-west-1',
|
||||
/* An array of default reporters to use when a reporter is not specified with the "--reporter" flag */
|
||||
reporters: ['list'],
|
||||
/* How many times to retry a failing test run when running `npx checkly test` or `npx checkly trigger` (max. 3) */
|
||||
retries: 2,
|
||||
},
|
||||
})
|
||||
|
||||
export default config
|
||||
63
activepieces-fork/packages/tests-e2e/fixtures/index.ts
Normal file
63
activepieces-fork/packages/tests-e2e/fixtures/index.ts
Normal file
@@ -0,0 +1,63 @@
|
||||
import { test as base } from '@playwright/test';
|
||||
import {
|
||||
AuthenticationPage,
|
||||
FlowsPage,
|
||||
BuilderPage,
|
||||
} from '../pages';
|
||||
import { signUp, AuthenticationResponse } from './users';
|
||||
import { DEFAULT_EMAIL, DEFAULT_PASSWORD } from '../global-setup';
|
||||
|
||||
type CustomFixtures = {
|
||||
authenticationPage: AuthenticationPage;
|
||||
flowsPage: FlowsPage;
|
||||
builderPage: BuilderPage;
|
||||
authenticatedPage: AuthenticationPage;
|
||||
users: {
|
||||
apiSignUp: () => Promise<AuthenticationResponse>;
|
||||
}
|
||||
};
|
||||
|
||||
export const test = base.extend<CustomFixtures>({
|
||||
// Override page fixture to automatically authenticate before each test
|
||||
page: async ({ page }, use) => {
|
||||
const authPage = new AuthenticationPage(page);
|
||||
|
||||
if (process.env.E2E_EMAIL && process.env.E2E_PASSWORD) {
|
||||
await authPage.signIn({
|
||||
email: process.env.E2E_EMAIL,
|
||||
password: process.env.E2E_PASSWORD,
|
||||
});
|
||||
} else {
|
||||
await authPage.signIn({
|
||||
email: DEFAULT_EMAIL,
|
||||
password: DEFAULT_PASSWORD,
|
||||
});
|
||||
}
|
||||
|
||||
await use(page);
|
||||
},
|
||||
|
||||
authenticationPage: async ({ page }, use) => {
|
||||
await use(new AuthenticationPage(page));
|
||||
},
|
||||
|
||||
flowsPage: async ({ page }, use) => {
|
||||
await use(new FlowsPage(page));
|
||||
},
|
||||
|
||||
builderPage: async ({ page }, use) => {
|
||||
await use(new BuilderPage(page));
|
||||
},
|
||||
|
||||
authenticatedPage: async ({ page }, use) => {
|
||||
await use(new AuthenticationPage(page));
|
||||
},
|
||||
|
||||
users: async ({ request, page }, use) => {
|
||||
await use({
|
||||
apiSignUp: async () => await signUp(request, page),
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
export { expect } from '@playwright/test';
|
||||
50
activepieces-fork/packages/tests-e2e/fixtures/users.ts
Normal file
50
activepieces-fork/packages/tests-e2e/fixtures/users.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
import { faker } from '@faker-js/faker';
|
||||
import type { APIRequestContext, Page } from '@playwright/test';
|
||||
|
||||
export async function signUp(request: APIRequestContext, page: Page): Promise<AuthenticationResponse> {
|
||||
const signUpPayload = {
|
||||
email: faker.internet.email(),
|
||||
password: '12345678',
|
||||
firstName: 'Test',
|
||||
lastName: 'User',
|
||||
trackEvents: false,
|
||||
platformId: null,
|
||||
newsLetter: false,
|
||||
provider: UserIdentityProvider.EMAIL,
|
||||
};
|
||||
|
||||
const response = await request.post('/api/v1/authentication/sign-up', {
|
||||
data: signUpPayload,
|
||||
});
|
||||
|
||||
const authResponse = await response.json();
|
||||
|
||||
await page.addInitScript((tokenValue) => {
|
||||
localStorage.setItem('token', tokenValue);
|
||||
}, authResponse.token);
|
||||
return authResponse;
|
||||
}
|
||||
|
||||
// cant import from shared: https://www.checklyhq.com/docs/runtimes/#why-cant-i-import-any-npm-package-or-other-3rd-party-dependencies
|
||||
export enum UserIdentityProvider {
|
||||
EMAIL = 'EMAIL',
|
||||
GOOGLE = 'GOOGLE',
|
||||
SAML = 'SAML',
|
||||
JWT = 'JWT',
|
||||
}
|
||||
|
||||
export type AuthenticationResponse = {
|
||||
id: string;
|
||||
platformRole: string;
|
||||
status: string;
|
||||
externalId: string;
|
||||
platformId: string;
|
||||
verified: boolean;
|
||||
firstName: string;
|
||||
lastName: string;
|
||||
email: string;
|
||||
trackEvents: boolean;
|
||||
newsLetter: boolean;
|
||||
token: string;
|
||||
projectId: string;
|
||||
}
|
||||
49
activepieces-fork/packages/tests-e2e/global-setup.ts
Normal file
49
activepieces-fork/packages/tests-e2e/global-setup.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
import { chromium } from '@playwright/test';
|
||||
import { AuthenticationPage } from './pages/authentication.page';
|
||||
|
||||
export const DEFAULT_EMAIL = 'test@activepieces.com';
|
||||
export const DEFAULT_PASSWORD = 'TestPassword123!@#';
|
||||
|
||||
async function globalSetup() {
|
||||
console.log('🔧 Running global setup...');
|
||||
|
||||
const browser = await chromium.launch({ headless: true });
|
||||
const context = await browser.newContext({
|
||||
baseURL: process.env.AP_FRONTEND_URL,
|
||||
});
|
||||
const page = await context.newPage();
|
||||
|
||||
const authPage = new AuthenticationPage(page);
|
||||
|
||||
try {
|
||||
if (process.env.E2E_EMAIL && process.env.E2E_PASSWORD) {
|
||||
console.log('✓ Using credentials from environment variables for sign-in');
|
||||
await authPage.signIn({
|
||||
email: process.env.E2E_EMAIL,
|
||||
password: process.env.E2E_PASSWORD,
|
||||
});
|
||||
} else {
|
||||
console.log('✓ Using default credentials for sign-up');
|
||||
await authPage.signUp({
|
||||
email: DEFAULT_EMAIL,
|
||||
password: DEFAULT_PASSWORD,
|
||||
firstName: 'Test',
|
||||
lastName: 'User',
|
||||
});
|
||||
}
|
||||
|
||||
// Wait for successful authentication (redirect to flows page or dashboard)
|
||||
await page.waitForURL('**/flows', { timeout: 15000 });
|
||||
|
||||
console.log('✓ Global setup completed successfully');
|
||||
} catch (error) {
|
||||
console.error('❌ Global setup failed:', error);
|
||||
throw error;
|
||||
} finally {
|
||||
await context.close();
|
||||
await browser.close();
|
||||
}
|
||||
}
|
||||
|
||||
export default globalSetup;
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
import { BasePage } from './base';
|
||||
import { faker } from '@faker-js/faker';
|
||||
|
||||
export class AuthenticationPage extends BasePage {
|
||||
url = `/sign-in`;
|
||||
signUpUrl = `/sign-up`;
|
||||
|
||||
async signIn(params: { email: string; password: string }) {
|
||||
await this.page.goto(this.url);
|
||||
|
||||
const emailField = this.page.getByTestId('sign-in-email');
|
||||
await emailField.click();
|
||||
await emailField.fill(params.email);
|
||||
|
||||
const passwordField = this.page.getByTestId('sign-in-password');
|
||||
await passwordField.click();
|
||||
await passwordField.fill(params.password);
|
||||
|
||||
await this.page.getByTestId('sign-in-button').click();
|
||||
}
|
||||
|
||||
async signUp(params?: { email?: string; password?: string; firstName?: string; lastName?: string }) {
|
||||
await this.page.goto(this.signUpUrl);
|
||||
|
||||
const firstNameField = this.page.getByTestId('sign-up-first-name');
|
||||
await firstNameField.click();
|
||||
await firstNameField.fill(params?.firstName || 'Bugs');
|
||||
await firstNameField.press('Tab');
|
||||
|
||||
const lastNameField = this.page.getByTestId('sign-up-last-name');
|
||||
await lastNameField.click();
|
||||
await lastNameField.fill(params?.lastName || 'Bunny');
|
||||
await lastNameField.press('Tab');
|
||||
|
||||
const emailField = this.page.getByTestId('sign-up-email');
|
||||
await emailField.click();
|
||||
await emailField.fill(params?.email || faker.internet.email());
|
||||
await emailField.press('Tab');
|
||||
|
||||
const passwordField = this.page.getByTestId('sign-up-password');
|
||||
await passwordField.click();
|
||||
await passwordField.fill(params?.password || faker.internet.password({
|
||||
pattern: /[!@#$%^&*()_+\-=[\]{};':"\\|,.<>/?a-zA-Z0-9]/,
|
||||
length: 12,
|
||||
prefix: '0'
|
||||
}));
|
||||
|
||||
await this.page.getByTestId('sign-up-button').click();
|
||||
}
|
||||
}
|
||||
29
activepieces-fork/packages/tests-e2e/pages/base.ts
Normal file
29
activepieces-fork/packages/tests-e2e/pages/base.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { Page, Locator } from '@playwright/test';
|
||||
|
||||
export interface IPageElement {
|
||||
(...args: unknown[]): Locator;
|
||||
}
|
||||
|
||||
export interface IPageAction {
|
||||
(...args: unknown[]): Promise<void>;
|
||||
}
|
||||
|
||||
export interface IPageGetter {
|
||||
(...args: unknown[]): Locator;
|
||||
}
|
||||
|
||||
export interface IPageObject {
|
||||
url: string;
|
||||
page: Page;
|
||||
visit(): Promise<void>;
|
||||
}
|
||||
|
||||
export abstract class BasePage implements IPageObject {
|
||||
abstract url: string;
|
||||
|
||||
constructor(public readonly page: Page) {}
|
||||
|
||||
async visit(): Promise<void> {
|
||||
await this.page.goto(this.url);
|
||||
}
|
||||
}
|
||||
60
activepieces-fork/packages/tests-e2e/pages/builder.page.ts
Normal file
60
activepieces-fork/packages/tests-e2e/pages/builder.page.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
import { expect } from '@playwright/test';
|
||||
import { BasePage } from './base';
|
||||
|
||||
export class BuilderPage extends BasePage {
|
||||
url = `/builder`;
|
||||
|
||||
async selectInitialTrigger(params: { piece: string; trigger: string }) {
|
||||
await this.page.getByTestId('rf__node-trigger').filter({ hasText: 'Select Trigger' }).click();
|
||||
await this.page.getByTestId('pieces-search-input').fill(params.trigger);
|
||||
await this.page.getByText(params.trigger).click();
|
||||
}
|
||||
|
||||
async addAction(params: { piece: string; action: string }) {
|
||||
await this.page.getByTestId('add-action-button').click();
|
||||
await this.page.getByTestId('pieces-search-input').fill(params.piece);
|
||||
await this.page.getByTestId(params.piece).click();
|
||||
await this.page.getByText(params.action).nth(1).click();
|
||||
}
|
||||
|
||||
async testFlowAndWaitForSuccess() {
|
||||
await this.page.getByRole('button', { name: 'Test Flow' }).click();
|
||||
await this.page.waitForTimeout(1000);
|
||||
const runSuccessLocator = this.page.locator('text=Run Succeeded');
|
||||
const runSuccessText = await runSuccessLocator.textContent({ timeout: 60000 });
|
||||
expect(runSuccessText).toContain('Run Succeeded');
|
||||
}
|
||||
|
||||
async testStep() {
|
||||
await this.page.getByRole('button', { name: 'Test Step Ctrl + G' }).click();
|
||||
await this.page.waitForTimeout(8000);
|
||||
}
|
||||
|
||||
async testTrigger() {
|
||||
await this.page.getByTestId('test-trigger-button').click();
|
||||
await this.page.waitForTimeout(5000);
|
||||
}
|
||||
|
||||
async handleDismissButton() {
|
||||
const dismissButton = this.page.getByRole('button', { name: 'Dismiss' });
|
||||
if (await dismissButton.isVisible()) {
|
||||
await dismissButton.click();
|
||||
}
|
||||
}
|
||||
|
||||
async loadSampleData() {
|
||||
await this.page.getByText('Load Sample data').click();
|
||||
await this.page.waitForTimeout(8000);
|
||||
}
|
||||
|
||||
async publishFlow() {
|
||||
await this.page.getByRole('button', { name: 'Publish' }).click();
|
||||
await this.page.waitForTimeout(15000);
|
||||
}
|
||||
|
||||
async waitFor() {
|
||||
await this.page.waitForURL('**/flows/**');
|
||||
await this.page.waitForSelector('.react-flow__nodes', { state: 'visible' });
|
||||
await this.page.waitForSelector('.react-flow__node', { state: 'visible' });
|
||||
}
|
||||
}
|
||||
30
activepieces-fork/packages/tests-e2e/pages/flows.page.ts
Normal file
30
activepieces-fork/packages/tests-e2e/pages/flows.page.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import { BasePage } from './base';
|
||||
export class FlowsPage extends BasePage {
|
||||
url = `/flows`;
|
||||
|
||||
async navigate() {
|
||||
await this.page.getByRole('link', { name: 'Flows' }).click();
|
||||
await this.page.waitForSelector('tbody tr');
|
||||
}
|
||||
|
||||
async waitFor() {
|
||||
await this.page.waitForSelector('tbody tr');
|
||||
}
|
||||
|
||||
async newFlowFromScratch() {
|
||||
await this.page.getByTestId('new-flow-button').click();
|
||||
await this.page.getByTestId('new-flow-from-scratch-button').click();
|
||||
}
|
||||
|
||||
async cleanupExistingFlows() {
|
||||
while ((await this.page.locator('span.text-muted-foreground').count()) > 1) {
|
||||
if (!(await this.page.locator('td:nth-child(7)').first().count())) break;
|
||||
await this.page.locator('td:nth-child(7)').first().click();
|
||||
await this.page.getByRole('menuitem', { name: 'Delete' }).click();
|
||||
const confirmButton = this.page.getByRole('button', { name: 'Remove' });
|
||||
await confirmButton.click();
|
||||
await this.page.waitForSelector('button:has-text("Remove")', { state: 'hidden' });
|
||||
await this.page.reload();
|
||||
}
|
||||
}
|
||||
}
|
||||
4
activepieces-fork/packages/tests-e2e/pages/index.ts
Normal file
4
activepieces-fork/packages/tests-e2e/pages/index.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export { BasePage } from './base';
|
||||
export { AuthenticationPage } from './authentication.page';
|
||||
export { FlowsPage } from './flows.page';
|
||||
export { BuilderPage } from './builder.page';
|
||||
75
activepieces-fork/packages/tests-e2e/playwright.config.ts
Normal file
75
activepieces-fork/packages/tests-e2e/playwright.config.ts
Normal file
@@ -0,0 +1,75 @@
|
||||
import { defineConfig, devices, PlaywrightTestConfig } from '@playwright/test';
|
||||
import dotenv from 'dotenv';
|
||||
import path from 'path';
|
||||
|
||||
// Load environment variables from the .env.e2e file (local dev)
|
||||
// In CI, use inherited environment variables instead
|
||||
if (!process.env.CI) {
|
||||
dotenv.config({ path: path.resolve(__dirname, '.env.e2e') });
|
||||
}
|
||||
|
||||
const AP_EDITION = process.env.AP_EDITION || 'ce';
|
||||
|
||||
const editionConfigs = {
|
||||
ce: {
|
||||
testDir: './scenarios/ce',
|
||||
},
|
||||
ee: {
|
||||
testDir: './scenarios/ee',
|
||||
},
|
||||
};
|
||||
|
||||
const editionConfig = editionConfigs[AP_EDITION as keyof typeof editionConfigs];
|
||||
|
||||
const config: PlaywrightTestConfig = {
|
||||
testDir: editionConfig.testDir,
|
||||
testMatch: '**/*.spec.ts',
|
||||
/* Run tests in files in parallel */
|
||||
fullyParallel: true,
|
||||
/* Fail the build on CI if you accidentally left test.only in the source code. */
|
||||
forbidOnly: !!process.env.CI,
|
||||
/* Retry on CI only */
|
||||
retries: process.env.CI ? 2 : 0,
|
||||
/* Opt out of parallel tests on CI. */
|
||||
workers: process.env.CI ? '100%' : undefined,
|
||||
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
|
||||
reporter: process.env.CI ? 'github' : 'html',
|
||||
/* Global setup to run once before all tests */
|
||||
globalSetup: require.resolve('./global-setup'),
|
||||
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
|
||||
use: {
|
||||
/* Base URL to use in actions like `await page.goto('/')`. */
|
||||
baseURL: 'http://localhost:4200',
|
||||
|
||||
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
|
||||
trace: 'on-first-retry',
|
||||
|
||||
/* Run in headless mode for environments without display server */
|
||||
headless: true,
|
||||
},
|
||||
|
||||
/* Configure projects for major browsers */
|
||||
projects: [
|
||||
{
|
||||
name: `@activepieces/${AP_EDITION}`,
|
||||
use: {
|
||||
...devices['Desktop Chrome'],
|
||||
headless: true,
|
||||
},
|
||||
testDir: editionConfig.testDir,
|
||||
},
|
||||
],
|
||||
|
||||
/* Run your local dev server before starting the tests */
|
||||
webServer: {
|
||||
command: process.env.CI
|
||||
? 'npm run dev'
|
||||
: 'export $(cat .env.e2e | xargs) && npm run dev',
|
||||
url: 'http://localhost:4200/api/v1/flags',
|
||||
reuseExistingServer: !process.env.CI,
|
||||
timeout: 100000,
|
||||
stdout: 'pipe',
|
||||
},
|
||||
};
|
||||
|
||||
export default defineConfig(config);
|
||||
37
activepieces-fork/packages/tests-e2e/project.json
Normal file
37
activepieces-fork/packages/tests-e2e/project.json
Normal file
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"name": "tests-e2e",
|
||||
"$schema": "../../node_modules/nx/schemas/project-schema.json",
|
||||
"sourceRoot": "packages/tests-e2e",
|
||||
"projectType": "application",
|
||||
"targets": {
|
||||
"test-e2e": {
|
||||
"executor": "nx:run-commands",
|
||||
"options": {
|
||||
"commands": [
|
||||
"npx playwright test --config=packages/tests-e2e/playwright.config.ts"
|
||||
]
|
||||
}
|
||||
},
|
||||
"test-checkly": {
|
||||
"executor": "nx:run-commands",
|
||||
"options": {
|
||||
"commands": [
|
||||
"npx checkly test --config=packages/tests-e2e/checkly.config.ts --reporter=github --record"
|
||||
]
|
||||
}
|
||||
},
|
||||
"deploy-checkly": {
|
||||
"executor": "nx:run-commands",
|
||||
"options": {
|
||||
"commands": [
|
||||
"npx checkly deploy"
|
||||
]
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"executor": "@nx/eslint:lint",
|
||||
"outputs": ["{options.outputFile}"]
|
||||
}
|
||||
},
|
||||
"tags": []
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import * as path from 'path'
|
||||
import { BrowserCheck } from 'checkly/constructs'
|
||||
|
||||
new BrowserCheck('webhook-should-return-response-check', {
|
||||
name: 'Webhook Should Return Response',
|
||||
frequency: 30, // every 30 minutes
|
||||
locations: ['eu-west-1'],
|
||||
code: {
|
||||
entrypoint: path.join(__dirname, 'webhook-should-return-response.spec.ts')
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,49 @@
|
||||
import { test, expect } from '../../../fixtures';
|
||||
|
||||
test.describe('Webhooks', () => {
|
||||
test('should handle webhook with return response', async ({ page, flowsPage, builderPage }) => {
|
||||
test.setTimeout(120000);
|
||||
|
||||
await flowsPage.waitFor();
|
||||
|
||||
await flowsPage.newFlowFromScratch();
|
||||
|
||||
await builderPage.selectInitialTrigger({
|
||||
piece: 'Webhook',
|
||||
trigger: 'Catch Webhook'
|
||||
});
|
||||
|
||||
const webhookInput = page.locator('input.grow.bg-background');
|
||||
const webhookUrl = await webhookInput.inputValue();
|
||||
const runVersion = Math.floor(Math.random() * 100000);
|
||||
const urlWithParams = `${webhookUrl}/sync?targetRunVersion=${runVersion}`;
|
||||
|
||||
await builderPage.testTrigger();
|
||||
|
||||
await page.context().request.get(urlWithParams);
|
||||
await page.waitForTimeout(5000);
|
||||
|
||||
await builderPage.addAction({
|
||||
piece: 'Webhook',
|
||||
action: 'Return Response'
|
||||
});
|
||||
|
||||
//clear
|
||||
await page.locator('div.cm-activeLine.cm-line').fill(
|
||||
''
|
||||
);
|
||||
|
||||
await page.locator('div.cm-activeLine.cm-line').fill(
|
||||
'{"targetRunVersion": "{{trigger[\'queryParams\'][\'targetRunVersion\']}}"}'
|
||||
);
|
||||
|
||||
await page.waitForTimeout(1000);
|
||||
await builderPage.publishFlow();
|
||||
|
||||
const response = await page.context().request.get(urlWithParams);
|
||||
const body = await response.json();
|
||||
|
||||
expect(body.targetRunVersion).toBe(runVersion.toString());
|
||||
});
|
||||
|
||||
});
|
||||
@@ -0,0 +1,7 @@
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
test.describe('Enterprise Edition - Placeholder Tests', () => {
|
||||
test('dummy test to ensure test suite runs successfully', async () => {
|
||||
expect(true).toBe(true);
|
||||
});
|
||||
});
|
||||
10
activepieces-fork/packages/tests-e2e/tsconfig.json
Normal file
10
activepieces-fork/packages/tests-e2e/tsconfig.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"sourceMap": false,
|
||||
"outDir": "../../dist/out-tsc",
|
||||
"allowJs": true,
|
||||
"types": ["node"]
|
||||
},
|
||||
"include": ["**/*.ts", "**/*.js", "playwright.config.ts"]
|
||||
}
|
||||
Reference in New Issue
Block a user