test: add full-stack Playwright integration test infrastructure
Sprint 12 Phase 2: Real integration tests with seed DB - R__seed_test_data.sql (Flyway repeatable, 7 members, strains, batches, docs, board, events) - TestResetController (profile-gated per-test DB reset) - docker-compose.test.yml (self-contained, tmpfs Postgres) - Dockerfile.playwright (v1.60.0, pre-installed deps) - 13 integration spec files, 70+ test cases (@smoke + @full) - seed-constants.ts, selectors.ts, api-client.ts test helpers
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
package de.cannamanage.api.controller;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.sql.Connection;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Test-only controller for resetting the database to a known seed state.
|
||||
* Only active when cannamanage.test.endpoints.enabled=true (test profile).
|
||||
* NEVER activate this in production.
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("/api/v1/test")
|
||||
@RequiredArgsConstructor
|
||||
@ConditionalOnProperty(name = "cannamanage.test.endpoints.enabled", havingValue = "true")
|
||||
public class TestResetController {
|
||||
|
||||
private final DataSource dataSource;
|
||||
|
||||
/**
|
||||
* Truncates all application tables and re-seeds with test data.
|
||||
* The Flyway schema_history table is preserved.
|
||||
*/
|
||||
@PostMapping("/reset-db")
|
||||
public ResponseEntity<Void> resetDatabase() {
|
||||
log.info("Test DB reset requested — truncating all tables and re-seeding");
|
||||
|
||||
try (Connection conn = dataSource.getConnection()) {
|
||||
truncateAllTables(conn);
|
||||
reseed();
|
||||
log.info("Test DB reset complete — seed data re-applied");
|
||||
return ResponseEntity.ok().build();
|
||||
} catch (SQLException e) {
|
||||
log.error("Failed to reset test database", e);
|
||||
return ResponseEntity.internalServerError().build();
|
||||
}
|
||||
}
|
||||
|
||||
private void truncateAllTables(Connection conn) throws SQLException {
|
||||
List<String> tables = getApplicationTables(conn);
|
||||
|
||||
try (Statement stmt = conn.createStatement()) {
|
||||
// Disable FK constraints for truncation
|
||||
stmt.execute("SET session_replication_role = 'replica'");
|
||||
|
||||
for (String table : tables) {
|
||||
stmt.execute("TRUNCATE TABLE " + table + " CASCADE");
|
||||
log.debug("Truncated table: {}", table);
|
||||
}
|
||||
|
||||
// Re-enable FK constraints
|
||||
stmt.execute("SET session_replication_role = 'origin'");
|
||||
}
|
||||
}
|
||||
|
||||
private List<String> getApplicationTables(Connection conn) throws SQLException {
|
||||
List<String> tables = new ArrayList<>();
|
||||
|
||||
try (Statement stmt = conn.createStatement();
|
||||
ResultSet rs = stmt.executeQuery(
|
||||
"SELECT tablename FROM pg_tables " +
|
||||
"WHERE schemaname = 'public' " +
|
||||
"AND tablename != 'flyway_schema_history'")) {
|
||||
while (rs.next()) {
|
||||
tables.add(rs.getString("tablename"));
|
||||
}
|
||||
}
|
||||
|
||||
return tables;
|
||||
}
|
||||
|
||||
private void reseed() {
|
||||
ResourceDatabasePopulator populator = new ResourceDatabasePopulator();
|
||||
populator.addScript(new ClassPathResource("db/testdata/R__seed_test_data.sql"));
|
||||
populator.setSeparator(";");
|
||||
populator.execute(dataSource);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user