@fluentui-react-native/tester 0.101.5 → 0.101.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/CHANGELOG.json +169 -1
  2. package/CHANGELOG.md +41 -2
  3. package/lib/E2E/FocusZone/pages/FocusZonePageObject.d.ts +37 -0
  4. package/lib/E2E/FocusZone/pages/FocusZonePageObject.d.ts.map +1 -1
  5. package/lib/E2E/FocusZone/pages/FocusZonePageObject.js +197 -4
  6. package/lib/E2E/FocusZone/pages/FocusZonePageObject.js.map +1 -1
  7. package/lib/E2E/FocusZone/specs/FocusZone.spec.win.js +457 -0
  8. package/lib/E2E/FocusZone/specs/FocusZone.spec.win.js.map +1 -1
  9. package/lib/E2E/common/BasePage.d.ts +2 -0
  10. package/lib/E2E/common/BasePage.d.ts.map +1 -1
  11. package/lib/E2E/common/BasePage.js +34 -14
  12. package/lib/E2E/common/BasePage.js.map +1 -1
  13. package/lib/E2E/common/consts.d.ts +15 -0
  14. package/lib/E2E/common/consts.d.ts.map +1 -1
  15. package/lib/TestComponents/Common/MenuPicker.d.ts +2 -0
  16. package/lib/TestComponents/Common/MenuPicker.d.ts.map +1 -1
  17. package/lib/TestComponents/Common/MenuPicker.js +2 -2
  18. package/lib/TestComponents/Common/MenuPicker.js.map +1 -1
  19. package/lib/TestComponents/FocusZone/FocusZoneE2ETest.d.ts +20 -0
  20. package/lib/TestComponents/FocusZone/FocusZoneE2ETest.d.ts.map +1 -0
  21. package/lib/TestComponents/FocusZone/FocusZoneE2ETest.js +51 -0
  22. package/lib/TestComponents/FocusZone/FocusZoneE2ETest.js.map +1 -0
  23. package/lib/TestComponents/FocusZone/FocusZoneTest.d.ts.map +1 -1
  24. package/lib/TestComponents/FocusZone/FocusZoneTest.js +26 -70
  25. package/lib/TestComponents/FocusZone/FocusZoneTest.js.map +1 -1
  26. package/lib/TestComponents/FocusZone/consts.d.ts +10 -0
  27. package/lib/TestComponents/FocusZone/consts.d.ts.map +1 -1
  28. package/lib/TestComponents/FocusZone/consts.js +11 -0
  29. package/lib/TestComponents/FocusZone/consts.js.map +1 -1
  30. package/lib/TestComponents/FocusZone/styles.d.ts +5 -0
  31. package/lib/TestComponents/FocusZone/styles.d.ts.map +1 -1
  32. package/lib/TestComponents/FocusZone/styles.js +5 -0
  33. package/lib/TestComponents/FocusZone/styles.js.map +1 -1
  34. package/lib-commonjs/E2E/FocusZone/pages/FocusZonePageObject.d.ts +37 -0
  35. package/lib-commonjs/E2E/FocusZone/pages/FocusZonePageObject.d.ts.map +1 -1
  36. package/lib-commonjs/E2E/FocusZone/pages/FocusZonePageObject.js +196 -3
  37. package/lib-commonjs/E2E/FocusZone/pages/FocusZonePageObject.js.map +1 -1
  38. package/lib-commonjs/E2E/FocusZone/specs/FocusZone.spec.win.js +457 -0
  39. package/lib-commonjs/E2E/FocusZone/specs/FocusZone.spec.win.js.map +1 -1
  40. package/lib-commonjs/E2E/common/BasePage.d.ts +2 -0
  41. package/lib-commonjs/E2E/common/BasePage.d.ts.map +1 -1
  42. package/lib-commonjs/E2E/common/BasePage.js +34 -14
  43. package/lib-commonjs/E2E/common/BasePage.js.map +1 -1
  44. package/lib-commonjs/E2E/common/consts.d.ts +15 -0
  45. package/lib-commonjs/E2E/common/consts.d.ts.map +1 -1
  46. package/lib-commonjs/TestComponents/Common/MenuPicker.d.ts +2 -0
  47. package/lib-commonjs/TestComponents/Common/MenuPicker.d.ts.map +1 -1
  48. package/lib-commonjs/TestComponents/Common/MenuPicker.js +2 -2
  49. package/lib-commonjs/TestComponents/Common/MenuPicker.js.map +1 -1
  50. package/lib-commonjs/TestComponents/FocusZone/FocusZoneE2ETest.d.ts +20 -0
  51. package/lib-commonjs/TestComponents/FocusZone/FocusZoneE2ETest.d.ts.map +1 -0
  52. package/lib-commonjs/TestComponents/FocusZone/FocusZoneE2ETest.js +57 -0
  53. package/lib-commonjs/TestComponents/FocusZone/FocusZoneE2ETest.js.map +1 -0
  54. package/lib-commonjs/TestComponents/FocusZone/FocusZoneTest.d.ts.map +1 -1
  55. package/lib-commonjs/TestComponents/FocusZone/FocusZoneTest.js +27 -71
  56. package/lib-commonjs/TestComponents/FocusZone/FocusZoneTest.js.map +1 -1
  57. package/lib-commonjs/TestComponents/FocusZone/consts.d.ts +10 -0
  58. package/lib-commonjs/TestComponents/FocusZone/consts.d.ts.map +1 -1
  59. package/lib-commonjs/TestComponents/FocusZone/consts.js +14 -1
  60. package/lib-commonjs/TestComponents/FocusZone/consts.js.map +1 -1
  61. package/lib-commonjs/TestComponents/FocusZone/styles.d.ts +5 -0
  62. package/lib-commonjs/TestComponents/FocusZone/styles.d.ts.map +1 -1
  63. package/lib-commonjs/TestComponents/FocusZone/styles.js +5 -0
  64. package/lib-commonjs/TestComponents/FocusZone/styles.js.map +1 -1
  65. package/package.json +25 -25
  66. package/src/E2E/FocusZone/pages/FocusZonePageObject.ts +135 -4
  67. package/src/E2E/FocusZone/specs/FocusZone.spec.win.ts +177 -2
  68. package/src/E2E/common/BasePage.ts +8 -3
  69. package/src/E2E/common/consts.ts +17 -0
  70. package/src/TestComponents/Common/MenuPicker.tsx +5 -2
  71. package/src/TestComponents/FocusZone/FocusZoneE2ETest.tsx +126 -0
  72. package/src/TestComponents/FocusZone/FocusZoneTest.tsx +40 -127
  73. package/src/TestComponents/FocusZone/consts.ts +17 -0
  74. package/src/TestComponents/FocusZone/styles.ts +5 -0
