Skip to content

Commit 2d0ebca

Browse files
committed
Cover reader keyboard shortcuts (#35)
1 parent 75790a3 commit 2d0ebca

3 files changed

Lines changed: 139 additions & 0 deletions

File tree

tests/PrompterOne.Web.UITests.Reader/Learn/LearnKeyboardShortcutFlowTests.cs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System.Globalization;
12
using PrompterOne.Shared.Contracts;
23
using static Microsoft.Playwright.Assertions;
34

@@ -7,6 +8,8 @@ namespace PrompterOne.Web.UITests;
78
public sealed class LearnKeyboardShortcutFlowTests(StandaloneAppFixture fixture)
89
: AppUiTestBase(fixture)
910
{
11+
private readonly record struct ProgressState(int CurrentWordNumber, int TotalWordCount);
12+
1013
[Test]
1114
public Task LearnPage_KeyboardShortcuts_ToggleLoopPlaybackAndSpeed() =>
1215
RunPageAsync(async page =>
@@ -30,9 +33,68 @@ await Expect(page.GetByTestId(UiTestIds.Learn.LoopToggle))
3033
await Expect(page.GetByTestId(UiTestIds.Learn.SpeedValue))
3134
.ToHaveTextAsync(BrowserTestConstants.Learn.SpeedAfterIncreaseText);
3235

36+
await page.Keyboard.PressAsync(BrowserTestConstants.Keyboard.ArrowDown);
37+
await Expect(page.GetByTestId(UiTestIds.Learn.SpeedValue))
38+
.ToHaveTextAsync(BrowserTestConstants.Learn.SpeedAfterDecreaseText);
39+
3340
await UiScenarioArtifacts.CapturePageAsync(
3441
page,
3542
BrowserTestConstants.Learn.ShortcutScenarioName,
3643
BrowserTestConstants.Learn.ShortcutStep);
3744
});
45+
46+
[Test]
47+
public Task LearnPage_KeyboardShortcuts_MoveByWordAndPhraseWithoutPlayback() =>
48+
RunPageAsync(async page =>
49+
{
50+
UiScenarioArtifacts.ResetScenario(BrowserTestConstants.Learn.ShortcutNavigationScenarioName);
51+
52+
await ReaderRouteDriver.OpenLearnAsync(page, BrowserTestConstants.Routes.LearnDemo);
53+
await Expect(page.GetByTestId(UiTestIds.Learn.Page))
54+
.ToBeVisibleAsync(new() { Timeout = BrowserTestConstants.Timing.ExtendedVisibleTimeoutMs });
55+
56+
await page.GetByTestId(UiTestIds.Learn.Page).FocusAsync();
57+
var initialProgress = await ReadProgressStateAsync(page);
58+
59+
await page.Keyboard.PressAsync(BrowserTestConstants.Keyboard.ArrowRight);
60+
var afterForward = await ReadProgressStateAsync(page);
61+
62+
await Assert.That(afterForward.CurrentWordNumber).IsEqualTo(initialProgress.CurrentWordNumber + 1);
63+
await Assert.That(afterForward.TotalWordCount).IsEqualTo(initialProgress.TotalWordCount);
64+
65+
await page.Keyboard.PressAsync(BrowserTestConstants.Keyboard.ArrowLeft);
66+
var afterBackward = await ReadProgressStateAsync(page);
67+
68+
await Assert.That(afterBackward.CurrentWordNumber).IsEqualTo(initialProgress.CurrentWordNumber);
69+
await Assert.That(afterBackward.TotalWordCount).IsEqualTo(initialProgress.TotalWordCount);
70+
71+
await page.Keyboard.PressAsync(BrowserTestConstants.Keyboard.PageDown);
72+
var afterLargeForward = await ReadProgressStateAsync(page);
73+
74+
await Assert.That(afterLargeForward.CurrentWordNumber)
75+
.IsEqualTo(initialProgress.CurrentWordNumber + BrowserTestConstants.Learn.StepForwardLargeWordCount);
76+
await Assert.That(afterLargeForward.TotalWordCount).IsEqualTo(initialProgress.TotalWordCount);
77+
78+
await page.Keyboard.PressAsync(BrowserTestConstants.Keyboard.PageUp);
79+
var afterLargeBackward = await ReadProgressStateAsync(page);
80+
81+
await Assert.That(afterLargeBackward.CurrentWordNumber).IsEqualTo(initialProgress.CurrentWordNumber);
82+
await Assert.That(afterLargeBackward.TotalWordCount).IsEqualTo(initialProgress.TotalWordCount);
83+
84+
await UiScenarioArtifacts.CapturePageAsync(
85+
page,
86+
BrowserTestConstants.Learn.ShortcutNavigationScenarioName,
87+
BrowserTestConstants.Learn.ShortcutNavigationStep);
88+
});
89+
90+
private static async Task<ProgressState> ReadProgressStateAsync(Microsoft.Playwright.IPage page)
91+
{
92+
var progressLabel = await page.GetByTestId(UiTestIds.Learn.ProgressLabel).TextContentAsync() ?? string.Empty;
93+
var match = BrowserTestConstants.Regexes.LearnProgressLabel.Match(progressLabel);
94+
await Assert.That(match.Success).IsTrue().Because($"Expected Learn progress label to match the current progress contract, but found '{progressLabel}'.");
95+
96+
return new ProgressState(
97+
int.Parse(match.Groups["current"].Value, CultureInfo.InvariantCulture),
98+
int.Parse(match.Groups["total"].Value, CultureInfo.InvariantCulture));
99+
}
38100
}

