This is an automated email from the ASF dual-hosted git repository. maximebeauchemin pushed a commit to branch cypress-docker-compose in repository https://gitbox.apache.org/repos/asf/superset.git
commit 29befe3feb56d3783b35cb0f7705f2ef6122f48a Author: Maxime Beauchemin <[email protected]> AuthorDate: Mon Jan 6 18:33:26 2025 -0800 progress --- docker-compose.yml | 2 + docker/docker-bootstrap.sh | 7 ++- docker/docker-entrypoint-initdb.d/cypress-init.sh | 28 ++++++++++ docker/docker-init.sh | 19 +++---- docker/pythonpath_dev/superset_config.py | 11 ++++ docs/docs/contributing/development.mdx | 65 ---------------------- docs/docs/contributing/howtos.mdx | 16 +----- .../cypress-base/cypress/support/commands.ts | 37 ++++++++++++ .../cypress/support/component-index.html | 12 ++++ .../cypress-base/cypress/support/component.ts | 39 +++++++++++++ superset/config.py | 4 +- tests/integration_tests/superset_test_config.py | 1 + 12 files changed, 146 insertions(+), 95 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 471ac9363d..45c14c08ef 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -89,6 +89,8 @@ services: restart: unless-stopped ports: - 8088:8088 + # When in cypress-mode -> + - 8081:8081 extra_hosts: - "host.docker.internal:host-gateway" user: *superset-user diff --git a/docker/docker-bootstrap.sh b/docker/docker-bootstrap.sh index 1f7f17bb59..5a4f9b1cd8 100755 --- a/docker/docker-bootstrap.sh +++ b/docker/docker-bootstrap.sh @@ -26,11 +26,14 @@ if [ "$DEV_MODE" == "true" ]; then fi fi REQUIREMENTS_LOCAL="/app/docker/requirements-local.txt" +PORT=${PORT:-8088} # If Cypress run – overwrite the password for admin and export env variables if [ "$CYPRESS_CONFIG" == "true" ]; then export SUPERSET_CONFIG=tests.integration_tests.superset_test_config export SUPERSET_TESTENV=true - export SUPERSET__SQLALCHEMY_DATABASE_URI=postgresql+psycopg2://superset:superset@db:5432/superset + export POSTGRES_DB=superset_cypress + export SUPERSET__SQLALCHEMY_DATABASE_URI=postgresql+psycopg2://superset:superset@db:5432/superset_cypress + PORT=8081 fi if [[ "$DATABASE_DIALECT" == postgres* ]] ; then echo "Installing postgres requirements" @@ -65,7 +68,7 @@ case "${1}" in ;; app) echo "Starting web app (using development server)..." - flask run -p 8088 --with-threads --reload --debugger --host=0.0.0.0 + flask run -p $PORT --with-threads --reload --debugger --host=0.0.0.0 ;; app-gunicorn) echo "Starting web app..." diff --git a/docker/docker-entrypoint-initdb.d/cypress-init.sh b/docker/docker-entrypoint-initdb.d/cypress-init.sh new file mode 100755 index 0000000000..4e1bc76c73 --- /dev/null +++ b/docker/docker-entrypoint-initdb.d/cypress-init.sh @@ -0,0 +1,28 @@ +#!/usr/bin/env bash + +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +# ------------------------------------------------------------------------ +# Creates the examples database and respective user. This database location +# and access credentials are defined on the environment variables +# ------------------------------------------------------------------------ +set -e + +psql -v ON_ERROR_STOP=1 --username "${POSTGRES_USER}" <<-EOSQL + CREATE DATABASE superset_cypress; +EOSQL diff --git a/docker/docker-init.sh b/docker/docker-init.sh index 0f93058b73..d6ac229dbd 100755 --- a/docker/docker-init.sh +++ b/docker/docker-init.sh @@ -30,15 +30,9 @@ fi echo_step() { cat <<EOF - ###################################################################### - - Init Step ${1}/${STEP_CNT} [${2}] -- ${3} - - ###################################################################### - EOF } ADMIN_PASSWORD="${ADMIN_PASSWORD:-admin}" @@ -47,7 +41,8 @@ if [ "$CYPRESS_CONFIG" == "true" ]; then ADMIN_PASSWORD="general" export SUPERSET_CONFIG=tests.integration_tests.superset_test_config export SUPERSET_TESTENV=true - export SUPERSET__SQLALCHEMY_DATABASE_URI=postgresql+psycopg2://superset:superset@db:5432/superset + export POSTGRES_DB=superset_cypress + export SUPERSET__SQLALCHEMY_DATABASE_URI=postgresql+psycopg2://superset:superset@db:5432/superset_cypress fi # Initialize the database echo_step "1" "Starting" "Applying DB migrations" @@ -57,11 +52,11 @@ echo_step "1" "Complete" "Applying DB migrations" # Create an admin user echo_step "2" "Starting" "Setting up admin user ( admin / $ADMIN_PASSWORD )" superset fab create-admin \ - --username admin \ - --firstname Superset \ - --lastname Admin \ - --email [email protected] \ - --password "$ADMIN_PASSWORD" + --username admin \ + --firstname Superset \ + --lastname Admin \ + --email [email protected] \ + --password "$ADMIN_PASSWORD" echo_step "2" "Complete" "Setting up admin user" # Create default roles and permissions echo_step "3" "Starting" "Setting up roles and perms" diff --git a/docker/pythonpath_dev/superset_config.py b/docker/pythonpath_dev/superset_config.py index d435c8826c..786bbc8a84 100644 --- a/docker/pythonpath_dev/superset_config.py +++ b/docker/pythonpath_dev/superset_config.py @@ -22,6 +22,7 @@ # import logging import os +import sys from celery.schedules import crontab from flask_caching.backends.filesystemcache import FileSystemCache @@ -107,6 +108,16 @@ SQLLAB_CTAS_NO_LIMIT = True log_level_text = os.getenv("SUPERSET_LOG_LEVEL", "INFO") LOG_LEVEL = getattr(logging, log_level_text.upper(), logging.INFO) +if os.getenv("CYPRESS_CONFIG") == "true": + base_dir = os.path.dirname(__file__) + module_folder = os.path.abspath( + os.path.join(base_dir, "../../tests/integration_tests/") + ) + sys.path.insert(0, module_folder) + from superset_test_config import * # noqa + + sys.path.pop(0) + # # Optionally import superset_config_docker.py (which will have been included on # the PYTHONPATH) in order to allow for local settings to be overridden diff --git a/docs/docs/contributing/development.mdx b/docs/docs/contributing/development.mdx index f7925ff730..7a61432697 100644 --- a/docs/docs/contributing/development.mdx +++ b/docs/docs/contributing/development.mdx @@ -631,71 +631,6 @@ To run a single test file: npm run test -- path/to/file.js ``` -### Integration Testing - -We use [Cypress](https://www.cypress.io/) for integration tests. To open Cypress and explore tests first setup and run test server: - -```bash -export SUPERSET_CONFIG=tests.integration_tests.superset_test_config -export SUPERSET_TESTENV=true -export CYPRESS_BASE_URL="http://localhost:8081" -superset db upgrade -superset load_test_users -superset load-examples --load-test-data -superset init -superset run --port 8081 -``` - -Run Cypress tests: - -```bash -cd superset-frontend -npm run build-instrumented - -cd cypress-base -npm install - -# run tests via headless Chrome browser (requires Chrome 64+) -npm run cypress-run-chrome - -# run tests from a specific file -npm run cypress-run-chrome -- --spec cypress/e2e/explore/link.test.ts - -# run specific file with video capture -npm run cypress-run-chrome -- --spec cypress/e2e/dashboard/index.test.js --config video=true - -# to open the cypress ui -npm run cypress-debug - -# to point cypress to a url other than the default (http://localhost:8088) set the environment variable before running the script -# e.g., CYPRESS_BASE_URL="http://localhost:9000" -CYPRESS_BASE_URL=<your url> npm run cypress open -``` - -See [`superset-frontend/cypress_build.sh`](https://github.com/apache/superset/blob/master/superset-frontend/cypress_build.sh). - -As an alternative you can use docker compose environment for testing: - -Make sure you have added below line to your /etc/hosts file: -`127.0.0.1 db` - -If you already have launched Docker environment please use the following command to ensure a fresh database instance: -`docker compose down -v` - -Launch environment: - -`CYPRESS_CONFIG=true docker compose up --build` - -It will serve the backend and frontend on port 8088. - -Run Cypress tests: - -```bash -cd cypress-base -npm install -npm run cypress open -``` - ### Debugging Server App #### Local diff --git a/docs/docs/contributing/howtos.mdx b/docs/docs/contributing/howtos.mdx index 698d4ddf6f..b18f5d7e99 100644 --- a/docs/docs/contributing/howtos.mdx +++ b/docs/docs/contributing/howtos.mdx @@ -225,22 +225,10 @@ npm run test -- path/to/file.js ### e2e Integration Testing -For e2e testing, we recommend that you use a `docker-compose` backed-setup - -Alternatively, you can go lower level and set things up in your -development environment by following these steps: - -First set up a python/flask backend: +For e2e testing, we recommend that you use a `docker compose` backend ```bash -export SUPERSET_CONFIG=tests.integration_tests.superset_test_config -export SUPERSET_TESTENV=true -export CYPRESS_BASE_URL="http://localhost:8081" -superset db upgrade -superset load_test_users -superset init -superset load-examples --load-test-data -superset run --port 8081 +CYPRESS_CONFIG=true docker compose up ``` In another terminal, prepare the frontend and run Cypress tests: diff --git a/superset-frontend/cypress-base/cypress/support/commands.ts b/superset-frontend/cypress-base/cypress/support/commands.ts new file mode 100644 index 0000000000..95857aea4c --- /dev/null +++ b/superset-frontend/cypress-base/cypress/support/commands.ts @@ -0,0 +1,37 @@ +/// <reference types="cypress" /> +// *********************************************** +// 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<void> +// drag(subject: string, options?: Partial<TypeOptions>): Chainable<Element> +// dismiss(subject: string, options?: Partial<TypeOptions>): Chainable<Element> +// visit(originalFn: CommandOriginalFn, url: string, options: Partial<VisitOptions>): Chainable<Element> +// } +// } +// } diff --git a/superset-frontend/cypress-base/cypress/support/component-index.html b/superset-frontend/cypress-base/cypress/support/component-index.html new file mode 100644 index 0000000000..faf3b5f43b --- /dev/null +++ b/superset-frontend/cypress-base/cypress/support/component-index.html @@ -0,0 +1,12 @@ +<!doctype html> +<html> + <head> + <meta charset="utf-8" /> + <meta http-equiv="X-UA-Compatible" content="IE=edge" /> + <meta name="viewport" content="width=device-width,initial-scale=1.0" /> + <title>Components App</title> + </head> + <body> + <div data-cy-root></div> + </body> +</html> diff --git a/superset-frontend/cypress-base/cypress/support/component.ts b/superset-frontend/cypress-base/cypress/support/component.ts new file mode 100644 index 0000000000..69e1fa9661 --- /dev/null +++ b/superset-frontend/cypress-base/cypress/support/component.ts @@ -0,0 +1,39 @@ +// *********************************************************** +// This example support/component.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') + +import { mount } from 'cypress/react'; + +// Augment the Cypress namespace to include type definitions for +// your custom command. +// Alternatively, can be defined in cypress/support/component.d.ts +// with a <reference path="./component" /> at the top of your spec. +declare global { + namespace Cypress { + interface Chainable { + mount: typeof mount; + } + } +} + +Cypress.Commands.add('mount', mount); + +// Example use: +// cy.mount(<MyComponent />) diff --git a/superset/config.py b/superset/config.py index f36ffade3c..c40e11a55e 100644 --- a/superset/config.py +++ b/superset/config.py @@ -58,7 +58,7 @@ from superset.stats_logger import DummyStatsLogger from superset.superset_typing import CacheConfig from superset.tasks.types import ExecutorType from superset.utils import core as utils -from superset.utils.core import is_test, NO_TIME_RANGE, parse_boolean_string +from superset.utils.core import NO_TIME_RANGE, parse_boolean_string from superset.utils.encrypt import SQLAlchemyUtilsAdapter from superset.utils.log import DBEventLogger from superset.utils.logging_configurator import DefaultLoggingConfigurator @@ -1923,7 +1923,7 @@ if CONFIG_PATH_ENV_VAR in os.environ: "Failed to import config for %s=%s", CONFIG_PATH_ENV_VAR, cfg_path ) raise -elif importlib.util.find_spec("superset_config") and not is_test(): +elif importlib.util.find_spec("superset_config"): try: # pylint: disable=import-error,wildcard-import,unused-wildcard-import import superset_config diff --git a/tests/integration_tests/superset_test_config.py b/tests/integration_tests/superset_test_config.py index 4358ba875b..18cd829e6e 100644 --- a/tests/integration_tests/superset_test_config.py +++ b/tests/integration_tests/superset_test_config.py @@ -151,3 +151,4 @@ CUSTOM_TEMPLATE_PROCESSORS = { } PRESERVE_CONTEXT_ON_EXCEPTION = False +print("Loaded TEST config for INTEGRATION tests")
