From 3fae3f06311997358b39118f7de2c5a5f15ee812 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Fri, 20 Oct 2023 14:29:22 +0530 Subject: [PATCH 1/3] ci: Init automated UI tests --- .github/helper/install.sh | 49 ++++++++++++ .github/helper/install_dependencies.sh | 17 +++++ .github/helper/site_config.json | 20 +++++ .github/workflows/ci.yml | 4 +- .github/workflows/ui-test.yml | 100 +++++++++++++++++++++++++ frontend/cypress.config.ts | 13 ++++ frontend/cypress/e2e/landing.cy.ts | 8 ++ frontend/cypress/support/commands.ts | 51 +++++++++++++ frontend/cypress/support/e2e.ts | 20 +++++ frontend/cypress/tsconfig.json | 11 +++ frontend/package.json | 5 +- frontend/tsconfig.json | 2 +- website_builder/www/builder.html | 5 +- 13 files changed, 298 insertions(+), 7 deletions(-) create mode 100644 .github/helper/install.sh create mode 100644 .github/helper/install_dependencies.sh create mode 100644 .github/helper/site_config.json create mode 100644 .github/workflows/ui-test.yml create mode 100644 frontend/cypress.config.ts create mode 100644 frontend/cypress/e2e/landing.cy.ts create mode 100644 frontend/cypress/support/commands.ts create mode 100644 frontend/cypress/support/e2e.ts create mode 100644 frontend/cypress/tsconfig.json diff --git a/.github/helper/install.sh b/.github/helper/install.sh new file mode 100644 index 00000000..f5edea00 --- /dev/null +++ b/.github/helper/install.sh @@ -0,0 +1,49 @@ +#!/bin/bash +set -e +cd ~ || exit + +echo "Setting Up Bench..." + +pip install frappe-bench +bench -v init frappe-bench --skip-assets --python "$(which python)" +cd ./frappe-bench || exit + +bench -v setup requirements + +echo "Setting Up Builder App..." +bench get-app builder "${GITHUB_WORKSPACE}" + +echo "Setting Up Sites & Database..." + +mkdir ~/frappe-bench/sites/builder.test +cp "${GITHUB_WORKSPACE}/.github/helper/site_config.json" ~/frappe-bench/sites/builder.test/site_config.json + +mariadb --host 127.0.0.1 --port 3306 -u root -p123 -e "SET GLOBAL character_set_server = 'utf8mb4'"; +mariadb --host 127.0.0.1 --port 3306 -u root -p123 -e "SET GLOBAL collation_server = 'utf8mb4_unicode_ci'"; + +mariadb --host 127.0.0.1 --port 3306 -u root -p123 -e "CREATE DATABASE test_builder"; +mariadb --host 127.0.0.1 --port 3306 -u root -p123 -e "CREATE USER 'test_builder'@'localhost' IDENTIFIED BY 'test_builder'"; +mariadb --host 127.0.0.1 --port 3306 -u root -p123 -e "GRANT ALL PRIVILEGES ON \`test_builder\`.* TO 'test_builder'@'localhost'"; + +mariadb --host 127.0.0.1 --port 3306 -u root -p123 -e "FLUSH PRIVILEGES"; + + +echo "Setting Up Procfile..." + +sed -i 's/^watch:/# watch:/g' Procfile +sed -i 's/^schedule:/# schedule:/g' Procfile + + +echo "Starting Bench..." + +bench start &> bench_start.log & + +CI=Yes bench build & +build_pid=$! + +bench --site builder.test reinstall --yes +bench --site builder.test install-app builder +bench --site builder.test execute builder.search.build_index_if_not_exists + +# wait till assets are built succesfully +wait $build_pid diff --git a/.github/helper/install_dependencies.sh b/.github/helper/install_dependencies.sh new file mode 100644 index 00000000..fdcd920e --- /dev/null +++ b/.github/helper/install_dependencies.sh @@ -0,0 +1,17 @@ +#!/bin/bash +set -e + +echo "Setting Up System Dependencies..." + +# redis repository +curl -fsSL https://packages.redis.io/gpg | sudo gpg --dearmor -o /usr/share/keyrings/redis-archive-keyring.gpg +echo "deb [signed-by=/usr/share/keyrings/redis-archive-keyring.gpg] https://packages.redis.io/deb $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/redis.list + +sudo apt update +sudo apt install libcups2-dev redis mariadb-client-10.6 + +install_wkhtmltopdf() { + wget -q https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6-1/wkhtmltox_0.12.6-1.focal_amd64.deb + sudo apt install ./wkhtmltox_0.12.6-1.focal_amd64.deb +} +install_wkhtmltopdf & diff --git a/.github/helper/site_config.json b/.github/helper/site_config.json new file mode 100644 index 00000000..134aab8d --- /dev/null +++ b/.github/helper/site_config.json @@ -0,0 +1,20 @@ +{ + "db_host": "127.0.0.1", + "db_port": 3306, + "db_name": "test_builder", + "db_password": "test_builder", + "allow_tests": true, + "enable_ui_tests": true, + "db_type": "mariadb", + "auto_email_id": "test@example.com", + "mail_server": "smtp.example.com", + "mail_login": "test@example.com", + "mail_password": "test", + "admin_password": "admin", + "root_login": "root", + "root_password": "123", + "host_name": "http://builder.test:8000", + "monitor": 1, + "server_script_enabled": true, + "mute_emails": true +} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e30c9a05..519b50d4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,11 +4,11 @@ name: CI on: push: branches: - - develop + - main pull_request: concurrency: - group: develop-website_builder-${{ github.event.number }} + group: main-website_builder-${{ github.event.number }} cancel-in-progress: true jobs: diff --git a/.github/workflows/ui-test.yml b/.github/workflows/ui-test.yml new file mode 100644 index 00000000..bfbffaec --- /dev/null +++ b/.github/workflows/ui-test.yml @@ -0,0 +1,100 @@ +name: UI Test + +on: + pull_request: + push: + branches: [ main ] + +permissions: + contents: read + +jobs: + test: + runs-on: ubuntu-latest + if: ${{ github.repository_owner == 'frappe' }} + timeout-minutes: 60 + + strategy: + fail-fast: false + + name: UI Tests (Cypress) + + services: + mariadb: + image: mariadb:10.6 + env: + MARIADB_ROOT_PASSWORD: 123 + ports: + - 3306:3306 + options: --health-cmd="mysqladmin ping" --health-interval=5s --health-timeout=2s --health-retries=3 + + steps: + - name: Clone + uses: actions/checkout@v3 + + - name: Setup Python + uses: actions/setup-python@v4 + with: + python-version: '3.10' + + - uses: actions/setup-node@v3 + with: + node-version: 16 + check-latest: true + + - name: Add to Hosts + run: | + echo "127.0.0.1 builder.test" | sudo tee -a /etc/hosts + + - name: Cache pip + uses: actions/cache@v3 + with: + path: ~/.cache/pip + key: ${{ runner.os }}-pip-${{ hashFiles('**/*requirements.txt', '**/pyproject.toml', '**/setup.py') }} + restore-keys: | + ${{ runner.os }}-pip- + ${{ runner.os }}- + + - name: Get yarn cache directory path + id: yarn-cache-dir-path + run: echo "::set-output name=dir::$(yarn cache dir)" + + - uses: actions/cache@v3 + id: yarn-cache + with: + path: ${{ steps.yarn-cache-dir-path.outputs.dir }} + key: ${{ runner.os }}-yarn-ui-${{ hashFiles('**/yarn.lock') }} + restore-keys: | + ${{ runner.os }}-yarn-ui- + + - name: Cache cypress binary + uses: actions/cache@v3 + with: + path: ~/.cache/Cypress + key: ${{ runner.os }}-cypress + + - name: Install Dependencies + run: | + bash ${GITHUB_WORKSPACE}/.github/helper/install_dependencies.sh + bash ${GITHUB_WORKSPACE}/.github/helper/install.sh + env: + BEFORE: ${{ env.GITHUB_EVENT_PATH.before }} + AFTER: ${{ env.GITHUB_EVENT_PATH.after }} + + - name: Site Setup + run: | + cd ~/frappe-bench/ + bench --site builder.test execute frappe.utils.install.complete_setup_wizard + bench --site builder.test execute frappe.tests.ui_test_helpers.create_test_user + + - name: UI Tests + run: cd ~/frappe-bench/apps/gameplan/frontend && yarn test + + - name: Stop server + run: | + ps -ef | grep "[f]rappe serve" | awk '{print $2}' | xargs kill -s SIGINT + sleep 5 + + - name: Show bench output + if: ${{ always() }} + run: cat ~/frappe-bench/bench_start.log || true diff --git a/frontend/cypress.config.ts b/frontend/cypress.config.ts new file mode 100644 index 00000000..98e70ca4 --- /dev/null +++ b/frontend/cypress.config.ts @@ -0,0 +1,13 @@ +import { defineConfig } from "cypress"; + +module.exports = defineConfig({ + projectId: "jvejd7", + e2e: { + baseUrl: "http://builder.test:8000", + adminPassword: "admin", + }, + retries: { + runMode: 2, + openMode: 0, + }, +}); diff --git a/frontend/cypress/e2e/landing.cy.ts b/frontend/cypress/e2e/landing.cy.ts new file mode 100644 index 00000000..dc7fd2d9 --- /dev/null +++ b/frontend/cypress/e2e/landing.cy.ts @@ -0,0 +1,8 @@ +describe("Builder Landing", () => { + before(() => { + cy.login(); + }); + it("Open builder page", () => { + cy.visit("builder/home"); + }); +}); diff --git a/frontend/cypress/support/commands.ts b/frontend/cypress/support/commands.ts new file mode 100644 index 00000000..eb2286dd --- /dev/null +++ b/frontend/cypress/support/commands.ts @@ -0,0 +1,51 @@ +/// +// *********************************************** +// This example commands.ts shows you how to +// create various custom commands and overwrite +// existing commands. +// +// For more comprehensive examples of custom +// commands please read more here: +// https://on.cypress.io/custom-commands +// *********************************************** +// +// +// -- This is a parent command -- +// Cypress.Commands.add('login', (email, password) => { ... }) +// +// +// -- This is a child command -- +// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) +// +// +// -- This is a dual command -- +// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) +// +// +// -- This will overwrite an existing command -- +// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) +// +// declare global { +// namespace Cypress { +// interface Chainable { +// login(email: string, password: string): Chainable +// drag(subject: string, options?: Partial): Chainable +// dismiss(subject: string, options?: Partial): Chainable +// visit(originalFn: CommandOriginalFn, url: string, options: Partial): Chainable +// } +// } +// } + +Cypress.Commands.add("login", (email, password) => { + if (!email) { + email = Cypress.config("testUser") || "Administrator"; + } + if (!password) { + password = Cypress.config("adminPassword"); + } + cy.request({ + url: "/api/method/login", + method: "POST", + body: { usr: email, pwd: password }, + }); +}); diff --git a/frontend/cypress/support/e2e.ts b/frontend/cypress/support/e2e.ts new file mode 100644 index 00000000..f80f74f8 --- /dev/null +++ b/frontend/cypress/support/e2e.ts @@ -0,0 +1,20 @@ +// *********************************************************** +// This example support/e2e.ts is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import './commands' + +// Alternatively you can use CommonJS syntax: +// require('./commands') \ No newline at end of file diff --git a/frontend/cypress/tsconfig.json b/frontend/cypress/tsconfig.json new file mode 100644 index 00000000..c3693385 --- /dev/null +++ b/frontend/cypress/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../tsconfig.json", + "include": [ + "../node_modules/cypress", + "*/*.ts" + ], + "compilerOptions": { + "noEmit": false, + "sourceMap": false + } +} \ No newline at end of file diff --git a/frontend/package.json b/frontend/package.json index f443984a..a7e26f90 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -7,7 +7,9 @@ "dev": "vite", "build": "vite build --base=/assets/website_builder/frontend/ && yarn copy-html-entry", "copy-html-entry": "cp ../website_builder/public/frontend/index.html ../website_builder/www/builder.html", - "preview": "vite preview" + "preview": "vite preview", + "test-local": "cypress open --e2e --browser chrome", + "test": "npx cypress run --record --key fa50a4df-569e-41bc-8600-850331fd1630" }, "dependencies": { "@tiptap/extension-color": "^2.0.4", @@ -31,6 +33,7 @@ "devDependencies": { "@vitejs/plugin-vue": "3", "autoprefixer": "^10.4.2", + "cypress": "^13.3.1", "eslint": "^8.38.0", "eslint-plugin-import": "^2.27.5", "eslint-plugin-vue": "^9.11.0", diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json index d76ed781..530ce5a7 100644 --- a/frontend/tsconfig.json +++ b/frontend/tsconfig.json @@ -21,7 +21,7 @@ "@/*": [ "src/*" ], - "tslib" : ["/node_modules/tslib/tslib.d.ts"] + "tslib" : ["/node_modules/tslib/"] }, "lib": [ "esnext", diff --git a/website_builder/www/builder.html b/website_builder/www/builder.html index c4f8c2a9..62f50792 100644 --- a/website_builder/www/builder.html +++ b/website_builder/www/builder.html @@ -7,8 +7,8 @@ Frappe Builder - - + +
@@ -18,6 +18,5 @@ - From a0ec44161ec31307186a64eedf16775d1fc147f7 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Sat, 21 Oct 2023 21:28:36 +0530 Subject: [PATCH 2/3] ci: Update node version --- .github/workflows/ui-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ui-test.yml b/.github/workflows/ui-test.yml index bfbffaec..057e7225 100644 --- a/.github/workflows/ui-test.yml +++ b/.github/workflows/ui-test.yml @@ -39,7 +39,7 @@ jobs: - uses: actions/setup-node@v3 with: - node-version: 16 + node-version: 18 check-latest: true - name: Add to Hosts From 956074319aacdf795e49759470fab857237e2839 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Sun, 22 Oct 2023 15:23:59 +0530 Subject: [PATCH 3/3] ci: fix app name --- .github/helper/install.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/helper/install.sh b/.github/helper/install.sh index f5edea00..8b8de45a 100644 --- a/.github/helper/install.sh +++ b/.github/helper/install.sh @@ -42,8 +42,7 @@ CI=Yes bench build & build_pid=$! bench --site builder.test reinstall --yes -bench --site builder.test install-app builder -bench --site builder.test execute builder.search.build_index_if_not_exists +bench --site builder.test install-app website_builder # wait till assets are built succesfully wait $build_pid