Two independent shortcut correctness fixes surfaced by the audit: - Name→ID resolution (chat +dm / +broadcast / … via the shared resolver) dropped every search_contact_by_key_word row with an empty userId. External / cross-org contacts arrive with only an openDingTalkId, so they were silently discarded — making resolution report a real person as missing, or collapse to the wrong single match when an in-org namesake existed. Keep any row with at least one usable identity (userId or openDingTalkId) and fall the display name back through nick/showName/flowerName/staffName/userName. - chat +messages-resource-url required --message-id with no alias, so an agent copying the message list's openMessageId/msgId output field hit "unknown flag". Accept --msg-id / --open-message-id as aliases (declared via an at-least-one constraint since a shortcut's Required check only sees the primary flag name), mirroring the earlier chat message download-media fix. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
68 lines
2.4 KiB
Go
68 lines
2.4 KiB
Go
// Copyright 2026 Alibaba Group
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package smart
|
|
|
|
import "testing"
|
|
|
|
func TestExtractUsers(t *testing.T) {
|
|
data := map[string]any{
|
|
"result": []any{
|
|
// in-org contact: full identity
|
|
map[string]any{"userId": "024083", "name": "朱鸿", "openDingTalkId": "DHUGO"},
|
|
// external / cross-org contact: no userId, only openDingTalkId +
|
|
// display name under a non-"name" key — must be kept, not dropped.
|
|
map[string]any{"openDingtalkId": "DEXT", "nick": "外部小王"},
|
|
// unusable row (no identity at all) is skipped
|
|
map[string]any{"name": "无ID的人"},
|
|
// non-map entry is skipped
|
|
"garbage",
|
|
},
|
|
}
|
|
users := extractUsers(data)
|
|
if len(users) != 2 {
|
|
t.Fatalf("extractUsers kept %d, want 2: %#v", len(users), users)
|
|
}
|
|
if users[0].userID != "024083" || users[0].openDingTalkID != "DHUGO" || users[0].name != "朱鸿" {
|
|
t.Errorf("in-org user = %#v", users[0])
|
|
}
|
|
// external contact kept via openDingTalkId, name resolved from "nick"
|
|
if users[1].userID != "" || users[1].openDingTalkID != "DEXT" || users[1].name != "外部小王" {
|
|
t.Errorf("external user = %#v", users[1])
|
|
}
|
|
}
|
|
|
|
func TestExtractUsersNoResult(t *testing.T) {
|
|
if got := extractUsers(map[string]any{}); got != nil {
|
|
t.Errorf("no result should be nil, got %#v", got)
|
|
}
|
|
}
|
|
|
|
func TestUsersWithUserIDExcludesOpenIDOnlyContacts(t *testing.T) {
|
|
users := []contactUser{
|
|
{userID: "user-1", openDingTalkID: "open-1", name: "内部用户"},
|
|
{openDingTalkID: "open-external", name: "外部联系人"},
|
|
}
|
|
got := usersWithUserID(users)
|
|
if len(got) != 1 || got[0].userID != "user-1" {
|
|
t.Fatalf("usersWithUserID() = %#v, want only the organization user", got)
|
|
}
|
|
}
|
|
|
|
func TestUserLabelsFallsBackToOpenDingTalkID(t *testing.T) {
|
|
got := userLabels([]contactUser{{openDingTalkID: "open-external", name: "外部联系人"}})
|
|
if len(got) != 1 || got[0] != "外部联系人(open-external)" {
|
|
t.Fatalf("userLabels() = %#v", got)
|
|
}
|
|
}
|