145 lines
5.5 KiB
Go
145 lines
5.5 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 app
|
|
|
|
import (
|
|
"testing"
|
|
|
|
authpkg "github.com/DingTalk-Real-AI/dingtalk-workspace-cli/internal/auth"
|
|
)
|
|
|
|
func blankProfileSelectorAppFixture(blankName, corpName string) *authpkg.ProfilesConfig {
|
|
const (
|
|
corpID = "corp_selector_fixture"
|
|
exactUserID = "identity_exact_fixture"
|
|
)
|
|
exactSelector := corpID + ":" + exactUserID
|
|
cfg := &authpkg.ProfilesConfig{
|
|
Version: 2,
|
|
PrimaryProfile: exactSelector,
|
|
PreviousProfile: exactSelector,
|
|
OrgCurrentProfiles: map[string]string{
|
|
corpID: exactSelector,
|
|
},
|
|
Profiles: []authpkg.Profile{
|
|
{
|
|
Name: "Exact Fixture Account",
|
|
CorpID: corpID,
|
|
CorpName: corpName,
|
|
UserID: exactUserID,
|
|
UserName: "Exact Fixture Account",
|
|
Status: authpkg.ProfileStatusActive,
|
|
},
|
|
{
|
|
Name: blankName,
|
|
CorpID: corpID,
|
|
CorpName: corpName,
|
|
Status: authpkg.ProfileStatusActive,
|
|
},
|
|
},
|
|
}
|
|
cfg.CurrentProfile = authpkg.ProfileSelectionSelector(cfg.Profiles[1], cfg)
|
|
return cfg
|
|
}
|
|
|
|
func captureProfileListSelectors(t *testing.T, cfg *authpkg.ProfilesConfig) ([]string, []profileView) {
|
|
t.Helper()
|
|
originalLoadToken := profileLoadTokenData
|
|
selectors := make([]string, 0, len(cfg.Profiles))
|
|
profileLoadTokenData = func(_ string, selector string) (*authpkg.TokenData, error) {
|
|
selectors = append(selectors, selector)
|
|
return nil, authpkg.ErrTokenDataNotFound
|
|
}
|
|
t.Cleanup(func() { profileLoadTokenData = originalLoadToken })
|
|
views := profileViews("unused-config-dir", cfg)
|
|
return selectors, views
|
|
}
|
|
|
|
func TestCrossPlatformCoverageBlankProfileNameMatchingCorpNameRoundTripsThroughListAndTUI(t *testing.T) {
|
|
cfg := blankProfileSelectorAppFixture("Fixture Organization", "Fixture Organization")
|
|
blank := cfg.Profiles[1]
|
|
blankSelector := authpkg.ProfileSelectionSelector(blank, cfg)
|
|
|
|
if blankSelector == blank.Name || blankSelector == blank.CorpID {
|
|
t.Fatalf("unsafe blank selector = %q, want reserved exact selector", blankSelector)
|
|
}
|
|
if got := profileCLISelector(blank, cfg); got != blankSelector {
|
|
t.Errorf("profileCLISelector(blank) = %q, want %q", got, blankSelector)
|
|
}
|
|
if got := profileSwitchProfileIndex(cfg.Profiles, cfg.CurrentProfile, cfg); got != 1 {
|
|
t.Errorf("profileSwitchProfileIndex(blank current) = %d, want 1", got)
|
|
}
|
|
model := newProfileSwitchTUIModel(cfg, cfg.CurrentProfile)
|
|
if model.selected != 1 {
|
|
t.Errorf("TUI selected index = %d, want blank profile index 1", model.selected)
|
|
}
|
|
if got := model.selectedCorpID(); got != blankSelector {
|
|
t.Errorf("TUI selected selector = %q, want %q", got, blankSelector)
|
|
}
|
|
|
|
selectors, views := captureProfileListSelectors(t, cfg)
|
|
if len(selectors) != 2 || selectors[0] != cfg.PreviousProfile || selectors[1] != blankSelector {
|
|
t.Errorf("profile list token selectors = %#v, want exact then %q", selectors, blankSelector)
|
|
}
|
|
if len(views) != 2 {
|
|
t.Fatalf("profile list views = %#v, want two entries", views)
|
|
}
|
|
if views[0].IsCurrent {
|
|
t.Error("exact account should not be marked current when blank local selector is current")
|
|
}
|
|
if views[1].Profile != blankSelector || !views[1].IsCurrent {
|
|
t.Errorf("blank list view = %#v, want local selector marked current", views[1])
|
|
}
|
|
}
|
|
|
|
func TestCrossPlatformCoverageBlankProfileNameContainingColonWinsOverIdentityParsingInListAndTUI(t *testing.T) {
|
|
cfg := blankProfileSelectorAppFixture("legacy:outsourced", "Fixture Organization")
|
|
blank := cfg.Profiles[1]
|
|
blankSelector := authpkg.ProfileSelectionSelector(blank, cfg)
|
|
|
|
if blankSelector == blank.Name {
|
|
t.Fatalf("colon-containing name leaked as selector %q", blankSelector)
|
|
}
|
|
if _, _, parsedAsIdentity := authpkg.ParseIdentitySelector(blankSelector); parsedAsIdentity {
|
|
t.Fatalf("stable blank selector %q was parsed as an identity", blankSelector)
|
|
}
|
|
if got := profileCLISelector(blank, cfg); got != blankSelector {
|
|
t.Errorf("profileCLISelector(colon blank) = %q, want %q", got, blankSelector)
|
|
}
|
|
if got := profileSwitchProfileIndex(cfg.Profiles, cfg.CurrentProfile, cfg); got != 1 {
|
|
t.Errorf("profileSwitchProfileIndex(colon blank current) = %d, want 1", got)
|
|
}
|
|
model := newProfileSwitchTUIModel(cfg, cfg.CurrentProfile)
|
|
if model.selected != 1 {
|
|
t.Errorf("TUI selected index = %d, want colon-name blank profile index 1", model.selected)
|
|
}
|
|
if got := model.selectedCorpID(); got != blankSelector {
|
|
t.Errorf("TUI selected selector = %q, want %q", got, blankSelector)
|
|
}
|
|
|
|
selectors, views := captureProfileListSelectors(t, cfg)
|
|
if len(selectors) != 2 || selectors[0] != cfg.PreviousProfile || selectors[1] != blankSelector {
|
|
t.Errorf("profile list token selectors = %#v, want exact then %q", selectors, blankSelector)
|
|
}
|
|
if len(views) != 2 {
|
|
t.Fatalf("profile list views = %#v, want two entries", views)
|
|
}
|
|
if views[0].IsCurrent {
|
|
t.Error("exact account should not be marked current when colon-name blank selector is current")
|
|
}
|
|
if views[1].Profile != blankSelector || !views[1].IsCurrent {
|
|
t.Errorf("colon-name blank list view = %#v, want local selector marked current", views[1])
|
|
}
|
|
}
|