@fluentui-react-native/tester 0.101.6 → 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 +16 -1
  2. package/CHANGELOG.md +10 -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 +1 -1
  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,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
+ };
@@ -1,19 +1,15 @@
1
1
  import * as React from 'react';
2
- import { View, Switch, ScrollView } from 'react-native';
3
- import { FocusZone, Text, FocusZoneDirection } from '@fluentui/react-native';
4
- import { ButtonV1 as Button, ButtonProps } from '@fluentui-react-native/button';
2
+ import { View, ScrollView } from 'react-native';
3
+ import { FocusZone, FocusZoneDirection, Text } from '@fluentui/react-native';
4
+ import { ButtonV1 as Button } from '@fluentui-react-native/button';
5
5
  import { Checkbox, CheckboxProps } from '@fluentui-react-native/experimental-checkbox';
6
6
  import { Test, TestSection, PlatformStatus } from '../Test';
7
7
  import { FOCUSZONE_TESTPAGE } from './consts';
8
- import { focusZoneTestStyles, GridButton, SubheaderText } from './styles';
9
- import { commonTestStyles } from '../Common/styles';
10
- import { CollectionItem, MenuPicker } from '../Common/MenuPicker';
8
+ import { focusZoneTestStyles, SubheaderText } from './styles';
9
+ import { FocusZone2D, FocusZoneDirections, FocusZoneListWrapper, GridOfButtons } from './FocusZoneE2ETest';
10
+ import { MenuPicker, CollectionItem } from '../Common/MenuPicker';
11
11
 
12
- const FocusZoneDirections: FocusZoneDirection[] = ['bidirectional', 'horizontal', 'vertical', 'none'];
13
- const directionCollection: CollectionItem<FocusZoneDirection>[] = FocusZoneDirections.map((x) => ({
14
- label: x,
15
- value: x,
16
- }));
12
+ const directionCollection: CollectionItem[] = FocusZoneDirections.map((dir) => ({ label: dir, value: dir }));
17
13
 
