Skip to content

Commit 19dcdcd

Browse files
jsuarezruizrmarinhotj-devel709
authored
[Testing] Enable snapshot tests on Catalyst (#25710)
* Enable snapshot tests on Catalyst * Added some mac snapshots * Updated mac test project * More snapshots * More snapshots * Added scripts to disable the notification center running macos UI tests * More snapshots * More snapshots * More snapshots * More fixes * Updated snapshot * More snapshots * Updated snapshot * Ignore test on Catalyst * More changes * More changes * More fixes * Update AppiumCatalystApp.cs * Added snapshot from new UITest * more mac screenshots --------- Co-authored-by: Rui Marinho <me@ruimarinho.net> Co-authored-by: tj-devel709 <tj.devel709@gmail.com>
1 parent 7291b48 commit 19dcdcd

File tree

85 files changed

+214
-13
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

85 files changed

+214
-13
lines changed

eng/pipelines/common/ui-tests-steps.yml

+17-1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,14 @@ steps:
3737
continueOnError: true
3838
timeoutInMinutes: 60
3939
40+
- ${{ if eq(parameters.platform, 'catalyst')}}:
41+
- bash: |
42+
chmod +x $(System.DefaultWorkingDirectory)/eng/scripts/disable-notification-center.sh
43+
$(System.DefaultWorkingDirectory)/eng/scripts/disable-notification-center.sh
44+
displayName: 'Disable Notification Center'
45+
continueOnError: true
46+
timeoutInMinutes: 60
47+
4048
- template: provision.yml
4149
parameters:
4250
skipAndroidSdks: ${{ ne(parameters.platform, 'android') }}
@@ -143,8 +151,16 @@ steps:
143151
condition: always()
144152
displayName: publish artifacts
145153

154+
- ${{ if eq(parameters.platform, 'catalyst')}}:
155+
- bash: |
156+
chmod +x $(System.DefaultWorkingDirectory)/eng/scripts/enable-notification-center.sh
157+
$(System.DefaultWorkingDirectory)/eng/scripts/enable-notification-center.sh
158+
displayName: 'Enable Notification Center'
159+
continueOnError: true
160+
timeoutInMinutes: 60
161+
146162
- ${{ if and(eq(parameters.platform, 'ios'), ne(parameters.poolName, 'Azure Pipelines'), eq(variables['System.TeamProject'], 'devdiv') ) }}:
147163
# This must always be placed as the last step in the job
148164
- template: agent-rebooter/mac.v1.yml@yaml-templates
149165
parameters:
150-
AgentPoolAccessToken: ${{ parameters.agentPoolAccessToken }}
166+
AgentPoolAccessToken: ${{ parameters.agentPoolAccessToken }}
+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#!/bin/sh
2+
3+
export PATH=/usr/bin:/bin:/usr/sbin:/sbin
4+
5+
currentUser=$( echo "show State:/Users/ConsoleUser" | scutil | awk '/Name :/ { print $3 }' )
6+
7+
if [ -z "$currentUser" -o "$currentUser" = "loginwindow" ]; then
8+
echo "no user logged in, cannot proceed"
9+
exit 1
10+
fi
11+
12+
uid=$(id -u "$currentUser")
13+
14+
runAsUser() {
15+
if [ "$currentUser" != "loginwindow" ]; then
16+
launchctl asuser "$uid" sudo -u "$currentUser" "$@"
17+
else
18+
echo "no user logged in"
19+
fi
20+
}
21+
22+
runAsUser launchctl unload -w /System/Library/LaunchAgents/com.apple.notificationcenterui.plist
+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#!/bin/sh
2+
export PATH=/usr/bin:/bin:/usr/sbin:/sbin
3+
4+
currentUser=$( echo "show State:/Users/ConsoleUser" | scutil | awk '/Name :/ { print $3 }' )
5+
6+
if [ -z "$currentUser" -o "$currentUser" = "loginwindow" ]; then
7+
echo "no user logged in, cannot proceed"
8+
exit 1
9+
fi
10+
11+
uid=$(id -u "$currentUser")
12+
13+
runAsUser() {
14+
if [ "$currentUser" != "loginwindow" ]; then
15+
launchctl asuser "$uid" sudo -u "$currentUser" "$@"
16+
else
17+
echo "no user logged in"
18+
fi
19+
}
20+
21+
runAsUser launchctl load -w /System/Library/LaunchAgents/com.apple.notificationcenterui.plist

src/Controls/tests/TestCases.Mac.Tests/Controls.TestCases.Mac.Tests.csproj

+7-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,13 @@
4040
<ProjectReference Include="$(MauiRootDirectory)..\visual-test-utils\src\VisualTestUtils.MagickNet\VisualTestUtils.MagickNet.csproj" />
4141
<ProjectReference Include="$(MauiRootDirectory)..\visual-test-utils\src\VisualTestUtils\VisualTestUtils.csproj" />
4242
</ItemGroup>
43-
43+
44+
<ItemGroup>
45+
<Content Include="snapshots\**">
46+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
47+
</Content>
48+
</ItemGroup>
49+
4450
<ItemGroup>
4551
<Compile Include="..\TestCases.Shared.Tests\**\*.cs" Exclude="..\TestCases.Shared.Tests\obj\**;..\TestCases.Shared.Tests\bin\**" LinkBase="Shared" Visible="false" />
4652
</ItemGroup>

src/Controls/tests/TestCases.Shared.Tests/Tests/ImageButtonUITests.cs

+2
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ protected override void NavigateToGallery()
1919
App.NavigateToGallery(ImageButtonGallery);
2020
}
2121

