Isolate CI database journey and stabilize E2E dependency cache
This commit is contained in:
1 parent
82bf015283
commit
bbd629dcf8
3 files changed
+45
-4
No files matched your search
@@ -4,6 +4,15 @@ import { defineConfig } from 'vite';
|
|||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [react()],
|
plugins: [react()],
|
||||||
|
// Keep Vitest's dependency cache separate from the browser test server.
|
||||||
|
cacheDir: process.env.VITE_E2E === '1' ? 'node_modules/.vite-e2e' : undefined,
|
||||||
|
optimizeDeps: process.env.VITE_E2E === '1' ? {
|
||||||
|
// Lazy routes and workers must be scanned before browsers cache React chunks.
|
||||||
|
// Late discovery otherwise mixes cached and newly optimized React instances
|
||||||
|
// across full document navigations when HMR is disabled.
|
||||||
|
entries: ['index.html', 'src/**/*.{ts,tsx}', '!src/**/*.test.{ts,tsx}', '!src/**/*.d.ts', '!src/test/**'],
|
||||||
|
include: ['react', 'react-dom', 'react-dom/client', 'react/jsx-runtime', 'react/jsx-dev-runtime'],
|
||||||
|
} : undefined,
|
||||||
build: {
|
build: {
|
||||||
target: 'es2022',
|
target: 'es2022',
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
|
"github.com/jackc/pgx/v5"
|
||||||
"github.com/redis/go-redis/v9"
|
"github.com/redis/go-redis/v9"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
@@ -120,6 +121,7 @@ func TestUserJourney(t *testing.T) {
|
|||||||
if dbURL == "" {
|
if dbURL == "" {
|
||||||
t.Skip("TEST_DATABASE_URL is not set")
|
t.Skip("TEST_DATABASE_URL is not set")
|
||||||
}
|
}
|
||||||
|
dbURL = userJourneyDatabase(t, dbURL)
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
@@ -133,6 +135,7 @@ func TestUserJourney(t *testing.T) {
|
|||||||
t.Setenv("DATABASE_URL", dbURL)
|
t.Setenv("DATABASE_URL", dbURL)
|
||||||
t.Setenv("REDIS_URL", os.Getenv("TEST_REDIS_URL"))
|
t.Setenv("REDIS_URL", os.Getenv("TEST_REDIS_URL"))
|
||||||
t.Setenv("BOOTSTRAP_ADMIN_PASSWORD", "admin")
|
t.Setenv("BOOTSTRAP_ADMIN_PASSWORD", "admin")
|
||||||
|
t.Setenv("BOOTSTRAP_ADMIN_USERNAME", "admin")
|
||||||
t.Setenv("MUSICBRAINZ_ENABLED", "false") // public provider availability is covered by explicit live tests
|
t.Setenv("MUSICBRAINZ_ENABLED", "false") // public provider availability is covered by explicit live tests
|
||||||
cfg, err := config.Load[config.API]()
|
cfg, err := config.Load[config.API]()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@@ -172,6 +175,7 @@ func TestUserJourney(t *testing.T) {
|
|||||||
BootstrapRequired bool `json:"bootstrap_required"`
|
BootstrapRequired bool `json:"bootstrap_required"`
|
||||||
}
|
}
|
||||||
c.ok("GET", "/api/v1/server-info", nil, &info)
|
c.ok("GET", "/api/v1/server-info", nil, &info)
|
||||||
|
require.True(t, info.BootstrapRequired, "user journey requires a fresh database before the first admin login")
|
||||||
var tokens struct {
|
var tokens struct {
|
||||||
AccessToken string `json:"access_token"`
|
AccessToken string `json:"access_token"`
|
||||||
User struct {
|
User struct {
|
||||||
@@ -376,3 +380,29 @@ func TestUserJourney(t *testing.T) {
|
|||||||
})
|
})
|
||||||
fmt.Println("user journey ok")
|
fmt.Println("user journey ok")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Other integration packages deliberately create users and catalog fixtures.
|
||||||
|
// The bootstrap journey needs a new database, without modifying those fixtures.
|
||||||
|
// TEST_DATABASE_URL must use a role with CREATEDB (the CI Postgres owner does).
|
||||||
|
func userJourneyDatabase(t *testing.T, address string) string {
|
||||||
|
t.Helper()
|
||||||
|
ctx := context.Background()
|
||||||
|
admin, err := db.Connect(ctx, address)
|
||||||
|
require.NoError(t, err)
|
||||||
|
t.Cleanup(admin.Close)
|
||||||
|
name := "pipu_journey_" + strings.ReplaceAll(uuid.NewString(), "-", "")
|
||||||
|
identifier := pgx.Identifier{name}.Sanitize()
|
||||||
|
_, err = admin.Exec(ctx, "CREATE DATABASE "+identifier)
|
||||||
|
require.NoError(t, err)
|
||||||
|
t.Cleanup(func() {
|
||||||
|
cleanup, cancel := context.WithTimeout(context.Background(), 15*time.Second)
|
||||||
|
defer cancel()
|
||||||
|
_, err := admin.Exec(cleanup, "DROP DATABASE "+identifier+" WITH (FORCE)")
|
||||||
|
require.NoError(t, err)
|
||||||
|
})
|
||||||
|
dsn, err := url.Parse(address)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Contains(t, []string{"postgres", "postgresql"}, dsn.Scheme)
|
||||||
|
dsn.Path = "/" + name
|
||||||
|
return dsn.String()
|
||||||
|
}
|
||||||
@@ -25,16 +25,18 @@ func TestUploadedArtistPortraitStagingLifetime(t *testing.T) {
|
|||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
pool, err := db.Connect(ctx, address)
|
pool, err := db.Connect(ctx, address)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
defer pool.Close()
|
t.Cleanup(pool.Close)
|
||||||
require.NoError(t, db.Migrate(ctx, pool))
|
require.NoError(t, db.Migrate(ctx, pool))
|
||||||
store := NewStore(pool)
|
store := NewStore(pool)
|
||||||
author := uuid.New()
|
author := uuid.New()
|
||||||
_, err = pool.Exec(ctx, `INSERT INTO users(id,username,password_hash,role) VALUES($1,$2,'x','admin')`, author, "portrait-"+author.String())
|
_, err = pool.Exec(ctx, `INSERT INTO users(id,username,password_hash,role) VALUES($1,$2,'x','admin')`, author, "portrait-"+author.String())
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
t.Cleanup(func() {
|
t.Cleanup(func() {
|
||||||
_, _ = pool.Exec(ctx, `DELETE FROM upload_batches WHERE author_id=$1`, author)
|
_, err := pool.Exec(ctx, `DELETE FROM upload_batches WHERE author_id=$1`, author)
|
||||||
_, _ = pool.Exec(ctx, `DELETE FROM users WHERE id=$1`, author)
|
require.NoError(t, err)
|
||||||
_ = store.ReconcileQuota(ctx)
|
_, err = pool.Exec(ctx, `DELETE FROM users WHERE id=$1`, author)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NoError(t, store.ReconcileQuota(ctx))
|
||||||
})
|
})
|
||||||
svc := NewService(store, nil, nil, nil, nil, nil, library.FPCalc{}, Config{StagingDir: t.TempDir()}, slog.New(slog.DiscardHandler))
|
svc := NewService(store, nil, nil, nil, nil, nil, library.FPCalc{}, Config{StagingDir: t.TempDir()}, slog.New(slog.DiscardHandler))
|
||||||
owner := auth.WithPrincipal(ctx, auth.Principal{UserID: author, Role: auth.RoleAdmin})
|
owner := auth.WithPrincipal(ctx, auth.Principal{UserID: author, Role: auth.RoleAdmin})
|
||||||
|
|||||||
Reference in new issue
Block a user