18
14
  const Checkboxes = (props: CheckboxProps) => {
19
15
  return (
@@ -25,6 +21,34 @@ const Checkboxes = (props: CheckboxProps) => {
25
21
  );
26
22
  };
27
23
 
24
+ const DirectionalFocusZone: React.FunctionComponent = () => {
25
+ const [direction, setDirection] = React.useState<FocusZoneDirection>('none');
26
+
27
+ return (
28
+ <>
29
+ <MenuPicker prompt="Direction" selected={direction} onChange={setDirection} collection={directionCollection} />
30
+ <FocusZone focusZoneDirection={direction}>
31
+ <Checkboxes />
32
+ </FocusZone>
33
+ </>
34
+ );
35
+ };
36
+
37
+ const CommonUsageFocusZone: React.FunctionComponent = () => {
38
+ return (
39
+ <FocusZoneListWrapper>
40
+ <FocusZone isCircularNavigation={true}>
41
+ <SubheaderText>FocusZone with Circular Navigation</SubheaderText>
42
+ <Checkboxes />
43
+ </FocusZone>
44
+ <FocusZone disabled={true}>
45
+ <SubheaderText>Disabled FocusZone</SubheaderText>
46
+ <Checkboxes />
47
+ </FocusZone>
48
+ </FocusZoneListWrapper>
49
+ );
50
+ };
51
+
28
52
  const FocusZoneInsideScrollView: React.FunctionComponent = () => {
29
53
  return (
30
54
  <FocusZoneListWrapper>
@@ -86,131 +110,16 @@ const NestedFocusZone: React.FunctionComponent = () => {
86
110
  );
87
111
  };
88
112
 
89
- const FocusZoneListWrapper = (props) => {
90
- const buttonProps: ButtonProps = { children: 'Click to Focus', style: focusZoneTestStyles.listWrapperButton };
91
- return (
92
- <>
93
- <Button {...buttonProps} />
94
- {React.Children.map(props.children, (child) => {
95
- return (
96
- <>
97
- {child}
98
- <Button {...buttonProps} />
99
- </>
100
- );
101
- })}
102
- </>
103
- );
104
- };
105
-
106
- const DirectionalFocusZone: React.FunctionComponent = () => {
107
- const [direction, setDirection] = React.useState<FocusZoneDirection>('none');
108
-
109
- return (
110
- <>
111
- <MenuPicker prompt="Direction" selected={direction} onChange={setDirection} collection={directionCollection} />
112
- <FocusZone focusZoneDirection={direction}>
113
- <Checkboxes />
114
- </FocusZone>
115
- </>
116
- );
117
- };
118
-
119
- const CommonUsageFocusZone: React.FunctionComponent = () => {
120
- return (
121
- <FocusZoneListWrapper>
122
- <FocusZone isCircularNavigation={true}>
123
- <SubheaderText>FocusZone with Circular Navigation</SubheaderText>
124
- <Checkboxes />
125
- </FocusZone>
126
- <FocusZone disabled={true}>
127
- <SubheaderText>Disabled FocusZone</SubheaderText>
128
- <Checkboxes />
129
- </FocusZone>
130
- </FocusZoneListWrapper>
131
- );
132
- };
133
-
134
- type GridOfButtonsProps = {
135
- gridWidth: number;
136
- gridHeight: number;
137
- };
138
-
139
- const GridOfButtons: React.FunctionComponent<GridOfButtonsProps> = (props: GridOfButtonsProps) => {
140
- return (
141
- <View style={focusZoneTestStyles.dashedBorder}>
142
- {[...Array(props.gridHeight)].map((_value, heightIndex: number) => {
143
- return (
144
- <View key={heightIndex} style={focusZoneTestStyles.focusZoneViewStyle}>
145
- {[...Array(props.gridWidth)].map((_value, widthIndex: number) => {
146
- const gridIndex = heightIndex * props.gridWidth + widthIndex + 1;
147
- return (
148
- <GridButton key={widthIndex} style={focusZoneTestStyles.focusZoneButton}>
149
- <Text>{gridIndex}</Text>
150
- </GridButton>
151
- );
152
- })}
153
- </View>
154
- );
155
- })}
156
- </View>
157
- );
158
- };
159
-
160
- interface ISwitchWithLabelProps {
161
- label: string;
162
- value: boolean;
163
- onValueChange: (value: boolean) => void;
164
- }
165
-
166
- function SwitchWithLabel(props: ISwitchWithLabelProps): React.ReactElement {
167
- const { label, value, onValueChange } = props;
168
- return (
169
- <View style={commonTestStyles.switch}>
170
- <Text>{label}</Text>
171
- <Switch value={value} onValueChange={onValueChange} />
172
- </View>
173
- );
174
- }
175
-
176
- const FocusZone2D: React.FunctionComponent = () => {
177
- const [is2DNav, set2dNav] = React.useState(false);
178
- const [isDisabled, setDisabled] = React.useState(false);
179
- const [isCircularNav, setIsCircularNav] = React.useState(false);
180
- const [direction, setDirection] = React.useState<FocusZoneDirection>('bidirectional');
181
-
182
- return (
183
- <View style={commonTestStyles.root}>
184
- <View style={commonTestStyles.settings}>
185
- <SwitchWithLabel label="2D Navigation" value={is2DNav} onValueChange={set2dNav} />
186
- <SwitchWithLabel label="Disabled" value={isDisabled} onValueChange={setDisabled} />
187
- <SwitchWithLabel label="Circular Navigation" value={isCircularNav} onValueChange={setIsCircularNav} />
188
- <MenuPicker prompt="Direction" selected={direction} onChange={setDirection} collection={directionCollection} />
189
- </View>
190
-
191
- <FocusZoneListWrapper>
192
- <FocusZone disabled={isDisabled} use2DNavigation={is2DNav} focusZoneDirection={direction} isCircularNavigation={isCircularNav}>
193
- <GridOfButtons gridWidth={3} gridHeight={3} />
194
- </FocusZone>
195
- </FocusZoneListWrapper>
196
- </View>
197
- );
198
- };
199
-
200
113
  const focusZoneSections: TestSection[] = [
201
114
  {
202
115
  name: 'Common FocusZone Usage',
203
116
  component: CommonUsageFocusZone,
117
+ testID: FOCUSZONE_TESTPAGE,
204
118
  },
205
119
  {
206
120
  name: 'Directional FocusZone Usage',
207
- testID: FOCUSZONE_TESTPAGE,
208
121
  component: DirectionalFocusZone,
209
122
  },
210
- {
211
- name: '2D Navigation',
212
- component: FocusZone2D,
213
- },
214
123
  {
215
124
  name: 'ScrollView inside FocusZone',
216
125
  component: FocusZoneInsideScrollView,
@@ -227,6 +136,10 @@ const focusZoneSections: TestSection[] = [
227
136
  name: 'Nested FocusZone',
228
137
  component: NestedFocusZone,
229
138
  },
139
+ {
140
+ name: '2D Navigation + E2E Testing',
141
+ component: FocusZone2D,
142
+ },
230
143
  ];
231
144
 
232
145
  export const FocusZoneTest: React.FunctionComponent = () => {
@@ -1,3 +1,5 @@
1
+ import { FocusZoneDirection } from '@fluentui/react-native';
2
+
1
3
  export const HOMEPAGE_FOCUSZONE_BUTTON = 'Homepage_FocusZone_Button';
2
4
  export const FOCUSZONE_TESTPAGE = 'FocusZone_TestPage';
3
5
 
@@ -6,3 +8,18 @@ export const FOCUSZONE_TEST_COMPONENT = 'FocusZone_Test_Component'; // A compone
6
8
 
7
9
  /* E2E Testing FocusZone 2 */
8
10
  export const FOCUSZONE_SECOND_TEST_COMPONENT = 'FocusZone_Second_Test_Component';
11
+
12
+ /* FocusZone List Wrapper Buttons Keys */
13
+ export const FOCUSZONE_GRID_BEFORE = 'FocusZone_Grid_Before';
14
+ export const FOCUSZONE_GRID_AFTER = 'FocusZone_Grid_After';
15
+
16
+ /* Grid Button Test IDs */
17
+ export const FOCUSZONE_GRID_BUTTON = (idx: number) => `FocusZone_GridButton_${idx}`;
18
+
19
+ export const FOCUSZONE_TWO_DIM_SWITCH = 'FocusZone_2D_Switch';
20
+ export const FOCUSZONE_DISABLED_SWITCH = 'FocusZone_Disabled_Switch';
21
+ export const FOCUSZONE_DEFAULT_TABBABLE_SWITCH = 'FocusZone_Default_Tabbable_Switch';
22
+ export const FOCUSZONE_CIRCLE_NAV_SWITCH = 'FocusZone_Circular_Navigation_Switch';
23
+
24
+ export const FOCUSZONE_DIRECTION_PICKER = 'FocusZone_Direction_Picker';
25
+ export const FOCUSZONE_DIRECTION_ID = (direction: FocusZoneDirection) => `FocusZone_Direction_Opt_${direction}`;
@@ -27,6 +27,11 @@ export const focusZoneTestStyles = StyleSheet.create({
27
27
  borderWidth: 1,
28
28
  borderStyle: 'dashed',
29
29
  },
30
+ radioGroup: {
31
+ display: 'flex',
32
+ flexDirection: 'row',
33
+ fontSize: 12,
34
+ },
30
35
  scrollViewStyle: {
31
36
  height: 100,
32
37
  width: 300,