22+
#if TEST_FAILS_ON_CATALYST
2223
[Test]
2324
public void Aspect()
2425
{
@@ -37,6 +38,7 @@ public void Aspect()
3738
remote.TapStateButton();
3839
VerifyScreenshot("ImageButtonUITests_Aspect_State_AspectFit");
3940
}
41+
#endif
4042

4143
[Test]
4244
public void Aspect_AspectFill()

src/Controls/tests/TestCases.Shared.Tests/Tests/ImageUITests.cs

+2
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ public override void IsEnabled()
2424
Assert.Ignore("Image elements do not really have a concept of being \"disabled\".");
2525
}
2626

27+
#if TEST_FAILS_ON_CATALYST
2728
[Test]
2829
public void Source_FontImageSource()
2930
{
@@ -36,6 +37,7 @@ public void Source_FontImageSource()
3637
remote.TapStateButton();
3738
VerifyScreenshot("ImageUITests_Source_FontImageSource_FontAwesome");
3839
}
40+
#endif
3941

4042
[Test]
4143
public async Task IsAnimationPlaying()

src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue22306.cs

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#if TEST_FAILS_ON_CATALYST
12
using NUnit.Framework;
23
using UITest.Appium;
34
using UITest.Core;
@@ -58,3 +59,4 @@ void WaitForAllElements()
5859
}
5960
}
6061
}
62+
#endif

src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue22306_2.cs

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using NUnit.Framework;
1+
#if TEST_FAILS_ON_CATALYST
2+
using NUnit.Framework;
23
using UITest.Appium;
34
using UITest.Core;
45

@@ -27,3 +28,4 @@ public void BorderWidthAffectsTheImageSizing()
2728
}
2829
}
2930
}
31+
#endif

src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue22306_3.cs

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#if TEST_FAILS_ON_CATALYST
12
using NUnit.Framework;
23
using UITest.Appium;
34
using UITest.Core;
@@ -103,3 +104,4 @@ public void VerifyButtonPage8()
103104
}
104105
}
105106
}
107+
#endif

src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue22433.cs

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using NUnit.Framework;
1+
#if TEST_FAILS_ON_CATALYST
2+
using NUnit.Framework;
23
using UITest.Appium;
34
using UITest.Core;
45

@@ -35,3 +36,4 @@ public async Task ButtonLayoutAndSpacingTests()
3536
}
3637
}
3738
}
39+
#endif

src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue22606.cs

+2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ public Issue22606(TestDevice device) : base(device) { }
1111

1212
public override string Issue => "Border does not expand on Content size changed";
1313

14+
#if !MACCATALYST
1415
[Test]
1516
public void BorderBackgroundExpandsOnContentSizeChanged()
1617
{
@@ -21,6 +22,7 @@ public void BorderBackgroundExpandsOnContentSizeChanged()
2122
App.Tap("SetHeightTo500");
2223
VerifyScreenshot("Issue22606_SetHeightTo500");
2324
}
25+
#endif
2426

2527
#if ANDROID || IOS
2628
[Test]

src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue24583.cs

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using NUnit.Framework;
1+
#if TEST_FAILS_ON_CATALYST
2+
using NUnit.Framework;
23
using UITest.Appium;
34
using UITest.Core;
45

@@ -20,4 +21,5 @@ public void TextInEditorShouldBeCorrectlyPositionedAfterResizing()
2021
App.Click("button");
2122
VerifyScreenshot("TextsInEditorsAfterScaling");
2223
}
23-
}
24+
}
25+
#endif

src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue25074.cs

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#if TEST_FAILS_ON_CATALYST
12
using NUnit.Framework;
23
using UITest.Appium;
34
using UITest.Core;
@@ -23,3 +24,4 @@ public void ButtonResizesWhenTitleOrImageChanges()
2324
}
2425
}
2526
}
27+
#endif

src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue25074_2.cs

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#if TEST_FAILS_ON_CATALYST
12
using NUnit.Framework;
23
using UITest.Appium;
34
using UITest.Core;
@@ -23,3 +24,4 @@ public void ButtonTitleFillsSpaceWhenImageChanges()
2324
}
2425
}
2526
}
27+
#endif

src/Controls/tests/TestCases.Shared.Tests/UITest.cs

+25-7
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
using System.Reflection;
22
using NUnit.Framework;
3-
using OpenQA.Selenium.Appium.iOS;
43
using UITest.Appium;
54
using UITest.Appium.NUnit;
65
using UITest.Core;
@@ -178,11 +177,7 @@ but both can happen.
178177
break;
179178

