@@ -19,10 +19,13 @@ package compose
1919import (
2020 "bytes"
2121 "encoding/json"
22+ "strings"
2223 "testing"
2324
2425 "github.com/docker/cli/cli-plugins/hooks"
2526 "gotest.tools/v3/assert"
27+
28+ "github.com/docker/compose/v5/cmd/formatter"
2629)
2730
2831func TestHandleHook_NoArgs (t * testing.T ) {
@@ -52,7 +55,7 @@ func TestHandleHook_UnknownCommand(t *testing.T) {
5255func TestHandleHook_LogsCommand (t * testing.T ) {
5356 tests := []struct {
5457 rootCmd string
55- wantHint string
58+ wantHint func () string
5659 }{
5760 {rootCmd : "compose logs" , wantHint : composeLogsHint },
5861 {rootCmd : "logs" , wantHint : dockerLogsHint },
@@ -68,7 +71,7 @@ func TestHandleHook_LogsCommand(t *testing.T) {
6871
6972 msg := unmarshalResponse (t , buf .Bytes ())
7073 assert .Equal (t , msg .Type , hooks .NextSteps )
71- assert .Equal (t , msg .Template , tt .wantHint )
74+ assert .Equal (t , msg .Template , tt .wantHint () )
7275 })
7376 }
7477}
@@ -112,14 +115,58 @@ func TestHandleHook_ComposeUpDetached(t *testing.T) {
112115
113116 if tt .wantHint {
114117 msg := unmarshalResponse (t , buf .Bytes ())
115- assert .Equal (t , msg .Template , composeLogsHint )
118+ assert .Equal (t , msg .Template , composeLogsHint () )
116119 } else {
117120 assert .Equal (t , buf .String (), "" )
118121 }
119122 })
120123 }
121124}
122125
126+ func TestHandleHook_HintContainsOsc8Link (t * testing.T ) {
127+ data := marshalHookData (t , hooks.Request {
128+ RootCmd : "compose logs" ,
129+ })
130+ var buf bytes.Buffer
131+ err := handleHook ([]string {data }, & buf )
132+ assert .NilError (t , err )
133+
134+ msg := unmarshalResponse (t , buf .Bytes ())
135+ // Verify the template contains the OSC 8 hyperlink sequence
136+ wantLink := formatter .Osc8Link (deepLink , deepLink )
137+ assert .Assert (t , len (wantLink ) > len (deepLink ), "Osc8Link should wrap the URL with escape sequences" )
138+ assert .Assert (t , strings .Contains (msg .Template , wantLink ), "hint should contain OSC 8 hyperlink" )
139+ }
140+
141+ func TestHandleHook_NoColorDisablesOsc8 (t * testing.T ) {
142+ t .Setenv ("NO_COLOR" , "1" )
143+ data := marshalHookData (t , hooks.Request {
144+ RootCmd : "compose logs" ,
145+ })
146+ var buf bytes.Buffer
147+ err := handleHook ([]string {data }, & buf )
148+ assert .NilError (t , err )
149+
150+ msg := unmarshalResponse (t , buf .Bytes ())
151+ // With NO_COLOR set, the hint should contain the plain URL without escape sequences
152+ assert .Assert (t , strings .Contains (msg .Template , deepLink ), "hint should contain the deep link URL" )
153+ assert .Assert (t , ! strings .Contains (msg .Template , "\033 " ), "hint should not contain ANSI escape sequences" )
154+ }
155+
156+ func TestHandleHook_ComposeAnsiNeverDisablesOsc8 (t * testing.T ) {
157+ t .Setenv ("COMPOSE_ANSI" , "never" )
158+ data := marshalHookData (t , hooks.Request {
159+ RootCmd : "compose logs" ,
160+ })
161+ var buf bytes.Buffer
162+ err := handleHook ([]string {data }, & buf )
163+ assert .NilError (t , err )
164+
165+ msg := unmarshalResponse (t , buf .Bytes ())
166+ assert .Assert (t , strings .Contains (msg .Template , deepLink ), "hint should contain the deep link URL" )
167+ assert .Assert (t , ! strings .Contains (msg .Template , "\033 " ), "hint should not contain ANSI escape sequences" )
168+ }
169+
123170func marshalHookData (t * testing.T , data hooks.Request ) string {
124171 t .Helper ()
125172 b , err := json .Marshal (data )
0 commit comments