@@ -1,12 +1,115 @@
1
- import { FOCUSZONE_TESTPAGE, FOCUSZONE_TEST_COMPONENT, HOMEPAGE_FOCUSZONE_BUTTON } from '../../../TestComponents/FocusZone/consts';
1
+ import { FocusZoneDirection } from '@fluentui/react-native';
2
+ import { Attribute, AttributeValue, Keys } from '../../common/consts';
3
+ import {
4
+ FOCUSZONE_CIRCLE_NAV_SWITCH,
5
+ FOCUSZONE_DEFAULT_TABBABLE_SWITCH,
6
+ FOCUSZONE_DIRECTION_ID,
7
+ FOCUSZONE_DIRECTION_PICKER,
8
+ FOCUSZONE_DISABLED_SWITCH,
9
+ FOCUSZONE_GRID_AFTER,
10
+ FOCUSZONE_GRID_BEFORE,
11
+ FOCUSZONE_GRID_BUTTON,
12
+ FOCUSZONE_TESTPAGE,
13
+ FOCUSZONE_TEST_COMPONENT,
14
+ FOCUSZONE_TWO_DIM_SWITCH,
15
+ HOMEPAGE_FOCUSZONE_BUTTON,
16
+ } from '../../../TestComponents/FocusZone/consts';
2
17
  import { BasePage, By } from '../../common/BasePage';
3
18
 
