stabilize cef integration tests and cursor lint
- commit
- d42aca36baf630cd3e7ce8faa3b220788cdf78bc
- author
- brice · · 2026-03-20 09:35 UTC
- committer
- brice · · 2026-03-28 04:36 UTC
- parent
- faa77cd
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
5 files · +44 -67
M internal/application/usecase/navigate_test.go +1 -1
| @@ -81,11 +81,11 @@ func TestUpdateHistoryTitle_UsesMetadataUpdateWithoutIncrementingVisits(t *testi | |||
| 81 | 81 | uc := NewNavigateUseCase(repo, nil, entity.ZoomDefault) | |
| 82 | 82 | err = uc.UpdateHistoryTitle(ctx, "https://example.com/article", "New") | |
| 83 | 83 | require.NoError(t, err) | |
| 84 | + | uc.Close() | |
| 84 | 85 | ||
| 85 | 86 | after, err := repo.FindByURL(ctx, "https://example.com/article") | |
| 86 | 87 | require.NoError(t, err) | |
| 87 | 88 | require.NotNil(t, after) | |
| 88 | 89 | require.Equal(t, "New", after.Title) | |
| 89 | 90 | require.Equal(t, before.VisitCount, after.VisitCount) | |
| 90 | - | uc.Close() | |
| 91 | 91 | } | |
| @@ -81,11 +81,11 @@ func TestUpdateHistoryTitle_UsesMetadataUpdateWithoutIncrementingVisits(t *testi | |||||
| 81 | uc := NewNavigateUseCase(repo, nil, entity.ZoomDefault) | 81 | uc := NewNavigateUseCase(repo, nil, entity.ZoomDefault) | ||
| 82 | err = uc.UpdateHistoryTitle(ctx, "https://example.com/article", "New") | 82 | err = uc.UpdateHistoryTitle(ctx, "https://example.com/article", "New") | ||
| 83 | require.NoError(t, err) | 83 | require.NoError(t, err) | ||
| 84 | + | uc.Close() | |||
| 84 | 85 | ||||
| 85 | after, err := repo.FindByURL(ctx, "https://example.com/article") | 86 | after, err := repo.FindByURL(ctx, "https://example.com/article") | ||
| 86 | require.NoError(t, err) | 87 | require.NoError(t, err) | ||
| 87 | require.NotNil(t, after) | 88 | require.NotNil(t, after) | ||
| 88 | require.Equal(t, "New", after.Title) | 89 | require.Equal(t, "New", after.Title) | ||
| 89 | require.Equal(t, before.VisitCount, after.VisitCount) | 90 | require.Equal(t, before.VisitCount, after.VisitCount) | ||
| 90 | - | uc.Close() | |||
| 91 | } | 91 | } | ||
M internal/bootstrap/engine.go +0 -1
| @@ -27,7 +27,6 @@ type EngineInput struct { | |||
| 27 | 27 | } | |
| 28 | 28 | ||
| 29 | 29 | // BuildEngine constructs a port.Engine for the engine type specified in cfg.Engine.Type. | |
| 30 | - | // Currently only "webkit" is supported; "cef" and other types return an error. | |
| 31 | 30 | func BuildEngine(input EngineInput) (port.Engine, error) { | |
| 32 | 31 | cfg := input.Config | |
| 33 | 32 | engineType := cfg.Engine.Type | |
| @@ -27,7 +27,6 @@ type EngineInput struct { | |||||
| 27 | } | 27 | } | ||
| 28 | 28 | ||||
| 29 | // BuildEngine constructs a port.Engine for the engine type specified in cfg.Engine.Type. | 29 | // BuildEngine constructs a port.Engine for the engine type specified in cfg.Engine.Type. | ||
| 30 | - | // Currently only "webkit" is supported; "cef" and other types return an error. | |||
| 31 | func BuildEngine(input EngineInput) (port.Engine, error) { | 30 | func BuildEngine(input EngineInput) (port.Engine, error) { | ||
| 32 | cfg := input.Config | 31 | cfg := input.Config | ||
| 33 | engineType := cfg.Engine.Type | 32 | engineType := cfg.Engine.Type | ||
M internal/bootstrap/engine_test.go +3 -2
| @@ -16,10 +16,11 @@ func TestBuildEngine_UnknownType(t *testing.T) { | |||
| 16 | 16 | require.Contains(t, err.Error(), "unknown engine type") | |
| 17 | 17 | } | |
| 18 | 18 | ||
| 19 | - | func TestBuildEngine_CEF_NotImplemented(t *testing.T) { | |
| 19 | + | func TestBuildEngine_CEF_ReturnsErrorWhenRuntimeUnavailable(t *testing.T) { | |
| 20 | 20 | cfg := config.DefaultConfig() | |
| 21 | 21 | cfg.Engine.Type = "cef" | |
| 22 | + | cfg.Engine.CEF.CEFDir = t.TempDir() | |
| 22 | 23 | _, err := BuildEngine(EngineInput{Config: cfg, Ctx: context.Background()}) | |
| 23 | 24 | require.Error(t, err) | |
| 24 | - | require.Contains(t, err.Error(), "not yet implemented") | |
| 25 | + | require.Contains(t, err.Error(), "cef: open library") | |
| 25 | 26 | } | |
| @@ -16,10 +16,11 @@ func TestBuildEngine_UnknownType(t *testing.T) { | |||||
| 16 | require.Contains(t, err.Error(), "unknown engine type") | 16 | require.Contains(t, err.Error(), "unknown engine type") | ||
| 17 | } | 17 | } | ||
| 18 | 18 | ||||
| 19 | - | func TestBuildEngine_CEF_NotImplemented(t *testing.T) { | 19 | + | func TestBuildEngine_CEF_ReturnsErrorWhenRuntimeUnavailable(t *testing.T) { |
| 20 | cfg := config.DefaultConfig() | 20 | cfg := config.DefaultConfig() | ||
| 21 | cfg.Engine.Type = "cef" | 21 | cfg.Engine.Type = "cef" | ||
| 22 | + | cfg.Engine.CEF.CEFDir = t.TempDir() | |||
| 22 | _, err := BuildEngine(EngineInput{Config: cfg, Ctx: context.Background()}) | 23 | _, err := BuildEngine(EngineInput{Config: cfg, Ctx: context.Background()}) | ||
| 23 | require.Error(t, err) | 24 | require.Error(t, err) | ||
| 24 | - | require.Contains(t, err.Error(), "not yet implemented") | 25 | + | require.Contains(t, err.Error(), "cef: open library") |
| 25 | } | 26 | } | ||
M internal/infrastructure/cef/app.go +3 -1
| @@ -15,7 +15,9 @@ type dumberApp struct { | |||
| 15 | 15 | // adaptive message pump. | |
| 16 | 16 | func newDumberApp(engine *Engine) purecef.App { | |
| 17 | 17 | app := &dumberApp{engine: engine} | |
| 18 | - | app.bph = purecef.NewBrowserProcessHandler(&dumberBPH{engine: engine}) | |
| 18 | + | // Keep the raw Go implementation here. NewApp will wrap it exactly once | |
| 19 | + | // when GetBrowserProcessHandler is queried by CEF. | |
| 20 | + | app.bph = &dumberBPH{engine: engine} | |
| 19 | 21 | return purecef.NewApp(app) | |
| 20 | 22 | } | |
| 21 | 23 | ||
| @@ -15,7 +15,9 @@ type dumberApp struct { | |||||
| 15 | // adaptive message pump. | 15 | // adaptive message pump. | ||
| 16 | func newDumberApp(engine *Engine) purecef.App { | 16 | func newDumberApp(engine *Engine) purecef.App { | ||
| 17 | app := &dumberApp{engine: engine} | 17 | app := &dumberApp{engine: engine} | ||
| 18 | - | app.bph = purecef.NewBrowserProcessHandler(&dumberBPH{engine: engine}) | 18 | + | // Keep the raw Go implementation here. NewApp will wrap it exactly once |
| 19 | + | // when GetBrowserProcessHandler is queried by CEF. | |||
| 20 | + | app.bph = &dumberBPH{engine: engine} | |||
| 19 | return purecef.NewApp(app) | 21 | return purecef.NewApp(app) | ||
| 20 | } | 22 | } | ||
| 21 | 23 | ||||
M internal/infrastructure/cef/webview_handlers.go +37 -62
| @@ -256,6 +256,7 @@ func (h *handlerSet) OnLoadEnd(_ purecef.Browser, frame purecef.Frame, httpStatu | |||
| 256 | 256 | } | |
| 257 | 257 | // Successful load — reset the consecutive crash counter. | |
| 258 | 258 | h.wv.crashCount = 0 | |
| 259 | + | ||
| 259 | 260 | h.wv.mu.RLock() | |
| 260 | 261 | cb := h.wv.callbacks | |
| 261 | 262 | h.wv.mu.RUnlock() | |
| @@ -415,68 +416,42 @@ func (h *handlerSet) OnRenderProcessTerminated(_ purecef.Browser, status purecef | |||
| 415 | 416 | ||
| 416 | 417 | func (h *handlerSet) OnDocumentAvailableInMainFrame(_ purecef.Browser) {} | |
| 417 | 418 | ||
| 418 | - | // cefCursorToGDKName maps CEF cursor types to GDK/CSS cursor names. | |
| 419 | - | // | |
| 420 | - | //nolint:mnd,cyclop // cursor type lookup table | |
| 419 | + | // cefCursorNames maps CEF cursor types to GDK/CSS cursor names. | |
| 420 | + | var cefCursorNames = map[purecef.CursorType]string{ | |
| 421 | + | purecef.CursorTypeCtPointer: "default", | |
| 422 | + | purecef.CursorTypeCtCross: "crosshair", | |
| 423 | + | purecef.CursorTypeCtHand: "pointer", | |
| 424 | + | purecef.CursorTypeCtIbeam: "text", | |
| 425 | + | purecef.CursorTypeCtWait: "wait", | |
| 426 | + | purecef.CursorTypeCtHelp: "help", | |
| 427 | + | purecef.CursorTypeCtEastresize: "e-resize", | |
| 428 | + | purecef.CursorTypeCtNorthresize: "n-resize", | |
| 429 | + | purecef.CursorTypeCtNortheastresize: "ne-resize", | |
| 430 | + | purecef.CursorTypeCtNorthwestresize: "nw-resize", | |
| 431 | + | purecef.CursorTypeCtSouthresize: "s-resize", | |
| 432 | + | purecef.CursorTypeCtSoutheastresize: "se-resize", | |
| 433 | + | purecef.CursorTypeCtSouthwestresize: "sw-resize", | |
| 434 | + | purecef.CursorTypeCtWestresize: "w-resize", | |
| 435 | + | purecef.CursorTypeCtNorthsouthresize: "ns-resize", | |
| 436 | + | purecef.CursorTypeCtEastwestresize: "ew-resize", | |
| 437 | + | purecef.CursorTypeCtNortheastsouthwestresize: "nesw-resize", | |
| 438 | + | purecef.CursorTypeCtNorthwestsoutheastresize: "nwse-resize", | |
| 439 | + | purecef.CursorTypeCtColumnresize: "col-resize", | |
| 440 | + | purecef.CursorTypeCtRowresize: "row-resize", | |
| 441 | + | purecef.CursorTypeCtMove: "move", | |
| 442 | + | purecef.CursorTypeCtProgress: "progress", | |
| 443 | + | purecef.CursorTypeCtNodrop: "no-drop", | |
| 444 | + | purecef.CursorTypeCtNotallowed: "not-allowed", | |
| 445 | + | purecef.CursorTypeCtGrab: "grab", | |
| 446 | + | purecef.CursorTypeCtGrabbing: "grabbing", | |
| 447 | + | purecef.CursorTypeCtZoomin: "zoom-in", | |
| 448 | + | purecef.CursorTypeCtZoomout: "zoom-out", | |
| 449 | + | } | |
| 450 | + | ||
| 451 | + | // cefCursorToGDKName maps a CEF cursor type to a GDK/CSS cursor name. | |
| 421 | 452 | func cefCursorToGDKName(ct purecef.CursorType) string { | |
| 422 | - | switch ct { | |
| 423 | - | case purecef.CursorTypeCtPointer: | |
| 424 | - | return "default" | |
| 425 | - | case purecef.CursorTypeCtCross: | |
| 426 | - | return "crosshair" | |
| 427 | - | case purecef.CursorTypeCtHand: | |
| 428 | - | return "pointer" | |
| 429 | - | case purecef.CursorTypeCtIbeam: | |
| 430 | - | return "text" | |
| 431 | - | case purecef.CursorTypeCtWait: | |
| 432 | - | return "wait" | |
| 433 | - | case purecef.CursorTypeCtHelp: | |
| 434 | - | return "help" | |
| 435 | - | case purecef.CursorTypeCtEastresize: | |
| 436 | - | return "e-resize" | |
| 437 | - | case purecef.CursorTypeCtNorthresize: | |
| 438 | - | return "n-resize" | |
| 439 | - | case purecef.CursorTypeCtNortheastresize: | |
| 440 | - | return "ne-resize" | |
| 441 | - | case purecef.CursorTypeCtNorthwestresize: | |
| 442 | - | return "nw-resize" | |
| 443 | - | case purecef.CursorTypeCtSouthresize: | |
| 444 | - | return "s-resize" | |
| 445 | - | case purecef.CursorTypeCtSoutheastresize: | |
| 446 | - | return "se-resize" | |
| 447 | - | case purecef.CursorTypeCtSouthwestresize: | |
| 448 | - | return "sw-resize" | |
| 449 | - | case purecef.CursorTypeCtWestresize: | |
| 450 | - | return "w-resize" | |
| 451 | - | case purecef.CursorTypeCtNorthsouthresize: | |
| 452 | - | return "ns-resize" | |
| 453 | - | case purecef.CursorTypeCtEastwestresize: | |
| 454 | - | return "ew-resize" | |
| 455 | - | case purecef.CursorTypeCtNortheastsouthwestresize: | |
| 456 | - | return "nesw-resize" | |
| 457 | - | case purecef.CursorTypeCtNorthwestsoutheastresize: | |
| 458 | - | return "nwse-resize" | |
| 459 | - | case purecef.CursorTypeCtColumnresize: | |
| 460 | - | return "col-resize" | |
| 461 | - | case purecef.CursorTypeCtRowresize: | |
| 462 | - | return "row-resize" | |
| 463 | - | case purecef.CursorTypeCtMove: | |
| 464 | - | return "move" | |
| 465 | - | case purecef.CursorTypeCtProgress: | |
| 466 | - | return "progress" | |
| 467 | - | case purecef.CursorTypeCtNodrop: | |
| 468 | - | return "no-drop" | |
| 469 | - | case purecef.CursorTypeCtNotallowed: | |
| 470 | - | return "not-allowed" | |
| 471 | - | case purecef.CursorTypeCtGrab: | |
| 472 | - | return "grab" | |
| 473 | - | case purecef.CursorTypeCtGrabbing: | |
| 474 | - | return "grabbing" | |
| 475 | - | case purecef.CursorTypeCtZoomin: | |
| 476 | - | return "zoom-in" | |
| 477 | - | case purecef.CursorTypeCtZoomout: | |
| 478 | - | return "zoom-out" | |
| 479 | - | default: | |
| 480 | - | return "default" | |
| 453 | + | if name, ok := cefCursorNames[ct]; ok { | |
| 454 | + | return name | |
| 481 | 455 | } | |
| 456 | + | return "default" | |
| 482 | 457 | } | |
| @@ -256,6 +256,7 @@ func (h *handlerSet) OnLoadEnd(_ purecef.Browser, frame purecef.Frame, httpStatu | |||||
| 256 | } | 256 | } | ||
| 257 | // Successful load — reset the consecutive crash counter. | 257 | // Successful load — reset the consecutive crash counter. | ||
| 258 | h.wv.crashCount = 0 | 258 | h.wv.crashCount = 0 | ||
| 259 | + | ||||
| 259 | h.wv.mu.RLock() | 260 | h.wv.mu.RLock() | ||
| 260 | cb := h.wv.callbacks | 261 | cb := h.wv.callbacks | ||
| 261 | h.wv.mu.RUnlock() | 262 | h.wv.mu.RUnlock() | ||
| @@ -415,68 +416,42 @@ func (h *handlerSet) OnRenderProcessTerminated(_ purecef.Browser, status purecef | |||||
| 415 | 416 | ||||
| 416 | func (h *handlerSet) OnDocumentAvailableInMainFrame(_ purecef.Browser) {} | 417 | func (h *handlerSet) OnDocumentAvailableInMainFrame(_ purecef.Browser) {} | ||
| 417 | 418 | ||||
| 418 | - | // cefCursorToGDKName maps CEF cursor types to GDK/CSS cursor names. | 419 | + | // cefCursorNames maps CEF cursor types to GDK/CSS cursor names. |
| 419 | - | // | 420 | + | var cefCursorNames = map[purecef.CursorType]string{ |
| 420 | - | //nolint:mnd,cyclop // cursor type lookup table | 421 | + | purecef.CursorTypeCtPointer: "default", |
| 422 | + | purecef.CursorTypeCtCross: "crosshair", | |||
| 423 | + | purecef.CursorTypeCtHand: "pointer", | |||
| 424 | + | purecef.CursorTypeCtIbeam: "text", | |||
| 425 | + | purecef.CursorTypeCtWait: "wait", | |||
| 426 | + | purecef.CursorTypeCtHelp: "help", | |||
| 427 | + | purecef.CursorTypeCtEastresize: "e-resize", | |||
| 428 | + | purecef.CursorTypeCtNorthresize: "n-resize", | |||
| 429 | + | purecef.CursorTypeCtNortheastresize: "ne-resize", | |||
| 430 | + | purecef.CursorTypeCtNorthwestresize: "nw-resize", | |||
| 431 | + | purecef.CursorTypeCtSouthresize: "s-resize", | |||
| 432 | + | purecef.CursorTypeCtSoutheastresize: "se-resize", | |||
| 433 | + | purecef.CursorTypeCtSouthwestresize: "sw-resize", | |||
| 434 | + | purecef.CursorTypeCtWestresize: "w-resize", | |||
| 435 | + | purecef.CursorTypeCtNorthsouthresize: "ns-resize", | |||
| 436 | + | purecef.CursorTypeCtEastwestresize: "ew-resize", | |||
| 437 | + | purecef.CursorTypeCtNortheastsouthwestresize: "nesw-resize", | |||
| 438 | + | purecef.CursorTypeCtNorthwestsoutheastresize: "nwse-resize", | |||
| 439 | + | purecef.CursorTypeCtColumnresize: "col-resize", | |||
| 440 | + | purecef.CursorTypeCtRowresize: "row-resize", | |||
| 441 | + | purecef.CursorTypeCtMove: "move", | |||
| 442 | + | purecef.CursorTypeCtProgress: "progress", | |||
| 443 | + | purecef.CursorTypeCtNodrop: "no-drop", | |||
| 444 | + | purecef.CursorTypeCtNotallowed: "not-allowed", | |||
| 445 | + | purecef.CursorTypeCtGrab: "grab", | |||
| 446 | + | purecef.CursorTypeCtGrabbing: "grabbing", | |||
| 447 | + | purecef.CursorTypeCtZoomin: "zoom-in", | |||
| 448 | + | purecef.CursorTypeCtZoomout: "zoom-out", | |||
| 449 | + | } | |||
| 450 | + | ||||
| 451 | + | // cefCursorToGDKName maps a CEF cursor type to a GDK/CSS cursor name. | |||
| 421 | func cefCursorToGDKName(ct purecef.CursorType) string { | 452 | func cefCursorToGDKName(ct purecef.CursorType) string { | ||
| 422 | - | switch ct { | 453 | + | if name, ok := cefCursorNames[ct]; ok { |
| 423 | - | case purecef.CursorTypeCtPointer: | 454 | + | return name |
| 424 | - | return "default" | |||
| 425 | - | case purecef.CursorTypeCtCross: | |||
| 426 | - | return "crosshair" | |||
| 427 | - | case purecef.CursorTypeCtHand: | |||
| 428 | - | return "pointer" | |||
| 429 | - | case purecef.CursorTypeCtIbeam: | |||
| 430 | - | return "text" | |||
| 431 | - | case purecef.CursorTypeCtWait: | |||
| 432 | - | return "wait" | |||
| 433 | - | case purecef.CursorTypeCtHelp: | |||
| 434 | - | return "help" | |||
| 435 | - | case purecef.CursorTypeCtEastresize: | |||
| 436 | - | return "e-resize" | |||
| 437 | - | case purecef.CursorTypeCtNorthresize: | |||
| 438 | - | return "n-resize" | |||
| 439 | - | case purecef.CursorTypeCtNortheastresize: | |||
| 440 | - | return "ne-resize" | |||
| 441 | - | case purecef.CursorTypeCtNorthwestresize: | |||
| 442 | - | return "nw-resize" | |||
| 443 | - | case purecef.CursorTypeCtSouthresize: | |||
| 444 | - | return "s-resize" | |||
| 445 | - | case purecef.CursorTypeCtSoutheastresize: | |||
| 446 | - | return "se-resize" | |||
| 447 | - | case purecef.CursorTypeCtSouthwestresize: | |||
| 448 | - | return "sw-resize" | |||
| 449 | - | case purecef.CursorTypeCtWestresize: | |||
| 450 | - | return "w-resize" | |||
| 451 | - | case purecef.CursorTypeCtNorthsouthresize: | |||
| 452 | - | return "ns-resize" | |||
| 453 | - | case purecef.CursorTypeCtEastwestresize: | |||
| 454 | - | return "ew-resize" | |||
| 455 | - | case purecef.CursorTypeCtNortheastsouthwestresize: | |||
| 456 | - | return "nesw-resize" | |||
| 457 | - | case purecef.CursorTypeCtNorthwestsoutheastresize: | |||
| 458 | - | return "nwse-resize" | |||
| 459 | - | case purecef.CursorTypeCtColumnresize: | |||
| 460 | - | return "col-resize" | |||
| 461 | - | case purecef.CursorTypeCtRowresize: | |||
| 462 | - | return "row-resize" | |||
| 463 | - | case purecef.CursorTypeCtMove: | |||
| 464 | - | return "move" | |||
| 465 | - | case purecef.CursorTypeCtProgress: | |||
| 466 | - | return "progress" | |||
| 467 | - | case purecef.CursorTypeCtNodrop: | |||
| 468 | - | return "no-drop" | |||
| 469 | - | case purecef.CursorTypeCtNotallowed: | |||
| 470 | - | return "not-allowed" | |||
| 471 | - | case purecef.CursorTypeCtGrab: | |||
| 472 | - | return "grab" | |||
| 473 | - | case purecef.CursorTypeCtGrabbing: | |||
| 474 | - | return "grabbing" | |||
| 475 | - | case purecef.CursorTypeCtZoomin: | |||
| 476 | - | return "zoom-in" | |||
| 477 | - | case purecef.CursorTypeCtZoomout: | |||
| 478 | - | return "zoom-out" | |||
| 479 | - | default: | |||
| 480 | - | return "default" | |||
| 481 | } | 455 | } | ||
| 456 | + | return "default" | |||
| 482 | } | 457 | } | ||