tests/PrompterOne.Web.UITests.Reader/Teleprompter/TeleprompterKeyboardShortcutFlowTests.cs

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,49 @@ await Expect(page.GetByTestId(UiTestIds.Teleprompter.Page))
1818
.ToBeVisibleAsync(new() { Timeout = BrowserTestConstants.Timing.ExtendedVisibleTimeoutMs });
1919

2020
await page.GetByTestId(UiTestIds.Teleprompter.Page).FocusAsync();
21+
await page.Keyboard.PressAsync(BrowserTestConstants.Keyboard.Space);
22+
await Expect(page.GetByTestId(UiTestIds.Teleprompter.PlayToggle))
23+
.ToHaveAttributeAsync(
24+
BrowserTestConstants.State.ActiveAttribute,
25+
BrowserTestConstants.Teleprompter.ActiveStateValue);
26+
await Expect(page.GetByTestId(UiTestIds.Teleprompter.PauseIcon)).ToBeVisibleAsync();
27+
28+
await page.Keyboard.PressAsync(BrowserTestConstants.Keyboard.Space);
29+
await Expect(page.GetByTestId(UiTestIds.Teleprompter.PlayToggle))
30+
.ToHaveAttributeAsync(
31+
BrowserTestConstants.State.ActiveAttribute,
32+
BrowserTestConstants.Teleprompter.InactiveStateValue);
33+
34+
await page.Keyboard.PressAsync(BrowserTestConstants.Keyboard.ArrowRight);
35+
await Expect(page.GetByTestId(UiTestIds.Teleprompter.BlockIndicator))
36+
.ToHaveTextAsync(BrowserTestConstants.Regexes.ReaderSecondBlockIndicator);
37+
38+
await page.Keyboard.PressAsync(BrowserTestConstants.Keyboard.ArrowLeft);
39+
await Expect(page.GetByTestId(UiTestIds.Teleprompter.BlockIndicator))
40+
.ToHaveTextAsync(BrowserTestConstants.Regexes.ReaderFirstBlockIndicator);
41+
42+
await page.Keyboard.PressAsync(BrowserTestConstants.Keyboard.O);
43+
await Expect(page.GetByTestId(UiTestIds.Teleprompter.ClusterWrap))
44+
.ToHaveAttributeAsync(
45+
BrowserTestConstants.TeleprompterFlow.ReaderOrientationAttribute,
46+
BrowserTestConstants.TeleprompterFlow.OrientationPortraitValue);
47+
2148
await page.Keyboard.PressAsync(BrowserTestConstants.Keyboard.H);
2249
await Expect(page.GetByTestId(UiTestIds.Teleprompter.MirrorHorizontalToggle))
2350
.ToHaveAttributeAsync(BrowserTestConstants.State.ActiveAttribute, BrowserTestConstants.Teleprompter.ActiveStateValue);
2451