19
+ export const enum GridFocusZoneOption {
20
+ SetDirection = 0,
21
+ Set2DNavigation,
22
+ SetCircularNavigation,
23
+ UseDefaultTabbableElement,
24
+ Disable,
25
+ }
26
+
27
+ export const enum GridButtonSelector {
28
+ Before = 0,
29
+ One,
30
+ Two,
31
+ Three,
32
+ Four,
33
+ Five,
34
+ Six,
35
+ Seven,
36
+ Eight,
37
+ Nine,
38
+ After,
39
+ }
40
+
41
+ type BooleanGridFocusZoneOption =
42
+ | GridFocusZoneOption.UseDefaultTabbableElement
43
+ | GridFocusZoneOption.Set2DNavigation
44
+ | GridFocusZoneOption.SetCircularNavigation
45
+ | GridFocusZoneOption.Disable;
46
+
4
47
  class FocusZonePageObject extends BasePage {
5
- // OVERRIDE: We use isExisting() here instead of isDisplayed() because FocusZone does not have any UI to it, it's simply
6
- // a wrapper that adds keyboard focus functionality
7
48
  async waitForPrimaryElementDisplayed(timeout?: number): Promise<void> {
8
49
  const errorMsg = 'The FocusZone UI Element did not load correctly. Please see logs.';
9
- await this.waitForCondition(async () => await this._primaryComponent.isExisting(), errorMsg, timeout);
50
+ await this.waitForCondition(async () => await this._primaryComponent.isDisplayed(), errorMsg, timeout);
51
+ }
52
+
53
+ async resetTest() {
54
+ await this.configureGridFocusZone(GridFocusZoneOption.SetDirection, 'bidirectional');
55
+ await this.configureGridFocusZone(GridFocusZoneOption.Set2DNavigation, false);
56
+ await this.configureGridFocusZone(GridFocusZoneOption.SetCircularNavigation, false);
57
+ await this.configureGridFocusZone(GridFocusZoneOption.Disable, false);
58
+ }
59
+
60
+ async configureGridFocusZone(option: GridFocusZoneOption.SetDirection, direction: FocusZoneDirection);
61
+ async configureGridFocusZone(option: BooleanGridFocusZoneOption, value: boolean);
62
+ async configureGridFocusZone(option: GridFocusZoneOption, arg: any): Promise<void> {
63
+ let switchElement: WebdriverIO.Element;
64
+ switch (option) {
65
+ case GridFocusZoneOption.SetDirection:
66
+ await (await this._directionPicker).click();
67
+ await browser.waitUntil(async () => await (await this._getGridFocusZoneMenuOption(arg)).isDisplayed());
68
+ await (await this._getGridFocusZoneMenuOption(arg)).click();
69
+ return;
70
+ case GridFocusZoneOption.Set2DNavigation:
71
+ switchElement = await this._twoDimSwitch;
72
+ break;
73
+ case GridFocusZoneOption.SetCircularNavigation:
74
+ switchElement = await this._circleNavSwitch;
75
+ break;
76
+ case GridFocusZoneOption.UseDefaultTabbableElement:
77
+ switchElement = await this._defaultTabbableElementSwitch;
78
+ break;
79
+ case GridFocusZoneOption.Disable:
80
+ switchElement = await this._disabledSwitch;
81
+ break;
82
+ default:
83
+ }
84
+ const switchValue = await switchElement.isSelected();
85
+ if (switchValue !== arg) {
86
+ await switchElement.click();
87
+ }
88
+ }
89
+
90
+ async sendKeys(selector: GridButtonSelector, keys: Keys[]): Promise<void> {
91
+ const btn = await this._getGridButton(selector);
92
+ await btn.addValue(keys);
93
+ }
94
+
95
+ async gridButtonIsFocused(selector: GridButtonSelector): Promise<boolean> {
96
+ const btn = await this._getGridButton(selector);
97
+ return (await this.getElementAttribute(btn, Attribute.IsFocused)) === AttributeValue.true;
98
+ }
99
+
100
+ private async _getGridButton(selector: GridButtonSelector): Promise<WebdriverIO.Element> {
101
+ switch (selector) {
102
+ case GridButtonSelector.Before:
103
+ return await this._gridBeforeButton;
104
+ case GridButtonSelector.After:
105
+ return await this._gridAfterButton;
106
+ default:
107
+ return await By(FOCUSZONE_GRID_BUTTON(selector));
108
+ }
109
+ }
110
+
111
+ private async _getGridFocusZoneMenuOption(direction: FocusZoneDirection) {
112
+ return await By(FOCUSZONE_DIRECTION_ID(direction));
10
113
  }
11
114
 
12
115
  /*****************************************/
@@ -27,6 +130,34 @@ class FocusZonePageObject extends BasePage {
27
130
  get _pageButton() {
28
131
  return By(HOMEPAGE_FOCUSZONE_BUTTON);
29
132
  }
133
+
134
+ get _directionPicker() {
135
+ return By(FOCUSZONE_DIRECTION_PICKER);
136
+ }
137
+
138
+ get _twoDimSwitch() {
139
+ return By(FOCUSZONE_TWO_DIM_SWITCH);
140
+ }
141
+
142
+ get _disabledSwitch() {
143
+ return By(FOCUSZONE_DISABLED_SWITCH);
144
+ }
145
+
146
+ get _circleNavSwitch() {
147
+ return By(FOCUSZONE_CIRCLE_NAV_SWITCH);
148
+ }
149
+
150
+ get _defaultTabbableElementSwitch() {
151
+ return By(FOCUSZONE_DEFAULT_TABBABLE_SWITCH);
152
+ }
153
+
154
+ get _gridBeforeButton() {
155
+ return By(FOCUSZONE_GRID_BEFORE);
156
+ }
157
+
158
+ get _gridAfterButton() {
159
+ return By(FOCUSZONE_GRID_AFTER);
160
+ }
30
161
  }
31
162
 
32
163
  export default new FocusZonePageObject();
@@ -1,6 +1,6 @@
1
1
  import NavigateAppPage from '../../common/NavigateAppPage';
2
- import FocusZonePageObject from '../pages/FocusZonePageObject';
3
- import { PAGE_TIMEOUT, BOOT_APP_TIMEOUT } from '../../common/consts';
2
+ import FocusZonePageObject, { GridButtonSelector, GridFocusZoneOption } from '../pages/FocusZonePageObject';
3
+ import { PAGE_TIMEOUT, BOOT_APP_TIMEOUT, Keys } from '../../common/consts';
4
4
  import { Platform } from '../../common/BasePage';
5
5
 
6
6
  // Before testing begins, allow up to 60 seconds for app to open
@@ -23,3 +23,178 @@ describe('FocusZone Testing Initialization', function () {
23
23
  await expect(await FocusZonePageObject.didAssertPopup()).toBeFalsy(FocusZonePageObject.ERRORMESSAGE_ASSERT); // Ensure no asserts popped up
24
24
  });
25
25
  });
