UNPKG

spanwright

Version:

CLI tool to generate Cloud Spanner E2E testing framework projects with Go database tools and Playwright browser automation

218 lines (193 loc) โ€ข 10.9 kB
# Simplified Spanwright Makefile # Load environment variables -include .env export # Default values PROJECT_ID ?= test-project INSTANCE_ID ?= test-instance PRIMARY_DB_ID ?= primary-db SECONDARY_DB_ID ?= secondary-db DB_COUNT ?= 2 SCENARIO ?= example-01-basic-setup # Docker settings DOCKER_IMAGE ?= gcr.io/cloud-spanner-emulator/emulator DOCKER_CONTAINER_NAME ?= spanner-emulator DOCKER_SPANNER_PORT ?= 9010 .PHONY: help init clean start stop setup run-all test-e2e help: ## Show this help @echo "Spanwright E2E Testing Framework" @echo "================================" @echo "" @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(firstword $(MAKEFILE_LIST)) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}' init: ## Initialize project and check prerequisites @echo "๐Ÿš€ Initializing Spanwright project..." @$(MAKE) check-tools @$(MAKE) setup-playwright @echo "โœ… Project initialized successfully" check-tools: ## Check required tools @echo "๐Ÿ” Checking required tools..." @command -v wrench >/dev/null 2>&1 || { echo "โŒ wrench not found"; exit 1; } @command -v docker >/dev/null 2>&1 || { echo "โŒ docker not found"; exit 1; } @command -v node >/dev/null 2>&1 || { echo "โŒ node not found"; exit 1; } @$(MAKE) check-spalidate @echo "โœ… All tools available" check-spalidate: ## Check spalidate availability @command -v spalidate >/dev/null 2>&1 || { echo "โŒ spalidate not found - install from https://github.com/nu0ma/spalidate"; exit 1; } @echo "โœ… spalidate available" setup-playwright: ## Setup Playwright @echo "๐ŸŽญ Setting up Playwright..." @npm install @npx playwright install @echo "โœ… Playwright setup complete" start: ## Start Spanner emulator @echo "๐Ÿณ Starting Spanner emulator..." @if docker ps -a --format '{{.Names}}' | grep -q "^$(DOCKER_CONTAINER_NAME)$$"; then \ echo "๐Ÿ“ฆ Existing container found, restarting..."; \ docker stop $(DOCKER_CONTAINER_NAME) >/dev/null 2>&1 || true; \ docker rm $(DOCKER_CONTAINER_NAME) >/dev/null 2>&1 || true; \ fi @docker run -d --name $(DOCKER_CONTAINER_NAME) -p $(DOCKER_SPANNER_PORT):9010 $(DOCKER_IMAGE) >/dev/null @echo "โณ Waiting for emulator to be ready..." @sleep 15 @echo "๐Ÿ” Verifying emulator status..." @if ! docker ps | grep -q $(DOCKER_CONTAINER_NAME); then echo "โŒ Emulator container not running"; exit 1; fi @echo "โœ… Spanner emulator ready on localhost:$(DOCKER_SPANNER_PORT)" stop: ## Stop Spanner emulator @echo "๐Ÿ›‘ Stopping Spanner emulator..." @docker stop $(DOCKER_CONTAINER_NAME) 2>/dev/null || true @docker rm $(DOCKER_CONTAINER_NAME) 2>/dev/null || true clean: ## Clean up containers and artifacts @$(MAKE) stop @echo "๐Ÿงน Cleaning build artifacts..." @rm -rf test-results/ playwright-report/ setup: ## Setup databases and schemas @echo "๐Ÿ—๏ธ Setting up databases..." @$(MAKE) start @$(MAKE) setup-primary ifeq ($(DB_COUNT),2) @$(MAKE) setup-secondary endif @echo "โœ… Database setup complete" setup-primary: ## Setup primary database @echo "๐Ÿ”ถ Setting up primary database..." @echo "๐Ÿ“ก Creating Spanner instance $(INSTANCE_ID)..." @SPANNER_PROJECT_ID=$(PROJECT_ID) SPANNER_INSTANCE_ID=$(INSTANCE_ID) SPANNER_EMULATOR_HOST=localhost:$(DOCKER_SPANNER_PORT) wrench instance create 2>/dev/null || echo " โ„น๏ธ Instance $(INSTANCE_ID) already exists or has been created" @echo "๐Ÿ—„๏ธ Creating empty database $(PRIMARY_DB_ID)..." @mkdir -p ./tmp && echo "-- Empty schema for database creation" > ./tmp/schema.sql @SPANNER_PROJECT_ID=$(PROJECT_ID) SPANNER_INSTANCE_ID=$(INSTANCE_ID) SPANNER_DATABASE_ID=$(PRIMARY_DB_ID) SPANNER_EMULATOR_HOST=localhost:$(DOCKER_SPANNER_PORT) wrench create --directory="$$(pwd)/tmp" --schema_file=schema.sql 2>/dev/null || echo " โ„น๏ธ Database $(PRIMARY_DB_ID) already exists or has been created" @echo "๐Ÿ”„ Applying individual schema files from $(PRIMARY_SCHEMA_PATH)..." @for file in "$(PRIMARY_SCHEMA_PATH)"/*.sql; do \ if [ -f "$$file" ]; then \ echo " ๐Ÿ“„ Applying: $$file"; \ SPANNER_PROJECT_ID=$(PROJECT_ID) SPANNER_INSTANCE_ID=$(INSTANCE_ID) SPANNER_DATABASE_ID=$(PRIMARY_DB_ID) SPANNER_EMULATOR_HOST=localhost:$(DOCKER_SPANNER_PORT) wrench apply --ddl="$$file" || { echo "โŒ Failed to apply: $$file"; exit 1; }; \ fi; \ done @echo "โœ… Schema application completed for primary database" @echo "๐Ÿ”ง Setting up Go modules..." @go mod tidy >/dev/null 2>&1 @echo "๐ŸŒฑ Seeding primary database..." @SPANNER_EMULATOR_HOST=localhost:$(DOCKER_SPANNER_PORT) go run cmd/seed-injector/main.go --database-id $(PRIMARY_DB_ID) --fixture-dir "$$(pwd)/scenarios/$(SCENARIO)/fixtures/primary" || { echo "โŒ Failed to seed primary database"; exit 1; } @echo "โœ… Primary database ready" setup-secondary: ## Setup secondary database @echo "โ˜๏ธ Setting up secondary database..." @echo "๐Ÿ—„๏ธ Creating empty database $(SECONDARY_DB_ID)..." @mkdir -p ./tmp && echo "-- Empty schema for database creation" > ./tmp/schema.sql @SPANNER_PROJECT_ID=$(PROJECT_ID) SPANNER_INSTANCE_ID=$(INSTANCE_ID) SPANNER_DATABASE_ID=$(SECONDARY_DB_ID) SPANNER_EMULATOR_HOST=localhost:$(DOCKER_SPANNER_PORT) wrench create --directory="$$(pwd)/tmp" --schema_file=schema.sql 2>/dev/null || echo " โ„น๏ธ Database $(SECONDARY_DB_ID) already exists or has been created" @echo "๐Ÿ”„ Applying individual schema files from $(SECONDARY_SCHEMA_PATH)..." @for file in "$(SECONDARY_SCHEMA_PATH)"/*.sql; do \ if [ -f "$$file" ]; then \ echo " ๐Ÿ“„ Applying: $$file"; \ SPANNER_PROJECT_ID=$(PROJECT_ID) SPANNER_INSTANCE_ID=$(INSTANCE_ID) SPANNER_DATABASE_ID=$(SECONDARY_DB_ID) SPANNER_EMULATOR_HOST=localhost:$(DOCKER_SPANNER_PORT) wrench apply --ddl="$$file" || { echo "โŒ Failed to apply: $$file"; exit 1; }; \ fi; \ done @echo "โœ… Schema application completed for secondary database" @echo "๐Ÿ”ง Setting up Go modules..." @go mod tidy >/dev/null 2>&1 @echo "๐ŸŒฑ Seeding secondary database..." @SPANNER_EMULATOR_HOST=localhost:$(DOCKER_SPANNER_PORT) go run cmd/seed-injector/main.go --database-id $(SECONDARY_DB_ID) --fixture-dir "$$(pwd)/scenarios/$(SCENARIO)/fixtures/secondary" || { echo "โŒ Failed to seed secondary database"; exit 1; } @echo "โœ… Secondary database ready" test-scenario: ## Run specific scenario test @echo "๐Ÿงช Running scenario: $(SCENARIO)" @echo "๐Ÿ” Verifying emulator status before tests..." @if ! docker ps | grep -q $(DOCKER_CONTAINER_NAME); then echo "โŒ Emulator not running"; exit 1; fi @echo "๐ŸŽญ Starting Playwright tests..." @SPANNER_EMULATOR_HOST=localhost:$(DOCKER_SPANNER_PORT) \ PROJECT_ID=$(PROJECT_ID) \ INSTANCE_ID=$(INSTANCE_ID) \ PRIMARY_DB_ID=$(PRIMARY_DB_ID) \ SECONDARY_DB_ID=$(SECONDARY_DB_ID) \ DB_COUNT=$(DB_COUNT) \ npx playwright test --grep $(SCENARIO) || { echo "โŒ Playwright tests failed for $(SCENARIO)"; exit 1; } run-all: run-all-scenarios ## Alias for run-all-scenarios run-all-scenarios: ## Run all scenarios @echo "๐Ÿš€ Running all scenarios..." @echo "๐Ÿ“‹ Environment: PROJECT_ID=$(PROJECT_ID), INSTANCE_ID=$(INSTANCE_ID), DB_COUNT=$(DB_COUNT)" @$(MAKE) setup @scenarios=$$(ls scenarios/ | grep -E '^(scenario|example)-'); \ if [ -z "$$scenarios" ]; then \ echo "โŒ No scenarios found in scenarios/ directory"; \ exit 1; \ fi; \ echo "๐Ÿ“ Found scenarios: $$scenarios"; \ for scenario in $$scenarios; do \ echo "โ–ถ๏ธ Running $$scenario"; \ SCENARIO=$$scenario $(MAKE) test-scenario || { echo "โŒ Failed running scenario $$scenario"; exit 1; }; \ echo "๐Ÿ” Validating $$scenario database state..."; \ SCENARIO=$$scenario $(MAKE) validate-scenario || { echo "โŒ Failed validating scenario $$scenario"; exit 1; }; \ echo "โœ… Scenario $$scenario completed successfully"; \ done @echo "โœ… All scenarios completed" test-e2e: ## Run Playwright E2E tests @npx playwright test test-report: ## Open test report @echo "๐Ÿ“Š Opening test report..." @npx playwright show-report validate-scenario: ## Validate scenario database state @if [ -z "$(SCENARIO)" ]; then echo "โŒ SCENARIO required"; exit 1; fi @echo "๐Ÿ” Validating scenario databases for $(SCENARIO)..." @echo "๐Ÿ“ก Checking emulator status..." @if ! docker ps | grep -q $(DOCKER_CONTAINER_NAME); then echo "โŒ Emulator not running for validation"; exit 1; fi @if [ -f "scenarios/$(SCENARIO)/expected-primary.yaml" ]; then \ echo "๐Ÿ” Validating primary database for $(SCENARIO)..."; \ SPANNER_EMULATOR_HOST=localhost:$(DOCKER_SPANNER_PORT) spalidate --project $(PROJECT_ID) --instance $(INSTANCE_ID) --database $(PRIMARY_DB_ID) --verbose scenarios/$(SCENARIO)/expected-primary.yaml || { echo "โŒ Primary database validation failed for $(SCENARIO)"; exit 1; }; \ else \ echo "โš ๏ธ No primary validation file found for $(SCENARIO)"; \ fi ifeq ($(DB_COUNT),2) @if [ -f "scenarios/$(SCENARIO)/expected-secondary.yaml" ]; then \ echo "๐Ÿ” Validating secondary database for $(SCENARIO)..."; \ SPANNER_EMULATOR_HOST=localhost:$(DOCKER_SPANNER_PORT) spalidate --project $(PROJECT_ID) --instance $(INSTANCE_ID) --database $(SECONDARY_DB_ID) --verbose scenarios/$(SCENARIO)/expected-secondary.yaml || { echo "โŒ Secondary database validation failed for $(SCENARIO)"; exit 1; }; \ else \ echo "โš ๏ธ No secondary validation file found for $(SCENARIO)"; \ fi endif @echo "โœ… Database validation completed for $(SCENARIO)" validate-db: ## Validate all databases for current scenario @$(MAKE) validate-scenario new-scenario: ## Create new scenario (SCENARIO=name required) @if [ -z "$(SCENARIO)" ]; then echo "โŒ SCENARIO required"; exit 1; fi @echo "๐Ÿ“ Creating scenario: $(SCENARIO)" @mkdir -p scenarios/$(SCENARIO)/fixtures scenarios/$(SCENARIO)/tests @cp expected-primary.yaml.template scenarios/$(SCENARIO)/expected-primary.yaml 2>/dev/null || echo "โš ๏ธ No primary template found" ifeq ($(DB_COUNT),2) @cp expected-secondary.yaml.template scenarios/$(SCENARIO)/expected-secondary.yaml 2>/dev/null || echo "โš ๏ธ No secondary template found" endif @echo "โœ… Scenario $(SCENARIO) created" validate: ## Validate configuration and schemas @echo "๐Ÿ” Validating configuration..." @test -f ".env" || { echo "โŒ .env file missing"; exit 1; } @test -n "$(PRIMARY_SCHEMA_PATH)" || { echo "โŒ PRIMARY_SCHEMA_PATH not set"; exit 1; } @test -d "$(PRIMARY_SCHEMA_PATH)" || { echo "โŒ Primary schema directory not found"; exit 1; } ifeq ($(DB_COUNT),2) @test -n "$(SECONDARY_SCHEMA_PATH)" || { echo "โŒ SECONDARY_SCHEMA_PATH not set"; exit 1; } @test -d "$(SECONDARY_SCHEMA_PATH)" || { echo "โŒ Secondary schema directory not found"; exit 1; } endif @echo "โœ… Configuration valid" build: ## Build Go tools @echo "๐Ÿ”จ Building Go tools..." @go mod tidy @go build -o bin/seed-injector cmd/seed-injector/main.go @echo "โœ… Build complete" dev: ## Development mode - setup and watch @$(MAKE) setup @echo "๐Ÿ‘€ Development mode - run 'make test-e2e' to test"