diff --git a/go.mod b/go.mod index fd6cc2f..9914a33 100644 --- a/go.mod +++ b/go.mod @@ -13,7 +13,7 @@ require ( github.com/rusq/slackauth v0.6.1 github.com/rusq/slackdump/v3 v3.1.6 github.com/rusq/tagops v0.1.1 - github.com/slack-go/slack v0.17.1 + github.com/slack-go/slack v0.17.3 github.com/stretchr/testify v1.10.0 github.com/takara2314/slack-go-util v0.2.0 go.uber.org/zap v1.27.0 diff --git a/go.sum b/go.sum index 18ca02c..9c502ef 100644 --- a/go.sum +++ b/go.sum @@ -148,8 +148,8 @@ github.com/rusq/slackdump/v3 v3.1.6 h1:t6hi49jSDWpiXqyna8OlEd2I2zkLBgi9XZGr+xDl5 github.com/rusq/slackdump/v3 v3.1.6/go.mod h1:c9AiEEkmLWIbQJuxDIK+K9H5g6kdfc06Eqk6DmLWWps= github.com/rusq/tagops v0.1.1 h1:R5MHPR822lSg3LFr0RS3DFS0CapRiqtuHVD5NlOMOvY= github.com/rusq/tagops v0.1.1/go.mod h1:mUJ5WoHxrSv9wreCrHQkAeMevt5aXFadlOdLM6UsoHc= -github.com/slack-go/slack v0.17.1 h1:x0Mnc6biHBea5vfxLR+x4JFl/Rm3eIo0iS3xDZenX+o= -github.com/slack-go/slack v0.17.1/go.mod h1:X+UqOufi3LYQHDnMG1vxf0J8asC6+WllXrVrhl8/Prk= +github.com/slack-go/slack v0.17.3 h1:zV5qO3Q+WJAQ/XwbGfNFrRMaJ5T/naqaonyPV/1TP4g= +github.com/slack-go/slack v0.17.3/go.mod h1:X+UqOufi3LYQHDnMG1vxf0J8asC6+WllXrVrhl8/Prk= github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y= github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= diff --git a/pkg/handler/slack_error_test.go b/pkg/handler/slack_error_test.go new file mode 100644 index 0000000..74d0070 --- /dev/null +++ b/pkg/handler/slack_error_test.go @@ -0,0 +1,60 @@ +package handler + +import ( + "encoding/json" + "testing" + + "github.com/slack-go/slack" + "github.com/stretchr/testify/assert" +) + +// TestSlackErrorStringUnmarshal reproduces the bug where Slack API returns +// an "errors" field as an array of strings instead of objects. +// Error: json: cannot unmarshal string into Go struct field +// chatResponseFull.SlackResponse.errors of type map[string]interface{} +func TestSlackErrorStringUnmarshal(t *testing.T) { + // This is what Slack sometimes returns - errors as array of strings + jsonWithStringErrors := `{ + "ok": false, + "error": "invalid_blocks", + "errors": ["block_validation_error"] + }` + + // This response embeds SlackResponse just like chatResponseFull does + type testResponse struct { + Channel string `json:"channel"` + slack.SlackResponse + } + + var resp testResponse + err := json.Unmarshal([]byte(jsonWithStringErrors), &resp) + + // This currently FAILS with: + // json: cannot unmarshal string into Go struct field + // testResponse.SlackResponse.errors of type map[string]interface{} + assert.NoError(t, err, "Should handle string errors from Slack API") + assert.False(t, resp.Ok) + assert.Equal(t, "invalid_blocks", resp.Error) +} + +// TestSlackErrorObjectUnmarshal verifies that object errors work correctly +func TestSlackErrorObjectUnmarshal(t *testing.T) { + // This is the normal case where errors are objects + jsonWithObjectErrors := `{ + "ok": false, + "error": "invalid_blocks", + "errors": [{"pointer": "/blocks/0", "message": "Invalid block"}] + }` + + type testResponse struct { + Channel string `json:"channel"` + slack.SlackResponse + } + + var resp testResponse + err := json.Unmarshal([]byte(jsonWithObjectErrors), &resp) + + assert.NoError(t, err, "Should handle object errors from Slack API") + assert.False(t, resp.Ok) + assert.Equal(t, "invalid_blocks", resp.Error) +}