Skip to content

Commit

Permalink
feat: get docker-compose to work as the backend for Cypress tests (ap…
Browse files Browse the repository at this point in the history
  • Loading branch information
mistercrunch authored Jan 18, 2025
1 parent 2874096 commit 840773e
Show file tree
Hide file tree
Showing 15 changed files with 110 additions and 113 deletions.
2 changes: 2 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 5 additions & 3 deletions docker/docker-bootstrap.sh
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,13 @@ 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"
Expand Down Expand Up @@ -65,7 +67,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..."
Expand Down
28 changes: 28 additions & 0 deletions docker/docker-entrypoint-initdb.d/cypress-init.sh
Original file line number Diff line number Diff line change
@@ -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
20 changes: 7 additions & 13 deletions docker/docker-init.sh
Original file line number Diff line number Diff line change
Expand Up @@ -30,24 +30,18 @@ fi

echo_step() {
cat <<EOF
######################################################################
Init Step ${1}/${STEP_CNT} [${2}] -- ${3}
######################################################################
EOF
}
ADMIN_PASSWORD="${ADMIN_PASSWORD:-admin}"
# If Cypress run – overwrite the password for admin and export env variables
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"
Expand All @@ -57,11 +51,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"
Expand Down
13 changes: 13 additions & 0 deletions docker/pythonpath_dev/superset_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#
import logging
import os
import sys

from celery.schedules import crontab
from flask_caching.backends.filesystemcache import FileSystemCache
Expand Down Expand Up @@ -107,6 +108,18 @@ class CeleryConfig:
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":
# When running the service as a cypress backend, we need to import the config
# located @ tests/integration_tests/superset_test_config.py
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
Expand Down
65 changes: 0 additions & 65 deletions docs/docs/contributing/development.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -643,71 +643,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
Expand Down
19 changes: 5 additions & 14 deletions docs/docs/contributing/howtos.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -255,6 +243,9 @@ npm install
# run tests via headless Chrome browser (requires Chrome 64+)
npm run cypress-run-chrome
# use interactive mode to run tests, while keeping memory usage contained (default is 50!)
npx cypress open --config numTestsKeptInMemory=3
# run tests from a specific file
npm run cypress-run-chrome -- --spec cypress/e2e/explore/link.test.ts
Expand Down
8 changes: 6 additions & 2 deletions scripts/cypress_run.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,9 @@ def run_cypress_for_test_file(
group_id = f"matrix{group}-file{i}-{attempt}"
cmd = (
f"{XVFB_PRE_CMD} "
f'{cypress_cmd} --spec "{test_file}" --browser {browser} '
f'{cypress_cmd} --spec "{test_file}" '
f"--config numTestsKeptInMemory=0 "
f"--browser {browser} "
f"--record --group {group_id} --tag {REPO},{GITHUB_EVENT_NAME} "
f"--ci-build-id {build_id} "
f"-- {chrome_flags}"
Expand All @@ -64,7 +66,9 @@ def run_cypress_for_test_file(
os.environ.pop("CYPRESS_RECORD_KEY", None)
cmd = (
f"{XVFB_PRE_CMD} "
f"{cypress_cmd} --browser {browser} "
f"{cypress_cmd} "
f"--browser {browser} "
f"--config numTestsKeptInMemory=0 "
f'--spec "{test_file}" '
f"-- {chrome_flags}"
)
Expand Down
7 changes: 5 additions & 2 deletions superset-frontend/cypress-base/cypress.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,9 @@ export default eyesPlugin(
defineConfig({
chromeWebSecurity: false,
defaultCommandTimeout: 8000,
numTestsKeptInMemory: 0,
experimentalFetchPolyfill: true,
numTestsKeptInMemory: 5,
// Disabled after realizing this MESSES UP rison encoding in intricate ways
experimentalFetchPolyfill: false,
experimentalMemoryManagement: true,
requestTimeout: 10000,
video: false,
Expand Down Expand Up @@ -62,6 +63,7 @@ export default eyesPlugin(
}
return launchOptions;
});

// eslint-disable-next-line global-require
require('@cypress/code-coverage/task')(on, config);
on('task', verifyDownloadTasks);
Expand All @@ -70,6 +72,7 @@ export default eyesPlugin(
},
baseUrl: 'http://localhost:8088',
excludeSpecPattern: [],
experimentalRunAllSpecs: true,
specPattern: [
'cypress/e2e/**/*.{js,jsx,ts,tsx}',
'cypress/applitools/**/*.{js,jsx,ts,tsx}',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {
visitSampleChartFromList,
saveChartToDashboard,
interceptFiltering,
interceptFavoriteStatus,
} from '../explore/utils';
import { interceptGet as interceptDashboardGet } from '../dashboard/utils';

Expand All @@ -49,8 +50,10 @@ function confirmDelete() {

function visitChartList() {
interceptFiltering();
interceptFavoriteStatus();
cy.visit(CHART_LIST);
cy.wait('@filtering');
cy.wait('@favoriteStatus');
}

describe('Charts list', () => {
Expand Down Expand Up @@ -78,20 +81,15 @@ describe('Charts list', () => {
cy.wait('@get');
});

it('should show the newly added dashboards in a tooltip', () => {
it.only('should show the newly added dashboards in a tooltip', () => {
interceptDashboardGet();
visitSampleChartFromList('1 - Sample chart');
saveChartToDashboard('1 - Sample dashboard');
saveChartToDashboard('2 - Sample dashboard');
saveChartToDashboard('3 - Sample dashboard');
visitChartList();

cy.getBySel('count-crosslinks').should('be.visible');
cy.getBySel('crosslinks').first().trigger('mouseover');
cy.get('.antd5-tooltip')
.contains('3 - Sample dashboard')
.invoke('removeAttr', 'target')
.click();
cy.wait('@get');
});
});

Expand All @@ -116,7 +114,7 @@ describe('Charts list', () => {

it('should sort correctly in list mode', () => {
cy.getBySel('sort-header').eq(1).click();
cy.getBySel('table-row').first().contains('% Rural');
cy.getBySel('table-row').first().contains('Area Chart');
cy.getBySel('sort-header').eq(1).click();
cy.getBySel('table-row').first().contains("World's Population");
cy.getBySel('sort-header').eq(1).click();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,10 @@ function openMenu() {
}

function confirmDelete() {
cy.getBySel('delete-modal-input').type('DELETE');
cy.getBySel('modal-confirm-button').click();
// Wait for modal dialog to be present and visible
cy.get('[role="dialog"][aria-modal="true"]').should('be.visible');
cy.getBySel('delete-modal-input').should('be.visible').clear().type('DELETE');
cy.getBySel('modal-confirm-button').should('be.visible').click();
}

describe('Dashboards list', () => {
Expand Down
9 changes: 8 additions & 1 deletion superset-frontend/cypress-base/cypress/e2e/explore/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ export function interceptDelete() {
cy.intercept('DELETE', `/api/v1/chart/*`).as('delete');
}

export function interceptFavoriteStatus() {
cy.intercept('GET', '/api/v1/chart/favorite_status/*').as('favoriteStatus');
}

export function interceptUpdate() {
cy.intercept('PUT', `/api/v1/chart/*`).as('update');
}
Expand Down Expand Up @@ -68,7 +72,10 @@ export function saveChartToDashboard(dashboardName: string) {
interceptUpdate();
interceptExploreGet();

cy.getBySel('query-save-button').click();
cy.getBySel('query-save-button')
.should('be.enabled')
.should('not.be.disabled')
.click();
cy.getBySelLike('chart-modal').should('be.visible');
cy.get(
'[data-test="save-chart-modal-select-dashboard-form"] [aria-label="Select a dashboard"]',
Expand Down
Loading

0 comments on commit 840773e

Please sign in to comment.