mirror of
https://github.com/penpot/penpot.git
synced 2026-04-05 10:52:57 +02:00
🐛 Fix e2e tests for plugins
This commit is contained in:
@@ -126,6 +126,6 @@
|
||||
|
||||
(defn check-permission
|
||||
[plugin-id permission]
|
||||
(or (= plugin-id "TEST")
|
||||
(or (= plugin-id "00000000-0000-0000-0000-000000000000")
|
||||
(let [{:keys [permissions]} (dm/get-in @registry [:data plugin-id])]
|
||||
(contains? permissions permission))))
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
(let [;; ==== Setup
|
||||
store (ths/setup-store (cthf/sample-file :file1 :page-label :page1))
|
||||
|
||||
^js context (api/create-context "TEST")
|
||||
^js context (api/create-context "00000000-0000-0000-0000-000000000000")
|
||||
|
||||
_ (set! st/state store)
|
||||
|
||||
|
||||
@@ -28,5 +28,5 @@ export default [
|
||||
files: ['**/*.js', '**/*.jsx'],
|
||||
rules: {},
|
||||
},
|
||||
{ ignores: ['vite.config.ts'] },
|
||||
{ ignores: ['vite.config.ts', 'vitest.setup.ts'] },
|
||||
];
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -11,7 +11,7 @@ import comments from './plugins/create-comments';
|
||||
import { Agent } from './utils/agent';
|
||||
|
||||
describe('Plugins', () => {
|
||||
it.only('create board - text - rectable', async () => {
|
||||
it('create board - text - rectable', async () => {
|
||||
const agent = await Agent();
|
||||
const result = await agent.runCode(testingPlugin.toString(), {
|
||||
screenshot: 'create-board-text-rect',
|
||||
@@ -29,6 +29,7 @@ describe('Plugins', () => {
|
||||
|
||||
it('create grid layout', async () => {
|
||||
const agent = await Agent();
|
||||
|
||||
const result = await agent.runCode(grid.toString(), {
|
||||
screenshot: 'create-gridlayout',
|
||||
});
|
||||
@@ -83,9 +84,9 @@ describe('Plugins', () => {
|
||||
|
||||
it('comments', async () => {
|
||||
const agent = await Agent();
|
||||
console.log(comments.toString());
|
||||
const result = await agent.runCode(comments.toString(), {
|
||||
screenshot: 'create-comments',
|
||||
avoidSavedStatus: true,
|
||||
});
|
||||
expect(result).toMatchSnapshot();
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
import puppeteer, { ConsoleMessage } from 'puppeteer';
|
||||
import { PenpotApi } from './api';
|
||||
import { getFileUrl } from './get-file-url';
|
||||
import { idObjectToArray } from './clean-id';
|
||||
@@ -56,7 +56,10 @@ export async function Agent() {
|
||||
console.log('File URL:', fileUrl);
|
||||
|
||||
console.log('Launching browser...');
|
||||
const browser = await puppeteer.launch({args: ['--ignore-certificate-errors']});
|
||||
const browser = await puppeteer.launch({
|
||||
headless: process.env['E2E_HEADLESS'] !== 'false',
|
||||
args: ['--ignore-certificate-errors'],
|
||||
});
|
||||
const page = await browser.newPage();
|
||||
|
||||
await page.setViewport({ width: 1920, height: 1080 });
|
||||
@@ -88,8 +91,11 @@ export async function Agent() {
|
||||
|
||||
const finish = async () => {
|
||||
console.log('Deleting file and closing browser...');
|
||||
await penpotApi.deleteFile(file['~:id']);
|
||||
await browser.close();
|
||||
// TODO
|
||||
// await penpotApi.deleteFile(file['~:id']);
|
||||
if (process.env['E2E_CLOSE_BROWSER'] !== 'false') {
|
||||
await browser.close();
|
||||
}
|
||||
console.log('Clean up done.');
|
||||
};
|
||||
|
||||
@@ -99,11 +105,9 @@ export async function Agent() {
|
||||
options: {
|
||||
screenshot?: string;
|
||||
autoFinish?: boolean;
|
||||
avoidSavedStatus?: boolean;
|
||||
} = {
|
||||
screenshot: '',
|
||||
autoFinish: true,
|
||||
avoidSavedStatus: false,
|
||||
},
|
||||
) {
|
||||
const autoFinish = options.autoFinish ?? true;
|
||||
@@ -112,28 +116,27 @@ export async function Agent() {
|
||||
await page.evaluate((testingPlugin) => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
(globalThis as any).ɵloadPlugin({
|
||||
pluginId: 'TEST',
|
||||
pluginId: '00000000-0000-0000-0000-000000000000',
|
||||
name: 'Test',
|
||||
code: `
|
||||
(${testingPlugin})();
|
||||
`,
|
||||
icon: '',
|
||||
description: '',
|
||||
permissions: ['content:read', 'content:write'],
|
||||
permissions: [
|
||||
'content:read',
|
||||
'content:write',
|
||||
'library:read',
|
||||
'library:write',
|
||||
'user:read',
|
||||
'comment:read',
|
||||
'comment:write',
|
||||
'allow:downloads',
|
||||
'allow:localstorage',
|
||||
],
|
||||
});
|
||||
}, code);
|
||||
|
||||
if (!options.avoidSavedStatus) {
|
||||
console.log('Waiting for save status...');
|
||||
await page.waitForSelector(
|
||||
'.main_ui_workspace_right_header__saved-status',
|
||||
{
|
||||
timeout: 10000,
|
||||
},
|
||||
);
|
||||
console.log('Save status found.');
|
||||
}
|
||||
|
||||
if (options.screenshot && screenshotsEnable) {
|
||||
console.log('Taking screenshot:', options.screenshot);
|
||||
await page.screenshot({
|
||||
@@ -141,30 +144,55 @@ export async function Agent() {
|
||||
});
|
||||
}
|
||||
|
||||
return new Promise((resolve) => {
|
||||
page.once('console', async (msg) => {
|
||||
const result = await new Promise((resolve) => {
|
||||
const handleConsole = async (msg: ConsoleMessage) => {
|
||||
const args = (await Promise.all(
|
||||
msg.args().map((arg) => arg.jsonValue()),
|
||||
)) as Record<string, unknown>[];
|
||||
)) as unknown[];
|
||||
|
||||
const result = Object.values(args[1]) as Shape[];
|
||||
const type = args[0];
|
||||
const data = args[1];
|
||||
|
||||
if (type !== 'objects' || !data || typeof data !== 'object') {
|
||||
console.log('Invalid console message, waiting for valid one...');
|
||||
page.once('console', handleConsole);
|
||||
return;
|
||||
}
|
||||
|
||||
const result = Object.values(data) as Shape[];
|
||||
|
||||
replaceIds(result);
|
||||
console.log('IDs replaced in result.');
|
||||
|
||||
resolve(result);
|
||||
};
|
||||
|
||||
if (autoFinish) {
|
||||
console.log('Auto finish enabled. Cleaning up...');
|
||||
finish();
|
||||
}
|
||||
});
|
||||
page.once('console', handleConsole);
|
||||
|
||||
console.log('Evaluating debug.dump_objects...');
|
||||
page.evaluate(`
|
||||
debug.dump_objects();
|
||||
`);
|
||||
});
|
||||
|
||||
await page.waitForNetworkIdle({ idleTime: 2000 });
|
||||
|
||||
// Wait for the update-file API call to complete
|
||||
if (process.env['E2E_WAIT_API_RESPONSE'] === 'true') {
|
||||
await page.waitForResponse(
|
||||
(response) =>
|
||||
response.url().includes('api/main/methods/update-file') &&
|
||||
response.status() === 200,
|
||||
{ timeout: 10000 },
|
||||
);
|
||||
}
|
||||
|
||||
if (autoFinish) {
|
||||
console.log('Auto finish enabled. Cleaning up...');
|
||||
await finish();
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
finish,
|
||||
};
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { FileRpc } from '../models/file-rpc.model';
|
||||
|
||||
const apiUrl = 'https://localhost:3449';
|
||||
|
||||
export async function PenpotApi() {
|
||||
@@ -8,8 +7,8 @@ export async function PenpotApi() {
|
||||
}
|
||||
|
||||
const body = JSON.stringify({
|
||||
'email': process.env['E2E_LOGIN_EMAIL'],
|
||||
'password': process.env['E2E_LOGIN_PASSWORD'],
|
||||
email: process.env['E2E_LOGIN_EMAIL'],
|
||||
password: process.env['E2E_LOGIN_PASSWORD'],
|
||||
});
|
||||
|
||||
const resultLoginRequest = await fetch(
|
||||
@@ -18,25 +17,18 @@ export async function PenpotApi() {
|
||||
credentials: 'include',
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: body
|
||||
body: body,
|
||||
},
|
||||
);
|
||||
|
||||
console.log("AAAAAAAAAAAA", 1, apiUrl)
|
||||
// console.log("AAAAAAAAAAAA", 2, resultLoginRequest);
|
||||
|
||||
console.dir(resultLoginRequest.headers, {depth:20});
|
||||
console.log('Document Cookies:', window.document.cookie);
|
||||
|
||||
const loginData = await resultLoginRequest.json();
|
||||
|
||||
|
||||
const authToken = resultLoginRequest.headers
|
||||
.get('set-cookie')
|
||||
?.split(';')
|
||||
.at(0);
|
||||
.getSetCookie()
|
||||
.find((cookie: string) => cookie.startsWith('auth-token='))
|
||||
?.split(';')[0];
|
||||
|
||||
if (!authToken) {
|
||||
throw new Error('Login failed');
|
||||
@@ -62,6 +54,9 @@ export async function PenpotApi() {
|
||||
'fdata/objects-map',
|
||||
'fdata/pointer-map',
|
||||
'fdata/shape-data-type',
|
||||
'fdata/path-data',
|
||||
'design-tokens/v1',
|
||||
'variants/v1',
|
||||
'components/v2',
|
||||
'styles/v2',
|
||||
'layout/grid',
|
||||
@@ -72,7 +67,9 @@ export async function PenpotApi() {
|
||||
},
|
||||
);
|
||||
|
||||
return (await createFileRequest.json()) as FileRpc;
|
||||
const fileData = (await createFileRequest.json()) as FileRpc;
|
||||
console.log('File data received:', fileData);
|
||||
return fileData;
|
||||
},
|
||||
deleteFile: async (fileId: string) => {
|
||||
const deleteFileRequest = await fetch(
|
||||
|
||||
@@ -6,5 +6,5 @@ export function getFileUrl(file: FileRpc) {
|
||||
const fileId = cleanId(file['~:id']);
|
||||
const pageId = cleanId(file['~:data']['~:pages'][0]);
|
||||
|
||||
return `http://localhost:3449/#/workspace/${projectId}/${fileId}?page-id=${pageId}`;
|
||||
return `https://localhost:3449/#/workspace/${projectId}/${fileId}?page-id=${pageId}`;
|
||||
}
|
||||
|
||||
@@ -7,13 +7,27 @@ export default defineConfig({
|
||||
testTimeout: 20000,
|
||||
watch: false,
|
||||
globals: true,
|
||||
environment: 'happy-dom',
|
||||
environment: 'node',
|
||||
environmentOptions: {
|
||||
happyDOM: {
|
||||
settings: {
|
||||
disableCSSFileLoading: true,
|
||||
disableJavaScriptFileLoading: true,
|
||||
disableJavaScriptEvaluation: true,
|
||||
enableFileSystemHttpRequests: false,
|
||||
navigator: {
|
||||
userAgent:
|
||||
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||
reporters: ['default'],
|
||||
coverage: {
|
||||
reportsDirectory: '../coverage/e2e',
|
||||
provider: 'v8',
|
||||
},
|
||||
setupFiles: ['dotenv/config', 'vitest.setup.ts']
|
||||
setupFiles: ['dotenv/config', 'vitest.setup.ts'],
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,3 +1 @@
|
||||
// import { vi } from 'vitest';
|
||||
|
||||
window.location.href = 'https://localhost:3449';
|
||||
process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0';
|
||||
|
||||
@@ -9,7 +9,10 @@
|
||||
```env
|
||||
E2E_LOGIN_EMAIL="test@penpot.app"
|
||||
E2E_LOGIN_PASSWORD="123123123"
|
||||
E2E_SCREENSHOTS= "true"
|
||||
E2E_SCREENSHOTS="true" # Enable/disable screenshots (default: false)
|
||||
E2E_HEADLESS="false" # Run browser in headless mode (default: true)
|
||||
E2E_CLOSE_BROWSER="true" # Close browser after tests (default: true)
|
||||
E2E_WAIT_API_RESPONSE="false" # Wait for update-file API response (default: false)
|
||||
```
|
||||
|
||||
2. **Run E2E Tests**
|
||||
@@ -77,5 +80,5 @@
|
||||
If you need to refresh all the snapshopts run the test with the update option:
|
||||
|
||||
```bash
|
||||
pnpm run test:e2e -- --update
|
||||
pnpm run test:e2e --update
|
||||
```
|
||||
|
||||
@@ -28,7 +28,9 @@ export const initPluginsRuntime = (contextBuilder: (id: string) => Context) => {
|
||||
try {
|
||||
console.log('%c[PLUGINS] Initialize runtime', 'color: #008d7c');
|
||||
setContextBuilder(contextBuilder);
|
||||
globalThisAny$.ɵcontext = contextBuilder('TEST');
|
||||
globalThisAny$.ɵcontext = contextBuilder(
|
||||
'00000000-0000-0000-0000-000000000000',
|
||||
);
|
||||
globalThis.ɵloadPlugin = ɵloadPlugin;
|
||||
globalThis.ɵloadPluginByUrl = ɵloadPluginByUrl;
|
||||
globalThis.ɵunloadPlugin = ɵunloadPlugin;
|
||||
|
||||
Reference in New Issue
Block a user