package scopes import ( "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func TestGetToolScopeMap(t *testing.T) { // Reset and set up a test map SetGlobalToolScopeMap(ToolScopeMap{ "test_tool": &ToolScopeInfo{ RequiredScopes: []string{"read:org"}, AcceptedScopes: []string{"read:org", "write:org", "admin:org"}, }, }) m, err := GetToolScopeMap() require.NoError(t, err) require.NotNil(t, m) require.Greater(t, len(m), 0, "expected at least one tool in the scope map") testTool, ok := m["test_tool"] require.True(t, ok, "expected test_tool to be in the scope map") assert.Contains(t, testTool.RequiredScopes, "read:org") assert.Contains(t, testTool.AcceptedScopes, "read:org") assert.Contains(t, testTool.AcceptedScopes, "admin:org") } func TestGetToolScopeInfo(t *testing.T) { // Set up test scope map SetGlobalToolScopeMap(ToolScopeMap{ "search_orgs": &ToolScopeInfo{ RequiredScopes: []string{"read:org"}, AcceptedScopes: []string{"read:org", "write:org", "admin:org"}, }, }) info, err := GetToolScopeInfo("search_orgs") require.NoError(t, err) require.NotNil(t, info) // Non-existent tool should return nil info, err = GetToolScopeInfo("nonexistent_tool") require.NoError(t, err) assert.Nil(t, info) } func TestToolScopeInfo_HasAcceptedScope(t *testing.T) { testCases := []struct { name string scopeInfo *ToolScopeInfo userScopes []string expected bool }{ { name: "has exact required scope", scopeInfo: &ToolScopeInfo{ RequiredScopes: []string{"read:org"}, AcceptedScopes: []string{"read:org", "write:org", "admin:org"}, }, userScopes: []string{"read:org"}, expected: true, }, { name: "has parent scope (admin:org grants read:org)", scopeInfo: &ToolScopeInfo{ RequiredScopes: []string{"read:org"}, AcceptedScopes: []string{"read:org", "write:org", "admin:org"}, }, userScopes: []string{"admin:org"}, expected: true, }, { name: "has parent scope (write:org grants read:org)", scopeInfo: &ToolScopeInfo{ RequiredScopes: []string{"read:org"}, AcceptedScopes: []string{"read:org", "write:org", "admin:org"}, }, userScopes: []string{"write:org"}, expected: true, }, { name: "missing required scope", scopeInfo: &ToolScopeInfo{ RequiredScopes: []string{"read:org"}, AcceptedScopes: []string{"read:org", "write:org", "admin:org"}, }, userScopes: []string{"repo"}, expected: false, }, { name: "no scope required", scopeInfo: &ToolScopeInfo{ RequiredScopes: []string{}, AcceptedScopes: []string{}, }, userScopes: []string{}, expected: true, }, { name: "nil scope info", scopeInfo: nil, userScopes: []string{}, expected: true, }, { name: "repo scope for tool requiring repo", scopeInfo: &ToolScopeInfo{ RequiredScopes: []string{"repo"}, AcceptedScopes: []string{"repo"}, }, userScopes: []string{"repo"}, expected: true, }, { name: "missing repo scope", scopeInfo: &ToolScopeInfo{ RequiredScopes: []string{"repo"}, AcceptedScopes: []string{"repo"}, }, userScopes: []string{"public_repo"}, expected: false, }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { result := tc.scopeInfo.HasAcceptedScope(tc.userScopes...) assert.Equal(t, tc.expected, result) }) } } func TestToolScopeInfo_MissingScopes(t *testing.T) { testCases := []struct { name string scopeInfo *ToolScopeInfo userScopes []string expectedLen int expectedScopes []string }{ { name: "has required scope - no missing", scopeInfo: &ToolScopeInfo{ RequiredScopes: []string{"read:org"}, AcceptedScopes: []string{"read:org", "write:org", "admin:org"}, }, userScopes: []string{"read:org"}, expectedLen: 0, expectedScopes: nil, }, { name: "missing scope", scopeInfo: &ToolScopeInfo{ RequiredScopes: []string{"read:org"}, AcceptedScopes: []string{"read:org", "write:org", "admin:org"}, }, userScopes: []string{"repo"}, expectedLen: 1, expectedScopes: []string{"read:org"}, }, { name: "no scope required - no missing", scopeInfo: &ToolScopeInfo{ RequiredScopes: []string{}, AcceptedScopes: []string{}, }, userScopes: []string{}, expectedLen: 0, expectedScopes: nil, }, { name: "nil scope info - no missing", scopeInfo: nil, userScopes: []string{}, expectedLen: 0, expectedScopes: nil, }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { missing := tc.scopeInfo.MissingScopes(tc.userScopes...) assert.Len(t, missing, tc.expectedLen) if tc.expectedScopes != nil { for _, expected := range tc.expectedScopes { assert.Contains(t, missing, expected) } } }) } }