26
+
27
+ /* FocusZone Functional Testing
28
+ *
29
+ * This test validates that keyboard navigation using both arrow keys and
30
+ * tab key works, even when modifying how the FocusZone functions.
31
+ *
32
+ * */
33
+ describe('FocusZone Functional Testing', () => {
34
+ beforeEach(async () => {
35
+ await FocusZonePageObject.scrollToTestElement();
36
+ await FocusZonePageObject.waitForPrimaryElementDisplayed(PAGE_TIMEOUT);
37
+ await FocusZonePageObject.resetTest();
38
+ });
39
+
40
+ it('Navigate bidirectional focuszone by arrow keys - switches focus correctly', async () => {
41
+ // move to 2 with right arrow
42
+ await FocusZonePageObject.sendKeys(GridButtonSelector.One, [Keys.ARROW_RIGHT]);
43
+ await expect(await FocusZonePageObject.gridButtonIsFocused(GridButtonSelector.Two)).toBeTruthy();
44
+
45
+ // move to 3 with down arrow
46
+ await FocusZonePageObject.sendKeys(GridButtonSelector.Two, [Keys.ARROW_DOWN]);
47
+ await expect(await FocusZonePageObject.gridButtonIsFocused(GridButtonSelector.Three)).toBeTruthy();
48
+
49
+ await expect(await FocusZonePageObject.didAssertPopup()).toBeFalsy(FocusZonePageObject.ERRORMESSAGE_ASSERT);
50
+ });
51
+
52
+ it('Navigate horizontal focuszone by arrow keys - switches focus correctly', async () => {
53
+ await FocusZonePageObject.configureGridFocusZone(GridFocusZoneOption.SetDirection, 'horizontal');
54
+ // move to 2 with right arrow
55
+ await FocusZonePageObject.sendKeys(GridButtonSelector.One, [Keys.ARROW_RIGHT]);
56
+ await expect(await FocusZonePageObject.gridButtonIsFocused(GridButtonSelector.Two)).toBeTruthy();
57
+
58
+ // down arrow shouldn't move focus
59
+ await FocusZonePageObject.sendKeys(GridButtonSelector.Two, [Keys.ARROW_DOWN]);
60
+ await expect(await FocusZonePageObject.gridButtonIsFocused(GridButtonSelector.Two)).toBeTruthy();
61
+
62
+ // left arrow goes back
63
+ await FocusZonePageObject.sendKeys(GridButtonSelector.Four, [Keys.ARROW_LEFT]);
64
+ await expect(await FocusZonePageObject.gridButtonIsFocused(GridButtonSelector.Three)).toBeTruthy();
65
+
66
+ await expect(await FocusZonePageObject.didAssertPopup()).toBeFalsy(FocusZonePageObject.ERRORMESSAGE_ASSERT);
67
+ });
68
+
69
+ it('Navigates vertical focuszone by arrow keys - switches focus correctly', async () => {
70
+ await FocusZonePageObject.configureGridFocusZone(GridFocusZoneOption.SetDirection, 'vertical');
71
+
72
+ // move to 2 with down arrow
73
+ await FocusZonePageObject.sendKeys(GridButtonSelector.One, [Keys.ARROW_DOWN]);
74
+ await expect(await FocusZonePageObject.gridButtonIsFocused(GridButtonSelector.Two)).toBeTruthy();
75
+
76
+ // right arrow shouldn't move focus
77
+ await FocusZonePageObject.sendKeys(GridButtonSelector.Two, [Keys.ARROW_RIGHT]);
78
+ await expect(await FocusZonePageObject.gridButtonIsFocused(GridButtonSelector.Two)).toBeTruthy();
79
+
80
+ // up arrow goes back
81
+ await FocusZonePageObject.sendKeys(GridButtonSelector.Four, [Keys.ARROW_UP]);
82
+ await expect(await FocusZonePageObject.gridButtonIsFocused(GridButtonSelector.Three)).toBeTruthy();
83
+
84
+ await expect(await FocusZonePageObject.didAssertPopup()).toBeFalsy(FocusZonePageObject.ERRORMESSAGE_ASSERT);
85
+ });
86
+
87
+ it("Navigates none-direction focuszone by arrow keys - doesn't switch focus", async () => {
88
+ await FocusZonePageObject.configureGridFocusZone(GridFocusZoneOption.SetDirection, 'none');
89
+
90
+ // none of these key commands should move
91
+ await FocusZonePageObject.sendKeys(GridButtonSelector.Two, [Keys.ARROW_DOWN]);
92
+ await expect(await FocusZonePageObject.gridButtonIsFocused(GridButtonSelector.Two)).toBeTruthy();
93
+
94
+ await FocusZonePageObject.sendKeys(GridButtonSelector.Two, [Keys.ARROW_UP]);
95
+ await expect(await FocusZonePageObject.gridButtonIsFocused(GridButtonSelector.Two)).toBeTruthy();
96
+
97
+ await FocusZonePageObject.sendKeys(GridButtonSelector.Two, [Keys.ARROW_LEFT]);
98
+ await expect(await FocusZonePageObject.gridButtonIsFocused(GridButtonSelector.Two)).toBeTruthy();
99
+
100
+ await FocusZonePageObject.sendKeys(GridButtonSelector.Two, [Keys.ARROW_RIGHT]);
101
+ await expect(await FocusZonePageObject.gridButtonIsFocused(GridButtonSelector.Two)).toBeTruthy();
102
+
103
+ await expect(await FocusZonePageObject.didAssertPopup()).toBeFalsy(FocusZonePageObject.ERRORMESSAGE_ASSERT);
104
+ });
105
+
106
+ it('Navigates bi-directional focuszone with 2d navigation - switches focus correctly', async () => {
107
+ await FocusZonePageObject.configureGridFocusZone(GridFocusZoneOption.Set2DNavigation, true);
108
+
109
+ await FocusZonePageObject.sendKeys(GridButtonSelector.One, [Keys.ARROW_DOWN]);
110
+ await expect(await FocusZonePageObject.gridButtonIsFocused(GridButtonSelector.Four)).toBeTruthy();
111
+
112
+ await FocusZonePageObject.sendKeys(GridButtonSelector.Four, [Keys.ARROW_RIGHT]);
113
+ await expect(await FocusZonePageObject.gridButtonIsFocused(GridButtonSelector.Five)).toBeTruthy();
114
+
115
+ await expect(await FocusZonePageObject.didAssertPopup()).toBeFalsy(FocusZonePageObject.ERRORMESSAGE_ASSERT);
116
+ });
117
+
118
+ it("Navigates focuszone with circular navigation off - doesn't switch focus", async () => {
119
+ await FocusZonePageObject.sendKeys(GridButtonSelector.One, [Keys.ARROW_LEFT]);
120
+ await expect(await FocusZonePageObject.gridButtonIsFocused(GridButtonSelector.One)).toBeTruthy();
121
+
122
+ await FocusZonePageObject.sendKeys(GridButtonSelector.Nine, [Keys.ARROW_RIGHT]);
123
+ await expect(await FocusZonePageObject.gridButtonIsFocused(GridButtonSelector.Nine)).toBeTruthy();
124
+
125
+ await expect(await FocusZonePageObject.didAssertPopup()).toBeFalsy(FocusZonePageObject.ERRORMESSAGE_ASSERT);
126
+ });
127
+
128
+ it('Navigates focuszone with circular navigation on - switches focus correctly', async () => {
129
+ await FocusZonePageObject.configureGridFocusZone(GridFocusZoneOption.SetCircularNavigation, true);
130
+
131
+ await FocusZonePageObject.sendKeys(GridButtonSelector.One, [Keys.ARROW_LEFT]);
132
+ await expect(await FocusZonePageObject.gridButtonIsFocused(GridButtonSelector.Nine)).toBeTruthy();
133
+
134
+ await FocusZonePageObject.sendKeys(GridButtonSelector.Nine, [Keys.ARROW_RIGHT]);
135
+ await expect(await FocusZonePageObject.gridButtonIsFocused(GridButtonSelector.One)).toBeTruthy();
136
+
137
+ await expect(await FocusZonePageObject.didAssertPopup()).toBeFalsy(FocusZonePageObject.ERRORMESSAGE_ASSERT);
138
+ });
139
+
140
+ it("Navigates disabled focuszone by arrow keys - doesn't switch focus", async () => {
141
+ await FocusZonePageObject.configureGridFocusZone(GridFocusZoneOption.Disable, true);
142
+
143
+ // none of these key commands should move
144
+ await FocusZonePageObject.sendKeys(GridButtonSelector.Two, [Keys.ARROW_DOWN]);
145
+ await expect(await FocusZonePageObject.gridButtonIsFocused(GridButtonSelector.Two)).toBeTruthy();
146
+
147
+ await FocusZonePageObject.sendKeys(GridButtonSelector.Two, [Keys.ARROW_UP]);
148
+ await expect(await FocusZonePageObject.gridButtonIsFocused(GridButtonSelector.Two)).toBeTruthy();
149
+
150
+ await FocusZonePageObject.sendKeys(GridButtonSelector.Two, [Keys.ARROW_LEFT]);
151
+ await expect(await FocusZonePageObject.gridButtonIsFocused(GridButtonSelector.Two)).toBeTruthy();
152
+
153
+ await FocusZonePageObject.sendKeys(GridButtonSelector.Two, [Keys.ARROW_RIGHT]);
154
+ await expect(await FocusZonePageObject.gridButtonIsFocused(GridButtonSelector.Two)).toBeTruthy();
155
+
156
+ await expect(await FocusZonePageObject.didAssertPopup()).toBeFalsy(FocusZonePageObject.ERRORMESSAGE_ASSERT);
157
+ });
158
+
159
+ it('Tabs in and out of the FocusZone - switches focus correctly', async () => {
160
+ await FocusZonePageObject.sendKeys(GridButtonSelector.Before, [Keys.TAB]);
161
+ await expect(await FocusZonePageObject.gridButtonIsFocused(GridButtonSelector.One)).toBeTruthy();
162
+
163
+ await FocusZonePageObject.sendKeys(GridButtonSelector.One, [Keys.TAB]);
164
+ await expect(await FocusZonePageObject.gridButtonIsFocused(GridButtonSelector.After)).toBeTruthy();
165
+
166
+ await FocusZonePageObject.sendKeys(GridButtonSelector.After, [Keys.SHIFT, Keys.TAB]);
167
+ await expect(await FocusZonePageObject.gridButtonIsFocused(GridButtonSelector.Nine)).toBeTruthy();
168
+
169
+ await FocusZonePageObject.sendKeys(GridButtonSelector.Nine, [Keys.SHIFT, Keys.TAB]);
170
+ await expect(await FocusZonePageObject.gridButtonIsFocused(GridButtonSelector.Before)).toBeTruthy();
171
+
172
+ await expect(await FocusZonePageObject.didAssertPopup()).toBeFalsy(FocusZonePageObject.ERRORMESSAGE_ASSERT);
173
+ });
174
+
175
+ it('Tabs in and out of the FocusZone with a defaultTabbableElement set - switches focus correctly', async () => {
176
+ // This sets the defaultTabbableElement prop of the FocusZone to be grid button #4. Whenever a user tabs into the zone, button 4 should always be the first to be selected.
177
+ await FocusZonePageObject.configureGridFocusZone(GridFocusZoneOption.UseDefaultTabbableElement, true);
178
+
179
+ await FocusZonePageObject.sendKeys(GridButtonSelector.Before, [Keys.TAB]);
180
+ await expect(await FocusZonePageObject.gridButtonIsFocused(GridButtonSelector.Four)).toBeTruthy();
181
+
182
+ await FocusZonePageObject.sendKeys(GridButtonSelector.Four, [Keys.TAB]);
183
+ await expect(await FocusZonePageObject.gridButtonIsFocused(GridButtonSelector.After)).toBeTruthy();
184
+
185
+ await FocusZonePageObject.sendKeys(GridButtonSelector.After, [Keys.SHIFT, Keys.TAB]);
186
+ await expect(await FocusZonePageObject.gridButtonIsFocused(GridButtonSelector.Four)).toBeTruthy();
187
+
188
+ // Key to another button, tab out, and tab back in to make sure the default tabbable element is still the first to be tabbed to
189
+ await FocusZonePageObject.sendKeys(GridButtonSelector.Four, [Keys.ARROW_RIGHT]);
190
+ await expect(await FocusZonePageObject.gridButtonIsFocused(GridButtonSelector.Five)).toBeTruthy();
191
+
192
+ await FocusZonePageObject.sendKeys(GridButtonSelector.Five, [Keys.SHIFT, Keys.TAB]);
193
+ await expect(await FocusZonePageObject.gridButtonIsFocused(GridButtonSelector.Before)).toBeTruthy();
194
+
195
+ await FocusZonePageObject.sendKeys(GridButtonSelector.Before, [Keys.TAB]);
196
+ await expect(await FocusZonePageObject.gridButtonIsFocused(GridButtonSelector.Four)).toBeTruthy();
197
+
198
+ await expect(await FocusZonePageObject.didAssertPopup()).toBeFalsy(FocusZonePageObject.ERRORMESSAGE_ASSERT);
199
+ });
200
+ });
@@ -1,5 +1,6 @@
1
1
  import { Keys } from './consts';