52+
await page.Keyboard.PressAsync(BrowserTestConstants.Keyboard.V);
53+
await Expect(page.GetByTestId(UiTestIds.Teleprompter.MirrorVerticalToggle))
54+
.ToHaveAttributeAsync(BrowserTestConstants.State.ActiveAttribute, BrowserTestConstants.Teleprompter.ActiveStateValue);
55+
56+
await page.Keyboard.PressAsync(BrowserTestConstants.Keyboard.Digit2);
57+
await Expect(page.GetByTestId(UiTestIds.Teleprompter.AlignmentCenter))
58+
.ToHaveAttributeAsync(BrowserTestConstants.State.ActiveAttribute, BrowserTestConstants.Teleprompter.ActiveStateValue);
59+
60+
await page.Keyboard.PressAsync(BrowserTestConstants.Keyboard.Digit3);
61+
await Expect(page.GetByTestId(UiTestIds.Teleprompter.AlignmentRight))
62+
.ToHaveAttributeAsync(BrowserTestConstants.State.ActiveAttribute, BrowserTestConstants.Teleprompter.ActiveStateValue);
63+
2564
await page.Keyboard.PressAsync(BrowserTestConstants.Keyboard.Digit4);
2665
await Expect(page.GetByTestId(UiTestIds.Teleprompter.AlignmentJustify))
2766
.ToHaveAttributeAsync(BrowserTestConstants.State.ActiveAttribute, BrowserTestConstants.Teleprompter.ActiveStateValue);
@@ -35,4 +74,34 @@ await UiScenarioArtifacts.CapturePageAsync(
3574
BrowserTestConstants.Teleprompter.ShortcutScenarioName,
3675
BrowserTestConstants.Teleprompter.ShortcutStep);
3776
});
77+
78+
[Test]
79+
public Task TeleprompterPage_KeyboardShortcuts_KeepRangeInputFocusFromTriggeringPageShortcuts() =>
80+
RunPageAsync(async page =>
81+
{
82+
UiScenarioArtifacts.ResetScenario(BrowserTestConstants.Teleprompter.ShortcutInputFocusScenarioName);
83+
84+
await ReaderRouteDriver.OpenTeleprompterAsync(page, BrowserTestConstants.Routes.TeleprompterDemo);
85+
await Expect(page.GetByTestId(UiTestIds.Teleprompter.Page))
86+
.ToBeVisibleAsync(new() { Timeout = BrowserTestConstants.Timing.ExtendedVisibleTimeoutMs });
87+
await Expect(page.GetByTestId(UiTestIds.Teleprompter.BlockIndicator))
88+
.ToHaveTextAsync(BrowserTestConstants.Regexes.ReaderFirstBlockIndicator);
89+
90+
await page.GetByTestId(UiTestIds.Teleprompter.WidthSlider).FocusAsync();
91+
await page.Keyboard.PressAsync(BrowserTestConstants.Keyboard.PageDown);
92+
93+
await Expect(page.GetByTestId(UiTestIds.Teleprompter.BlockIndicator))
94+
.ToHaveTextAsync(BrowserTestConstants.Regexes.ReaderFirstBlockIndicator);
95+
96+
await page.Keyboard.PressAsync(BrowserTestConstants.Keyboard.O);
97+
await Expect(page.GetByTestId(UiTestIds.Teleprompter.ClusterWrap))
98+
.ToHaveAttributeAsync(
99+
BrowserTestConstants.TeleprompterFlow.ReaderOrientationAttribute,
100+
BrowserTestConstants.TeleprompterFlow.OrientationLandscapeValue);
101+
102+
await UiScenarioArtifacts.CapturePageAsync(
103+
page,
104+
BrowserTestConstants.Teleprompter.ShortcutInputFocusScenarioName,
105+
BrowserTestConstants.Teleprompter.ShortcutInputFocusStep);
106+
});
38107
}

tests/PrompterOne.Web.UITests/Support/BrowserTestConstants.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,10 @@ public static class Learn
139139
public const int StepForwardLargeWordCount = 5;
140140
public const string ShortcutScenarioName = "learn-keyboard-shortcuts";
141141
public const string ShortcutStep = "01-loop-and-speed";
142+
public const string ShortcutNavigationScenarioName = "learn-keyboard-navigation-shortcuts";
143+
public const string ShortcutNavigationStep = "01-word-navigation";
142144
public const string LoopPressedValue = "true";
145+
public const string SpeedAfterDecreaseText = "250";
143146
public const string SpeedAfterIncreaseText = "260";
144147
}
145148

@@ -161,6 +164,8 @@ public static class Teleprompter
161164
public const string PauseToggleIconSelector = $"[{Html.DataTestAttribute}='{UiTestIds.Teleprompter.PauseIcon}']";
162165
public const string ShortcutScenarioName = "teleprompter-keyboard-shortcuts";
163166
public const string ShortcutStep = "01-mirror-and-justify";
167+
public const string ShortcutInputFocusScenarioName = "teleprompter-keyboard-input-focus";
168+
public const string ShortcutInputFocusStep = "01-slider-focus-contained";
164169
}
165170

166171
public static class RapidInput
@@ -986,13 +991,16 @@ public static class Keyboard
986991
public const string PageDown = "PageDown";
987992
public const string PageUp = "PageUp";
988993
public const string Digit2 = "2";
994+
public const string Digit3 = "3";
989995
public const string Digit4 = "4";
990996
public const string Enter = "Enter";
991997
public const string F = "f";
992998
public const string H = "h";
993999
public const string L = "l";
1000+
public const string O = "o";
9941001
public const string R = "r";
9951002
public const string Space = "Space";
1003+
public const string V = "v";
9961004
public const string SelectAll = "ControlOrMeta+A";
9971005
public const string OpenAssistant = "ControlOrMeta+K";
9981006
public const string Backspace = "Backspace";

0 commit comments

Comments
 (0)