Skip to content

Tags: avito-tech/Mixbox

Tags

0.3.78

Toggle 0.3.78's commit message
Empty set on TestabilityCustomValues

UnfinishedRelease_0.3.78

Toggle UnfinishedRelease_0.3.78's commit message
Empty set on TestabilityCustomValues

0.3.47

Toggle 0.3.47's commit message

0.3.46

Toggle 0.3.46's commit message
Remove generic SwiftUI tests

0.3.39

Toggle 0.3.39's commit message
Fix EXC_BAD_ACCESS in IdlingResourceObjectTracker

UnfinishedRelease_0.3.39

Toggle UnfinishedRelease_0.3.39's commit message
Fix EXC_BAD_ACCESS in IdlingResourceObjectTracker

0.3.38

Toggle 0.3.38's commit message
Add Xcode 15 headers

0.3.35

Toggle 0.3.35's commit message
Fix flakiness in `test___action___is_performed_after_scroll_view_dece…

…leration_ends___when_using_swipe`

0.3.25

Toggle 0.3.25's commit message
Remove unneccessary `static let`

- `static let ` that cached values were replaced with `static var`.
- Some singletons were replaced with DI.

`static let` is very slow due to synchronization.

Every `static let` was removed, except for case with caching regular expression (it is faster to cache it in `static let`) and singletons (it is neccessary there)

Even `static let`'s for simple values like `Int` were removed. Compiler optimizes them to behave as with `static var`, however, for me it is better to not think about compiler optimizations, also, if there are only few `static let`, it is easier to track bad code like singletons or `static let` that lead to synchronization even with compiler optimizations.

0.3.24

Toggle 0.3.24's commit message
Implement keyboard hierarchy without using accessibility hierarchy

TL;DR. Stability is improved, code was refactored to support new changes.

Description of the bug:

The bug was in an app that doesn't initialize accessibility hierarchy using private API. The workaround for that app was to initialize accessibility hierarchy,
but when I read a comment in that app, about why initialization of accessibility via private API was disabled, I decided to get rid of using accessibility and recreate hierarchy from scratch.

Notes about why:
- Accessibility hierarchy is unstable and can sometimes fails to be initialized (via private API), sometimes it initializes by itself without us using private API.
- Accessibility hierarchy has problems with compatibility, it may be different for different iOS versions
- Accessibility hiearachy often doesn't represent visual state of the GUI, lacks elements, or provides combined element instead of separate elements
- Etc, etc

Attemptes solution:

I changed implementations of `ViewHierarchyElement` to use `KeyboardPrivateApi` instead of accessibility, but realized that it won't work and the whole thing should be rewritten.

`OverridingChildrenTestabilityElementViewHierarchyElement`, `KeyboardLayoutViewHierarchyElement`,  `KeyboardKeyViewHierarchyElement` were removed.

Why it didn't work:

The reason is that getting view hierarchy is a separate mechanism (`ViewHierarchyProviderImpl`), the other one is visibility checking (`CheckVisibilityIpcMethodHandler`),
which goes to `AccessibilityUniqueObjectMap`, gets instance of another type (`TestabilityElement`) and doesn't see same fields as in those custom `ViewHierarchyElement` implementations.
That was a mistake. Now only `TestabilityElementViewHierarchyElement` is used, so visibility check is in sync with `ViewHierarchyProviderImpl`.
In practice there was a bug, `CheckVisibilityIpcMethodHandler` called `NonViewVisibilityCkeckerImpl` and it couldn't get the frame of the element (`frameRelativeToScreen`).

Final solution:

Instead, the old mechanism to create accessibility hierarchy was used - `TestabilityElement`.

I added categories for `UIKeyboardLayout` and `UIKBTree` that replace default behavior: `UIKeyboardLayout` returns children of type `UIKBTree`, `UIKBTree` returns proper frames and custom values (and other things).

This required to implement getter of custom values in Objective-C to override `customValues` (without messing with the state, for example, previously custom values couldn't be computed, only stored in associated value of NSObject as a state).

Notes about why it was needed and implementation details:
- The whole thing with `TestabilityElement` being an Objective-C protocol was initially created,
  because it allows us to easily override methods of NSObject (and especially), while reusing the inheritance hierarchy of Objective-C (we can write a custom method of getting test of UILabel, for example,
  in a separate file, in few lines of code, and it will work fast).
- The extensions could be written in Swift, but there were problems, I described them in headers for those Obj-C categories.

New private API was exposed, Swift wrappers were added. The new hierarchy now looks the same as before (that was based on accessibility initialized using private API)

Major changes you should notice:
- `TestabilityElement` now has `mb_testability_getSerializedCustomValues`, this means that it can be overriden in subclasses of `NSObject` via a category (or an extension in Swift)

Minor changes:
- `mb_cast` was added, it is a throwing version of `as?` cast, it throws error with default text if `as?`-cast fails.
- Added another example in `Disassembling.md`

Refactorings:
- Code of creating `TestablilityElement` was moved to `NonTestabilityElementFallbackTestabilityElement`, because we have OOP, let's use it
Small optimizations:
- `static let` was replaced with `static var` in `DefaultTestabilityElementValues` and dummy version of `TestabilityCustomValues`, because the creation of a small object or value is faster than synchronization inside `static let`

Changes in tests:
- Modern iOS versions (15 and 16) are now tested WITHOUT initializing accessibility hierarchy via private API
- Tests on iOS 14 remain using it, because it's still a feature, it is used, and it should be tested