2
2
  import { TESTPAGE_BUTTONS_SCROLLVIEWER } from '../../TestComponents/Common/consts';
3
+ import { Attribute } from './consts';
3
4
 
4
5
  const DUMMY_CHAR = '';
5
6
  export const COMPONENT_SCROLL_COORDINATES = { x: -0, y: -100 }; // These are the offsets. Y is negative because we want the touch to move up (and thus it scrolls down)
@@ -36,17 +37,17 @@ export class BasePage {
36
37
  /**************** UI Element Interaction Methods ******************/
37
38
  /******************************************************************/
38
39
  async getAccessibilityRole(): Promise<string> {
39
- return await this._primaryComponent.getAttribute('ControlType');
40
+ return await this.getElementAttribute(await this._primaryComponent, Attribute.AccessibilityRole);
40
41
  }
41
42
 
42
43
  /* Gets the accessibility label of an UI element given the selector */
43
44
  async getAccessibilityLabel(componentSelector: ComponentSelector): Promise<string> {
44
45
  switch (componentSelector) {
45
46
  case ComponentSelector.Primary:
46
- return await this._primaryComponent.getAttribute('Name');
47
+ return await this.getElementAttribute(await this._primaryComponent, Attribute.AccessibilityLabel);
47
48
 
48
49
  case ComponentSelector.Secondary:
49
- return await this._secondaryComponent.getAttribute('Name');
50
+ return await this.getElementAttribute(await this._secondaryComponent, Attribute.AccessibilityLabel);
50
51
  }
51
52
  }
52
53
 
@@ -66,6 +67,10 @@ export class BasePage {
66
67
  await this._primaryComponent.click();
67
68
  }
68
69
 
70
+ async getElementAttribute(element: WebdriverIO.Element, attribute: Attribute) {
71
+ return await element.getAttribute(attribute);
72
+ }
73
+
69
74
  /* Scrolls until the desired test page's button is displayed. We use the scroll viewer UI element as the point to start scrolling.
70
75
  * We use a negative number as the Y-coordinate because that enables us to scroll downwards */
71
76
  async scrollToComponentButton(platform: Platform): Promise<void> {
@@ -16,6 +16,23 @@ export const TEXT_A11Y_ROLE = 'ControlType.Text';
16
16
  export const BOOT_APP_TIMEOUT = 60000;
17
17
  export const PAGE_TIMEOUT = 15000;
18
18
 
19
+ export const enum Attribute {
20
+ AccessibilityLabel = 'Name',
21
+ AccessibilityRole = 'ControlType',
22
+ IsEnabled = 'IsEnabled',
23
+ IsFocused = 'HasKeyboardFocus',
24
+ IsRequiredForForm = 'IsRequiredForForm',
25
+ IsTogglePatternAvailable = 'IsTogglePatternAvailable',
26
+ ToggleState = 'Toggle.ToggleState',
27
+ }
28
+
29
+ export const enum AttributeValue {
30
+ on = '1',
31
+ off = '0',
32
+ true = 'True',
33
+ false = 'False',
34
+ }
35
+
19
36
  /* Keyboard Key Constants */
20
37
  export const enum Keys {
21
38
  NULL = '\uE000',
@@ -9,6 +9,7 @@ import { Picker } from '@react-native-picker/picker';
9
9
  export interface CollectionItem<T = string> {
10
10
  label: string;
11
11
  value?: T;
12
+ testID?: string;
12
13
  }
13
14
 
14
15
  export interface MenuPickerProps {
@@ -17,10 +18,11 @@ export interface MenuPickerProps {
17
18
  onChange?: (value: any, index?: number) => void;
18
19
  collection?: CollectionItem[];
19
20
  style?: any;
21
+ testID?: string;
20
22
  }
21
23
 
22
24
  export const MenuPicker: React.FunctionComponent<MenuPickerProps> = (props: MenuPickerProps) => {
23
- const { prompt, selected, onChange, collection, style } = props;
25
+ const { prompt, selected, onChange, collection, style, testID } = props;
24
26
  let selectedItemKey;
25
27
 
26
28
  collection.forEach((item) => {
@@ -31,13 +33,14 @@ export const MenuPicker: React.FunctionComponent<MenuPickerProps> = (props: Menu
31
33
 
32
34
  return (
33
35
  <Picker
36
+ testID={testID}
34
37
  prompt={prompt}
35
38
  selectedValue={selectedItemKey}
36
39
  onValueChange={(value: string, index: number) => onChange(value, index)}
37
40
  style={{ ...style }}
38
41
  >
39
42
  {collection.map((item, index) => (
40
- <Picker.Item label={item.label} key={index} value={item.value} />
43
+ <Picker.Item label={item.label} key={index} value={item.value} testID={item.testID} />
41
44
  ))}
42
45
  </Picker>
43
46
  );
@@ -0,0 +1,126 @@
1
+ import React from 'react';
2
+ import { View } from 'react-native';
3
+ import { FocusZoneDirection, FocusZone, MenuButton, Text } from '@fluentui/react-native';
4
+ import { Switch } from '@fluentui-react-native/switch';
5
+ import { ButtonV1 as Button, ButtonProps } from '@fluentui-react-native/button';
6
+ import { commonTestStyles } from '../Common/styles';
7
+ import {
8
+ FOCUSZONE_TEST_COMPONENT,
9
+ FOCUSZONE_DIRECTION_ID,
10
+ FOCUSZONE_TWO_DIM_SWITCH,
11
+ FOCUSZONE_DISABLED_SWITCH,
12
+ FOCUSZONE_CIRCLE_NAV_SWITCH,
13
+ FOCUSZONE_DEFAULT_TABBABLE_SWITCH,
14
+ FOCUSZONE_GRID_BEFORE,
15
+ FOCUSZONE_GRID_AFTER,
16
+ FOCUSZONE_GRID_BUTTON,
17
+ FOCUSZONE_DIRECTION_PICKER,
18
+ } from './consts';
19
+ import { focusZoneTestStyles, GridButton } from './styles';
20
+
21
+ export const FocusZoneDirections: FocusZoneDirection[] = ['bidirectional', 'horizontal', 'vertical', 'none'];
22
+
23
+ type FocusZoneListWrapperProps = {
24
+ beforeID?: string;
25
+ afterID?: string;
26
+ };
27
+ export const FocusZoneListWrapper: React.FunctionComponent<FocusZoneListWrapperProps> = ({ beforeID, afterID, children }) => {
28
+ const buttonProps: ButtonProps = { children: 'Click to Focus', style: focusZoneTestStyles.listWrapperButton };
29
+ return (
30
+ <>
31
+ <Button {...buttonProps} testID={beforeID} />
32
+ {children}
33
+ <Button {...buttonProps} testID={afterID} />
34
+ </>
35
+ );
36
+ };
37
+
38
+ type GridOfButtonsProps = {
39
+ gridWidth: number;
40
+ gridHeight: number;
41
+ tabRef?: React.RefObject<View>;
42
+ tabbableIdx?: number;
43
+ e2etesting?: boolean;
44
+ };
45
+
46
+ export const GridOfButtons: React.FunctionComponent<GridOfButtonsProps> = (props: GridOfButtonsProps) => {
47
+ return (
48
+ <View style={focusZoneTestStyles.dashedBorder}>
49
+ {[...Array(props.gridHeight)].map((_value, heightIndex: number) => {
50
+ return (
51
+ <View key={heightIndex} style={focusZoneTestStyles.focusZoneViewStyle}>
52
+ {[...Array(props.gridWidth)].map((_value, widthIndex: number) => {
53
+ const gridIndex = heightIndex * props.gridWidth + widthIndex + 1;
54
+ return (
55
+ <GridButton
56
+ testID={props.e2etesting ? FOCUSZONE_GRID_BUTTON(gridIndex) : undefined}
57
+ key={widthIndex}
58
+ style={focusZoneTestStyles.focusZoneButton}
59
+ componentRef={gridIndex === props.tabbableIdx ? props.tabRef : undefined}
60
+ >
61
+ <Text>{gridIndex}</Text>
62
+ </GridButton>
63
+ );
64
+ })}
65
+ </View>
66
+ );
67
+ })}
68
+ </View>
69
+ );
70
+ };
71
+
72
+ export const FocusZone2D: React.FunctionComponent = () => {
73
+ const [is2DNav, set2dNav] = React.useState(false);
74
+ const [isDisabled, setDisabled] = React.useState(false);
75
+ const [isCircularNav, setIsCircularNav] = React.useState(false);
76
+ const [useDeffaultTabbableElement, setUseDeffaultTabbableElement] = React.useState(false);
77
+ const [direction, setDirection] = React.useState<FocusZoneDirection>('bidirectional');
78
+
79
+ const tabbableRef = React.useRef(null);
80
+
81
+ return (
82
+ <View style={commonTestStyles.root}>
83
+ <View style={commonTestStyles.settings}>
84
+ <Text variant="subheaderSemibold" testID={FOCUSZONE_TEST_COMPONENT}>
85
+ FocusZone Direction
86
+ </Text>
87
+ <MenuButton
88
+ testID={FOCUSZONE_DIRECTION_PICKER}
89
+ content={`Current direction: ${direction}`}
90
+ menuItems={FocusZoneDirections.map((dir) => ({
91
+ itemKey: dir,
92
+ text: dir,
93
+ testID: FOCUSZONE_DIRECTION_ID(dir),
94
+ }))}
95
+ onItemClick={(dir) => setDirection(dir as FocusZoneDirection)}
96
+ />
97
+ <Switch testID={FOCUSZONE_TWO_DIM_SWITCH} label="2D Navigation" checked={is2DNav} onChange={(_, checked) => set2dNav(checked)} />
98
+ <Switch testID={FOCUSZONE_DISABLED_SWITCH} label="Disabled" checked={isDisabled} onChange={(_, checked) => setDisabled(checked)} />
99
+ <Switch
100
+ testID={FOCUSZONE_CIRCLE_NAV_SWITCH}
101
+ label="Circular Navigation"
102
+ checked={isCircularNav}
103
+ onChange={(_, checked) => setIsCircularNav(checked)}
104
+ />
105
+ <Switch
106
+ testID={FOCUSZONE_DEFAULT_TABBABLE_SWITCH}
107
+ label="Use Default Tabbable Element"
108
+ checked={useDeffaultTabbableElement}
109
+ onChange={(_, checked) => setUseDeffaultTabbableElement(checked)}
110
+ />
111
+ </View>
112
+
113
+ <FocusZoneListWrapper beforeID={FOCUSZONE_GRID_BEFORE} afterID={FOCUSZONE_GRID_AFTER}>
114
+ <FocusZone
115
+ disabled={isDisabled}
116
+ use2DNavigation={is2DNav}
117
+ focusZoneDirection={direction}
118
+ isCircularNavigation={isCircularNav}
119
+ defaultTabbableElement={useDeffaultTabbableElement ? tabbableRef : undefined}
120
+ >
121
+ <GridOfButtons gridWidth={3} gridHeight={3} tabRef={tabbableRef} tabbableIdx={4} e2etesting />
122
+ </FocusZone>
123
+ </FocusZoneListWrapper>
124
+ </View>
125
+ );
126
+ };