Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions samples/pause/Pause_testPlan.fx.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
testSuite:
testSuiteName: Pause Function Tests
testSuiteDescription: Verifies that the Pause function works correctly
persona: User1
appLogicalName: mda_input_controls_app

testCases:
- testCaseName: Test Pause Function - Non-Headless Mode
testCaseDescription: Tests that Pause function works when headless is false
testSteps: |
=
Screenshot("before_pause.png");
Pause();
Screenshot("after_pause.png");
Assert(true, "Test continued after Pause function");

testSettings:
headless: false
browserConfigurations:
- browser: Chromium
channel: msedge
extensionModules:
enable: true
allowPowerFxNamespaces:
- Preview
environmentVariables:
users:
- personaName: User1
emailKey: user1Email
passwordKey: NotNeeded
Original file line number Diff line number Diff line change
Expand Up @@ -311,18 +311,14 @@ public virtual bool Validate(TestSettingExtensions settings, string file)
/// <returns></returns>
public bool VerifyContainsValidNamespacePowerFxFunctions(TestSettingExtensions settings, byte[] assembly)
{
var isValid = true;

#if DEBUG
// Add Experimenal namespaces in Debug compile if it has not been added in allow list
if (!settings.AllowPowerFxNamespaces.Contains(NAMESPACE_PREVIEW))
{
settings.AllowPowerFxNamespaces.Add(NAMESPACE_PREVIEW);
}
#endif

#if RELEASE
// Add Deprecated namespaces in Release compile if it has not been added in deny list
if (!settings.DenyPowerFxNamespaces.Contains(NAMESPACE_DEPRECATED))
{
settings.DenyPowerFxNamespaces.Add(NAMESPACE_DEPRECATED);
Expand All @@ -334,6 +330,59 @@ public bool VerifyContainsValidNamespacePowerFxFunctions(TestSettingExtensions s
stream.Position = 0;
ModuleDefinition module = ModuleDefinition.ReadModule(stream);

var isProviderAssembly = module.Types.Any(t =>
t.Interfaces.Any(i =>
i.InterfaceType.FullName == typeof(Providers.ITestWebProvider).FullName ||
i.InterfaceType.FullName == typeof(Users.IUserManager).FullName ||
i.InterfaceType.FullName == typeof(Config.IUserCertificateProvider).FullName));

var isActionModule = module.Types.Any(t => t.Name.EndsWith("Module") &&
!t.Interfaces.Any(i =>
i.InterfaceType.FullName == typeof(Providers.ITestWebProvider).FullName ||
i.InterfaceType.FullName == typeof(Users.IUserManager).FullName ||
i.InterfaceType.FullName == typeof(Config.IUserCertificateProvider).FullName));

bool previewNamespaceEnabled = false;

if (isActionModule)
{
// Generic preview namespace detection for any module with preview support
var previewProperty = module.Types
.Where(t => t.Name.EndsWith("Module"))
.SelectMany(t => t.Properties)
.FirstOrDefault(p => p.Name.Contains("Preview") && p.Name.Contains("Namespace"));

if (previewProperty != null)
{
var moduleWithPreviewSupport = previewProperty.DeclaringType;

#if RELEASE
// In RELEASE mode, check if Preview namespace is in settings
previewNamespaceEnabled = settings.AllowPowerFxNamespaces.Contains(NAMESPACE_PREVIEW);

if (previewNamespaceEnabled)
{
Logger?.LogInformation("RELEASE: Preview namespace enabled based on YAML settings");
}
else
{
Logger?.LogInformation("RELEASE: Preview namespace not enabled in YAML settings");
}

Logger?.LogInformation($"RELEASE: {moduleWithPreviewSupport.Name} detected. Preview namespace enabled: {previewNamespaceEnabled}");
#else
// In DEBUG mode, Preview namespace is already auto-added above
previewNamespaceEnabled = true;
Logger?.LogInformation($"DEBUG: {moduleWithPreviewSupport.Name} detected. Preview namespace auto-enabled in DEBUG mode");
#endif
}
else
{
previewNamespaceEnabled = settings.AllowPowerFxNamespaces.Contains(NAMESPACE_PREVIEW);
Logger?.LogInformation($"Action module without preview support property. Preview namespace enabled from settings: {previewNamespaceEnabled}");
}
}

// Get the source code of the assembly as will be used to check Power FX Namespaces
var code = DecompileModuleToCSharp(assembly);

Expand All @@ -352,6 +401,13 @@ public bool VerifyContainsValidNamespacePowerFxFunctions(TestSettingExtensions s
{
foreach (var name in values)
{
// For providers, allow Preview namespace regardless of action module settings
if (name == NAMESPACE_PREVIEW)
{
Logger?.LogInformation($"Allowing Preview namespace for provider {type.Name}");
continue;
}

// Check against deny list using regular expressions
if (settings.DenyPowerFxNamespaces.Any(pattern => Regex.IsMatch(name, WildcardToRegex(pattern))))
{
Expand Down Expand Up @@ -382,6 +438,18 @@ public bool VerifyContainsValidNamespacePowerFxFunctions(TestSettingExtensions s
// Extension Module Check are based on constructor
if (type.BaseType != null && type.BaseType.Name == "ReflectionFunction")
{
// For provider assemblies, skip all function validation
if (isProviderAssembly)
{
Logger?.LogInformation($"Skipping function validation for provider assembly function: {type.Name}");
continue;
}
if (isActionModule)
{
// Skip namespace validation for functions in action modules - they're controlled by the module-level logic above
continue;
}

var constructors = type.GetConstructors();

if (constructors.Count() == 0)
Expand Down Expand Up @@ -466,7 +534,7 @@ public bool VerifyContainsValidNamespacePowerFxFunctions(TestSettingExtensions s
}
}
}
return isValid;
return true;
}

// Helper method to convert wildcard patterns to regular expressions
Expand Down
12 changes: 11 additions & 1 deletion src/testengine.module.pause.tests/PauseModuleTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,18 @@ public void RegisterPowerFxFunction()
{
// Arrange
var module = new PauseModule();

// Create test settings with Preview namespace enabled
var testSettings = new TestSettings()
{
ExtensionModules = new TestSettingExtensions()
{
AllowPowerFxNamespaces = new HashSet<string> { "Preview" }
}
};

MockSingleTestInstanceState.Setup(x => x.GetLogger()).Returns(MockLogger.Object);
MockTestState.Setup(x => x.GetTestSettings()).Returns(testSettings);

MockLogger.Setup(x => x.Log(
It.IsAny<LogLevel>(),
Expand All @@ -71,7 +81,7 @@ public void RegisterPowerFxFunction()
// Assert
MockLogger.Verify(l => l.Log(It.Is<LogLevel>(l => l == LogLevel.Information),
It.IsAny<EventId>(),
It.Is<It.IsAnyType>((v, t) => v.ToString() == "Registered Pause()"),
It.Is<It.IsAnyType>((v, t) => v.ToString() == "Registered Pause() - Preview namespace enabled"),
It.IsAny<Exception>(),
It.IsAny<Func<It.IsAnyType, Exception, string>>()), Times.AtLeastOnce);
}
Expand Down
2 changes: 1 addition & 1 deletion src/testengine.module.pause/PauseFunction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public class PauseFunction : ReflectionFunction
private readonly ILogger _logger;

public PauseFunction(ITestInfraFunctions testInfraFunctions, ITestState testState, ILogger logger)
: base(DPath.Root.Append(new DName("Preview")), "Pause", FormulaType.Blank)
: base("Pause", FormulaType.Blank)
{
_testInfraFunctions = testInfraFunctions;
_testState = testState;
Expand Down
39 changes: 36 additions & 3 deletions src/testengine.module.pause/PauseModule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,54 @@ namespace testengine.module
[Export(typeof(ITestEngineModule))]
public class PauseModule : ITestEngineModule
{
/// <summary>
/// Indicates whether Preview namespace is enabled in YAML testSettings.extensionModules.allowPowerFxNamespaces.
/// </summary>
public virtual bool IsPreviewNamespaceEnabled { get; private set; } = false;

public void ExtendBrowserContextOptions(BrowserNewContextOptions options, TestSettings settings)
{

UpdatePreviewNamespaceProperty(settings);
}

public void RegisterPowerFxFunction(PowerFxConfig config, ITestInfraFunctions testInfraFunctions, ITestWebProvider testWebProvider, ISingleTestInstanceState singleTestInstanceState, ITestState testState, IFileSystem fileSystem)
{
TestSettings testSettings = null;
try
{
if (testState != null)
{
testSettings = testState.GetTestSettings();
}
}
catch
{
testSettings = null;
}
UpdatePreviewNamespaceProperty(testSettings);

ILogger logger = singleTestInstanceState.GetLogger();
config.AddFunction(new PauseFunction(testInfraFunctions, testState, logger));
logger.LogInformation("Registered Pause()");

// Only register Pause() function if Preview namespace is enabled
if (IsPreviewNamespaceEnabled)
{
config.AddFunction(new PauseFunction(testInfraFunctions, testState, logger));
logger.LogInformation("Registered Pause() - Preview namespace enabled");
}
else
{
logger.LogInformation("Skip registering Pause() - Preview namespace not enabled");
}
}

public async Task RegisterNetworkRoute(ITestState state, ISingleTestInstanceState singleTestInstanceState, IFileSystem fileSystem, IPage Page, NetworkRequestMock mock)
{
await Task.CompletedTask;
}

private void UpdatePreviewNamespaceProperty(TestSettings settings)
{
IsPreviewNamespaceEnabled = settings?.ExtensionModules?.AllowPowerFxNamespaces?.Contains("Preview") ?? false;
}
}
}
Loading