180179
case TestDevice.Mac:
181-
// For now, ignore visual tests on Mac Catalyst since the Appium screenshot on Mac (unlike Windows)
182-
// is of the entire screen, not just the app. Later when xharness relay support is in place to
183-
// send a message to the MAUI app to get the screenshot, we can use that to just screenshot
184-
// the app.
185-
Assert.Ignore("MacCatalyst isn't supported yet for visual tests");
180+
environmentName = "mac";
186181
break;
187182

188183
default:
@@ -198,7 +193,11 @@ but both can happen.
198193
Thread.Sleep(350);
199194
}
200195

196+
#if MACUITEST
197+
byte[] screenshotPngBytes = TakeScreenshot() ?? throw new InvalidOperationException("Failed to get screenshot");
198+
#else
201199
byte[] screenshotPngBytes = App.Screenshot() ?? throw new InvalidOperationException("Failed to get screenshot");
200+
#endif
202201

203202
var actualImage = new ImageSnapshot(screenshotPngBytes, ImageSnapshotFormat.PNG);
204203

@@ -254,8 +253,27 @@ public override void TestSetup()
254253
Thread.Sleep(1000);
255254
App.SetOrientationPortrait();
256255
}
257-
258256
}
259257
}
258+
259+
#if MACUITEST
260+
byte[] TakeScreenshot()
261+
{
262+
// Since the Appium screenshot on Mac (unlike Windows) is of the entire screen, not just the app,
263+
// we are going to maximize the App before take the screenshot.
264+
App.EnterFullScreen();
265+
266+
// The app might not be ready to take the screenshot.
267+
// Wait a little bit to complete the system animation moving the App Window to FullScreen.
268+
Thread.Sleep(1000);
269+
270+
byte[] screenshotPngBytes = App.Screenshot() ?? throw new InvalidOperationException("Failed to get screenshot");
271+
272+
// TODO: After take the screenshot, restore the App Window to the previous state.
273+
App.ExitFullScreen();
274+
275+
return screenshotPngBytes;
276+
}
277+
#endif
260278
}
261279
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
using UITest.Core;
2+
3+
namespace UITest.Appium;
4+
5+
public class AppiumCatalystSpecificActions : ICommandExecutionGroup
6+
{
7+
const string EnterFullScreenCommand = "enterFullScreen";
8+
const string ExitFullScreenCommand = "exitFullScreen";
9+
10+
readonly AppiumApp _appiumApp;
11+
12+
readonly List<string> _commands = new()
13+
{
14+
EnterFullScreenCommand,
15+
ExitFullScreenCommand,
16+
};
17+
18+
public AppiumCatalystSpecificActions(AppiumApp appiumApp)
19+
{
20+
_appiumApp = appiumApp;
21+
}
22+
23+
public bool IsCommandSupported(string commandName)
24+
{
25+
return _commands.Contains(commandName, StringComparer.OrdinalIgnoreCase);
26+
}
27+
28+
public CommandResponse Execute(string commandName, IDictionary<string, object> parameters)
29+
{
30+
return commandName switch
31+
{
32+
EnterFullScreenCommand => EnterFullScreen(parameters),
33+
ExitFullScreenCommand => ExitFullScreen(parameters),
34+
_ => CommandResponse.FailedEmptyResponse,
35+
};
36+
}
37+
38+
CommandResponse EnterFullScreen(IDictionary<string, object> parameters)
39+
{
40+
try
41+
{
42+
_appiumApp.Driver.Manage().Window.FullScreen();
43+
44+
return CommandResponse.SuccessEmptyResponse;
45+
}
46+
catch
47+
{
48+
return CommandResponse.FailedEmptyResponse;
49+
}
50+
}
51+
52+
CommandResponse ExitFullScreen(IDictionary<string, object> parameters)
53+
{
54+
try
55+
{
56+
string[] keys = ["XCUIKeyboardKeyEscape"];
57+
_appiumApp.Driver.ExecuteScript("macos: keys", new Dictionary<string, object>
58+
{
59+
{ "keys", keys },
60+
});
61+
62+
return CommandResponse.SuccessEmptyResponse;
63+
}
64+
catch
65+
{
66+
return CommandResponse.FailedEmptyResponse;
67+
}
68+
}
69+
}

src/TestUtils/src/UITest.Appium/AppiumCatalystApp.cs

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ public AppiumCatalystApp(Uri remoteAddress, IConfig config)
1313
_commandExecutor.AddCommandGroup(new AppiumCatalystMouseActions(this));
1414
_commandExecutor.AddCommandGroup(new AppiumCatalystTouchActions(this));
1515
_commandExecutor.AddCommandGroup(new AppiumCatalystAlertActions(this));
16+
_commandExecutor.AddCommandGroup(new AppiumCatalystSpecificActions(this));
1617
_commandExecutor.AddCommandGroup(new AppiumCatalystVirtualKeyboardActions(this));
1718
}
1819

0 commit comments

Comments
 (0)