@@ -22,6 +22,8 @@ public class PackageSourcesPageTests : NuGetExternalSettingsProviderTests<Packag
2222 {
2323 private IEnumerable < PackageSource > _packageSources ;
2424 private IEnumerable < PackageSource > _savedPackageSources ;
25+ private IEnumerable < PackageSource > _auditSources ;
26+ private IEnumerable < PackageSource > _savedAuditSources ;
2527 private int _countEnablePackageSourceCalled = 0 ;
2628 private int _countDisablePackageSourceCalled = 0 ;
2729
@@ -30,7 +32,9 @@ public PackageSourcesPageTests(GlobalServiceProvider sp)
3032 sp . Reset ( ) ;
3133 NuGetUIThreadHelper . SetCustomJoinableTaskFactory ( ThreadHelper . JoinableTaskFactory ) ;
3234 _packageSources = Enumerable . Empty < PackageSource > ( ) ;
35+ _auditSources = Enumerable . Empty < PackageSource > ( ) ;
3336 _savedPackageSources = Enumerable . Empty < PackageSource > ( ) ;
37+ _savedAuditSources = Enumerable . Empty < PackageSource > ( ) ;
3438 }
3539
3640 protected override PackageSourcesPage CreateInstance ( VSSettings ? vsSettings )
@@ -39,13 +43,23 @@ protected override PackageSourcesPage CreateInstance(VSSettings? vsSettings)
3943 mockedPackageSourceProvider . Setup ( packageSourceProvider => packageSourceProvider . LoadPackageSources ( ) )
4044 . Returns ( _packageSources ) ;
4145
46+ mockedPackageSourceProvider . Setup ( packageSourceProvider => packageSourceProvider . LoadAuditSources ( ) )
47+ . Returns ( _auditSources . ToList ( ) . AsReadOnly ( ) ) ;
48+
4249 mockedPackageSourceProvider . Setup ( packageSourceProvider =>
4350 packageSourceProvider . SavePackageSources ( It . IsAny < IEnumerable < PackageSource > > ( ) ) )
4451 . Callback < IEnumerable < PackageSource > > ( sources =>
4552 {
4653 _savedPackageSources = sources ;
4754 } ) ;
4855
56+ mockedPackageSourceProvider . Setup ( packageSourceProvider =>
57+ packageSourceProvider . SaveAuditSources ( It . IsAny < IEnumerable < PackageSource > > ( ) ) )
58+ . Callback < IEnumerable < PackageSource > > ( sources =>
59+ {
60+ _savedAuditSources = sources ;
61+ } ) ;
62+
4963 mockedPackageSourceProvider . Setup ( packageSourceProvider =>
5064 packageSourceProvider . EnablePackageSource ( It . IsAny < string > ( ) ) )
5165 . Callback < string > ( name =>
@@ -63,6 +77,139 @@ protected override PackageSourcesPage CreateInstance(VSSettings? vsSettings)
6377 return new PackageSourcesPage ( vsSettings ! , mockedPackageSourceProvider . Object ) ;
6478 }
6579
80+ [ Theory ]
81+ [ InlineData ( true ) ]
82+ [ InlineData ( false ) ]
83+ public async Task SetValueAsync_AuditSources_WhenNameChanging_RaisesSettingValuesChangedAsync ( bool isNameChanging )
84+ {
85+ // Arrange
86+ string originalSourceName = "auditTestingSourceName" ;
87+ string originalSourceUrl = "https://auditTestingSource" ;
88+ string newSourceName = isNameChanging ? "auditTestingSourceNameEdited" : originalSourceName ;
89+ string newSourceUrl = isNameChanging ? originalSourceUrl : "https://auditTestingSourceEdited" ;
90+
91+ bool wasVsSettingsSettingsChangedCalled = false ;
92+
93+ _savedAuditSources =
94+ [
95+ new PackageSource ( originalSourceUrl , originalSourceName )
96+ ] ;
97+
98+ PackageSourcesPage instance = CreateInstance ( _vsSettings ) ;
99+ instance . SettingValuesChanged += ( sender , e ) =>
100+ {
101+ wasVsSettingsSettingsChangedCalled = true ;
102+ } ;
103+
104+ Dictionary < string , object > auditSourceDictionary = new Dictionary < string , object > ( ) ;
105+ auditSourceDictionary [ PackageSourcesPage . MonikerSourceName ] = newSourceName ;
106+ auditSourceDictionary [ PackageSourcesPage . MonikerSourceUrl ] = newSourceUrl ;
107+
108+ IList < IDictionary < string , object > > auditSourceDictionaryList =
109+ new List < IDictionary < string , object > > ( capacity : 1 )
110+ {
111+ auditSourceDictionary
112+ } ;
113+
114+ // Act
115+ ExternalSettingOperationResult result = await instance . SetValueAsync (
116+ PackageSourcesPage . MonikerAuditSources ,
117+ auditSourceDictionaryList ,
118+ CancellationToken . None ) ;
119+
120+ // Assert
121+ result . Should ( ) . NotBeNull ( ) ;
122+ result . Should ( ) . BeOfType < ExternalSettingOperationResult . Success > ( ) ;
123+ // VS refresh event isn't needed for audit sources name changes.
124+ wasVsSettingsSettingsChangedCalled . Should ( ) . Be ( false ) ;
125+ }
126+
127+ [ Theory ]
128+ [ InlineData ( @"http://" ) ]
129+ [ InlineData ( @"https://" ) ]
130+ [ InlineData ( @"https:// " ) ]
131+ [ InlineData ( @" https://" ) ]
132+ [ InlineData ( @"ftp://" ) ]
133+ [ InlineData ( @"http:/" ) ]
134+ public async Task SetValueAsync_AuditSources_WithInvalidRemoteSource_ReturnsFailureResultTaskAsync ( string invalidSource )
135+ {
136+ // Arrange
137+ PackageSourcesPage instance = CreateInstance ( _vsSettings ) ;
138+ Dictionary < string , object > auditSourceDictionary = new Dictionary < string , object > ( ) ;
139+
140+ auditSourceDictionary [ PackageSourcesPage . MonikerSourceName ] = "auditTestingSourceName" ;
141+ auditSourceDictionary [ PackageSourcesPage . MonikerSourceUrl ] = invalidSource ;
142+ auditSourceDictionary [ PackageSourcesPage . MonikerIsEnabled ] = true ;
143+ auditSourceDictionary [ PackageSourcesPage . MonikerAllowInsecureConnections ] = false ;
144+
145+ IList < IDictionary < string , object > > auditSourceDictionaryList =
146+ new List < IDictionary < string , object > > ( capacity : 1 )
147+ {
148+ auditSourceDictionary
149+ } ;
150+
151+ // Act
152+ ExternalSettingOperationResult result = await instance . SetValueAsync (
153+ PackageSourcesPage . MonikerAuditSources ,
154+ auditSourceDictionaryList ,
155+ CancellationToken . None ) ;
156+
157+ // Assert
158+ result . Should ( ) . NotBeNull ( ) ;
159+ result . Should ( ) . BeOfType < ExternalSettingOperationResult . Failure > ( ) ;
160+
161+ var failure = result as ExternalSettingOperationResult . Failure ;
162+ failure . Should ( ) . NotBeNull ( ) ;
163+ failure . IsTransient . Should ( ) . BeTrue ( ) ;
164+ failure . Scope . Should ( ) . Be ( ExternalSettingsErrorScope . SingleSettingOnly ) ;
165+ failure . ErrorMessage . Should ( ) . StartWith ( Strings . Error_PackageSource_InvalidSource ) ;
166+ }
167+
168+ [ Theory ]
169+ [ InlineData ( @"C" ) ]
170+ [ InlineData ( @"http" ) ] // Missing :// causes this to be treated as a file path.
171+ [ InlineData ( @"http:" ) ]
172+ [ InlineData ( @"ftp" ) ] // Missing :// causes this to be treated as a file path.
173+ [ InlineData ( @"C:" ) ]
174+ [ InlineData ( @"C:\\invalid\\*\\'\\chars" ) ]
175+ [ InlineData ( @"\\\\server\\invalid\\*\\" ) ]
176+ [ InlineData ( @"..\\packages" ) ]
177+ [ InlineData ( @"./configs/source.config" ) ]
178+ [ InlineData ( @"../local-packages/" ) ]
179+ public async Task SetValueAsync_AuditSources_WithInvalidUncPath_ReturnsFailureResultTaskAsync ( string invalidSource )
180+ {
181+ // Arrange
182+ PackageSourcesPage instance = CreateInstance ( _vsSettings ) ;
183+ Dictionary < string , object > auditSourceDictionary = new Dictionary < string , object > ( ) ;
184+
185+ auditSourceDictionary [ PackageSourcesPage . MonikerSourceName ] = "auditTestingSourceName" ;
186+ auditSourceDictionary [ PackageSourcesPage . MonikerSourceUrl ] = invalidSource ;
187+ auditSourceDictionary [ PackageSourcesPage . MonikerIsEnabled ] = true ;
188+ auditSourceDictionary [ PackageSourcesPage . MonikerAllowInsecureConnections ] = false ;
189+
190+ IList < IDictionary < string , object > > auditSourceDictionaryList =
191+ new List < IDictionary < string , object > > ( capacity : 1 )
192+ {
193+ auditSourceDictionary
194+ } ;
195+
196+ // Act
197+ ExternalSettingOperationResult result = await instance . SetValueAsync (
198+ PackageSourcesPage . MonikerAuditSources ,
199+ auditSourceDictionaryList ,
200+ CancellationToken . None ) ;
201+
202+ // Assert
203+ result . Should ( ) . NotBeNull ( ) ;
204+ result . Should ( ) . BeOfType < ExternalSettingOperationResult . Failure > ( ) ;
205+
206+ var failure = result as ExternalSettingOperationResult . Failure ;
207+ failure . Should ( ) . NotBeNull ( ) ;
208+ failure . IsTransient . Should ( ) . BeTrue ( ) ;
209+ failure . Scope . Should ( ) . Be ( ExternalSettingsErrorScope . SingleSettingOnly ) ;
210+ failure . ErrorMessage . Should ( ) . StartWith ( Strings . Error_PackageSource_InvalidSource ) ;
211+ }
212+
66213 [ Fact ]
67214 public async Task GetValueAsync_WhenNuGetConfigHasInvalidSource_ReturnsFailureResultTaskAsync ( )
68215 {
0 commit comments