@@ -311,18 +311,14 @@ public virtual bool Validate(TestSettingExtensions settings, string file)
311311 /// <returns></returns>
312312 public bool VerifyContainsValidNamespacePowerFxFunctions ( TestSettingExtensions settings , byte [ ] assembly )
313313 {
314- var isValid = true ;
315-
316314#if DEBUG
317- // Add Experimenal namespaces in Debug compile if it has not been added in allow list
318315 if ( ! settings . AllowPowerFxNamespaces . Contains ( NAMESPACE_PREVIEW ) )
319316 {
320317 settings . AllowPowerFxNamespaces . Add ( NAMESPACE_PREVIEW ) ;
321318 }
322319#endif
323320
324321#if RELEASE
325- // Add Deprecated namespaces in Release compile if it has not been added in deny list
326322 if ( ! settings . DenyPowerFxNamespaces . Contains ( NAMESPACE_DEPRECATED ) )
327323 {
328324 settings . DenyPowerFxNamespaces . Add ( NAMESPACE_DEPRECATED ) ;
@@ -334,6 +330,59 @@ public bool VerifyContainsValidNamespacePowerFxFunctions(TestSettingExtensions s
334330 stream . Position = 0 ;
335331 ModuleDefinition module = ModuleDefinition . ReadModule ( stream ) ;
336332
333+ var isProviderAssembly = module . Types . Any ( t =>
334+ t . Interfaces . Any ( i =>
335+ i . InterfaceType . FullName == typeof ( Providers . ITestWebProvider ) . FullName ||
336+ i . InterfaceType . FullName == typeof ( Users . IUserManager ) . FullName ||
337+ i . InterfaceType . FullName == typeof ( Config . IUserCertificateProvider ) . FullName ) ) ;
338+
339+ var isActionModule = module . Types . Any ( t => t . Name . EndsWith ( "Module" ) &&
340+ ! t . Interfaces . Any ( i =>
341+ i . InterfaceType . FullName == typeof ( Providers . ITestWebProvider ) . FullName ||
342+ i . InterfaceType . FullName == typeof ( Users . IUserManager ) . FullName ||
343+ i . InterfaceType . FullName == typeof ( Config . IUserCertificateProvider ) . FullName ) ) ;
344+
345+ bool previewNamespaceEnabled = false ;
346+
347+ if ( isActionModule )
348+ {
349+ // Generic preview namespace detection for any module with preview support
350+ var previewProperty = module . Types
351+ . Where ( t => t . Name . EndsWith ( "Module" ) )
352+ . SelectMany ( t => t . Properties )
353+ . FirstOrDefault ( p => p . Name . Contains ( "Preview" ) && p . Name . Contains ( "Namespace" ) ) ;
354+
355+ if ( previewProperty != null )
356+ {
357+ var moduleWithPreviewSupport = previewProperty . DeclaringType ;
358+
359+ #if RELEASE
360+ // In RELEASE mode, check if Preview namespace is in settings
361+ previewNamespaceEnabled = settings . AllowPowerFxNamespaces . Contains ( NAMESPACE_PREVIEW ) ;
362+
363+ if ( previewNamespaceEnabled )
364+ {
365+ Logger ? . LogInformation ( "RELEASE: Preview namespace enabled based on YAML settings" ) ;
366+ }
367+ else
368+ {
369+ Logger ? . LogInformation ( "RELEASE: Preview namespace not enabled in YAML settings" ) ;
370+ }
371+
372+ Logger ? . LogInformation ( $ "RELEASE: { moduleWithPreviewSupport . Name } detected. Preview namespace enabled: { previewNamespaceEnabled } ") ;
373+ #else
374+ // In DEBUG mode, Preview namespace is already auto-added above
375+ previewNamespaceEnabled = true ;
376+ Logger ? . LogInformation ( $ "DEBUG: { moduleWithPreviewSupport . Name } detected. Preview namespace auto-enabled in DEBUG mode") ;
377+ #endif
378+ }
379+ else
380+ {
381+ previewNamespaceEnabled = settings . AllowPowerFxNamespaces . Contains ( NAMESPACE_PREVIEW ) ;
382+ Logger ? . LogInformation ( $ "Action module without preview support property. Preview namespace enabled from settings: { previewNamespaceEnabled } ") ;
383+ }
384+ }
385+
337386 // Get the source code of the assembly as will be used to check Power FX Namespaces
338387 var code = DecompileModuleToCSharp ( assembly ) ;
339388
@@ -352,6 +401,13 @@ public bool VerifyContainsValidNamespacePowerFxFunctions(TestSettingExtensions s
352401 {
353402 foreach ( var name in values )
354403 {
404+ // For providers, allow Preview namespace regardless of action module settings
405+ if ( name == NAMESPACE_PREVIEW )
406+ {
407+ Logger ? . LogInformation ( $ "Allowing Preview namespace for provider { type . Name } ") ;
408+ continue ;
409+ }
410+
355411 // Check against deny list using regular expressions
356412 if ( settings . DenyPowerFxNamespaces . Any ( pattern => Regex . IsMatch ( name , WildcardToRegex ( pattern ) ) ) )
357413 {
@@ -382,6 +438,18 @@ public bool VerifyContainsValidNamespacePowerFxFunctions(TestSettingExtensions s
382438 // Extension Module Check are based on constructor
383439 if ( type . BaseType != null && type . BaseType . Name == "ReflectionFunction" )
384440 {
441+ // For provider assemblies, skip all function validation
442+ if ( isProviderAssembly )
443+ {
444+ Logger ? . LogInformation ( $ "Skipping function validation for provider assembly function: { type . Name } ") ;
445+ continue ;
446+ }
447+ if ( isActionModule )
448+ {
449+ // Skip namespace validation for functions in action modules - they're controlled by the module-level logic above
450+ continue ;
451+ }
452+
385453 var constructors = type . GetConstructors ( ) ;
386454
387455 if ( constructors . Count ( ) == 0 )
@@ -466,7 +534,7 @@ public bool VerifyContainsValidNamespacePowerFxFunctions(TestSettingExtensions s
466534 }
467535 }
468536 }
469- return isValid ;
537+ return true ;
470538 }
471539
472540 // Helper method to convert wildcard patterns to regular expressions
0 commit comments