-
-
Notifications
You must be signed in to change notification settings - Fork 643
chore(test): add e2e tests for overrideScrollViewContentInsetAdjustmentBehavior (iOS) #3960
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
4c3e912
4736878
a5655b6
96fb36d
8df7d76
8f6aa6b
7b5bd7a
09b8e90
2dd112f
2a098f8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,214 @@ | ||||||||||||||||||||||||||||||||||||||||||||
| import { expect as jestExpect } from '@jest/globals'; | ||||||||||||||||||||||||||||||||||||||||||||
| import { device, expect, element, by } from 'detox'; | ||||||||||||||||||||||||||||||||||||||||||||
| import { IosElementAttributes } from 'detox/detox'; | ||||||||||||||||||||||||||||||||||||||||||||
| import { | ||||||||||||||||||||||||||||||||||||||||||||
| describeIfiOS, | ||||||||||||||||||||||||||||||||||||||||||||
| forceTapByLabeliOS, | ||||||||||||||||||||||||||||||||||||||||||||
| selectSingleFeatureTestsScreen, | ||||||||||||||||||||||||||||||||||||||||||||
| } from '../../e2e-utils'; | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| async function getElementAttributes( | ||||||||||||||||||||||||||||||||||||||||||||
| testLabel: string, | ||||||||||||||||||||||||||||||||||||||||||||
| ): Promise<IosElementAttributes> { | ||||||||||||||||||||||||||||||||||||||||||||
| const attrs = await element(by.label(testLabel)).getAttributes(); | ||||||||||||||||||||||||||||||||||||||||||||
| return attrs as IosElementAttributes; | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| async function getTabBarFrame(): Promise<{ | ||||||||||||||||||||||||||||||||||||||||||||
| x: number; | ||||||||||||||||||||||||||||||||||||||||||||
| y: number; | ||||||||||||||||||||||||||||||||||||||||||||
| width: number; | ||||||||||||||||||||||||||||||||||||||||||||
| height: number; | ||||||||||||||||||||||||||||||||||||||||||||
| }> { | ||||||||||||||||||||||||||||||||||||||||||||
| const attrs = await element(by.type('UITabBar')).getAttributes(); | ||||||||||||||||||||||||||||||||||||||||||||
| return (attrs as IosElementAttributes).frame; | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
| async function getElementFrame(label: string): Promise<{ | ||||||||||||||||||||||||||||||||||||||||||||
| x: number; | ||||||||||||||||||||||||||||||||||||||||||||
| y: number; | ||||||||||||||||||||||||||||||||||||||||||||
| width: number; | ||||||||||||||||||||||||||||||||||||||||||||
| height: number; | ||||||||||||||||||||||||||||||||||||||||||||
| }> { | ||||||||||||||||||||||||||||||||||||||||||||
| const attrs = await element(by.label(label)).getAttributes(); | ||||||||||||||||||||||||||||||||||||||||||||
| return (attrs as IosElementAttributes).frame; | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+26
to
+34
|
||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| function isAboveTabBar( | ||||||||||||||||||||||||||||||||||||||||||||
| itemFrame: { y: number; height: number }, | ||||||||||||||||||||||||||||||||||||||||||||
| tabBarFrame: { y: number }, | ||||||||||||||||||||||||||||||||||||||||||||
| ): boolean { | ||||||||||||||||||||||||||||||||||||||||||||
| return itemFrame.y + itemFrame.height < tabBarFrame.y; | ||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||
| return itemFrame.y + itemFrame.height < tabBarFrame.y; | |
| const epsilon = 1; | |
| const itemBottom = itemFrame.y + itemFrame.height; | |
| return itemBottom <= tabBarFrame.y + epsilon; |
Copilot
AI
Apr 30, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test name has a trailing space and refers to "behind the inset", but the scenario is about being clipped behind the navigation bar/tab bar. Tightening the wording (and removing the trailing space) will make failures easier to interpret.
| it('should hide the information text behind the inset ', async () => { | |
| it('should render the information text clipped behind the navigation bar', async () => { |
Copilot
AI
Apr 30, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The assertion informationFrame.y === 16 hard-codes an absolute pixel position, which is very likely to vary across devices, orientations, Dynamic Type, and different navigation bar configurations. Instead, assert relative positioning (e.g., compare the header frame against the navigation bar/tab bar frames, or compare False vs True/Default header positions).
| const informationFrame = await getElementFrame( | |
| 'overrideScrollViewContentInsetAdjustmentBehavior: false', | |
| ); | |
| jestExpect(informationFrame.y).toEqual(16); | |
| const falseInformationFrame = await getElementFrame( | |
| 'overrideScrollViewContentInsetAdjustmentBehavior: false', | |
| ); | |
| await forceTapByLabeliOS('override-inset-tab-true'); | |
| await expect( | |
| element(by.id('override-inset-true-scrollview')), | |
| ).toBeVisible(); | |
| await scrollToMaxTop('override-inset-true-scrollview'); | |
| const trueInformationFrame = await getElementFrame( | |
| 'overrideScrollViewContentInsetAdjustmentBehavior: true', | |
| ); | |
| jestExpect(falseInformationFrame.y).toBeLessThan( | |
| trueInformationFrame.y, | |
| ); |
Copilot
AI
Apr 30, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tab selection here uses element(...).tap() instead of the iOS coordinate-based forceTapByLabeliOS. Other tab e2e tests in this repo use forced taps on iOS to avoid tab bar items being obstructed (e.g. by the iOS 26 “Liquid Glass lens”), so these taps are likely to be flaky on iOS. Use the same forced-tap helper for consistency and stability.
| await element(by.label('override-inset-tab-true')).tap(); | |
| await forceTapByLabeliOS('override-inset-tab-true'); |
Copilot
AI
Apr 30, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above: use forceTapByLabeliOS (or a shared forceSelectTabByLabel wrapper) for tab selection on iOS to avoid flakiness from obstructed tab bar items.
Copilot
AI
Apr 30, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These expect(element(by.label('Item 1'))) assertions are vulnerable to ambiguous matches because every tab renders the same item labels (and inactive tabs remain mounted). Scope the matcher to the active scroll view (e.g. withAncestor(by.id('override-inset-true-scrollview'))) or give the items stable testIDs to ensure Detox targets the correct element.
Copilot
AI
Apr 30, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tab selection in this cross-tab flow uses tap() on iOS. For consistency with other tab e2e tests (and to reduce flakiness when tab bar items are partially obstructed), use forceTapByLabeliOS for these tab item interactions as well.
Copilot
AI
Apr 30, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These two it(...) blocks in the same describe have identical titles, which makes it harder to identify which one failed in CI output. Rename one (e.g., distinguish True/Default comparison vs False→True switching).
Copilot
AI
Apr 30, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This second informationFrame.y === 16 assertion has the same hard-coded pixel fragility as the earlier one and can easily break on different devices/safe-area insets. Prefer a relative assertion (e.g., compare the False header frame to the True header frame after scrolling both to top, or compare against the navigation bar frame).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
getElementAttributesis defined but never used, and it duplicates the sharedgetElementAttributeshelper ine2e-utils(which also guards against multiple matches). Remove this function or switch call sites to the shared helper to avoid dead code and inconsistent attribute handling.