From 0501130b19c8b7b1cf50cdd5f82e726f710f4423 Mon Sep 17 00:00:00 2001
From: Sergey Volkov <s.volkov@netris.ru>
Date: Tue, 2 Apr 2019 13:31:50 +0300
Subject: [PATCH] feat(ios): compose accessibility identifier

For UI testing purposes compose "accessibilityIdentifier" property for views (same way it's done
with "contentDescription" on Android).
---
 .../TitaniumKit/TitaniumKit/Sources/API/TiUIView.m |  3 ++
 .../TitaniumKit/TitaniumKit/Sources/API/TiUtils.h  |  2 +
 .../TitaniumKit/TitaniumKit/Sources/API/TiUtils.m  | 45 ++++++++++++++++++++++
 3 files changed, 50 insertions(+)

diff --git a/iphone/TitaniumKit/TitaniumKit/Sources/API/TiUIView.m b/iphone/TitaniumKit/TitaniumKit/Sources/API/TiUIView.m
index b543f84..886e180 100644
--- a/iphone/TitaniumKit/TitaniumKit/Sources/API/TiUIView.m
+++ b/iphone/TitaniumKit/TitaniumKit/Sources/API/TiUIView.m
@@ -337,6 +337,7 @@ DEFINE_EXCEPTIONS
   if (accessibilityElement != nil) {
     [accessibilityElement setIsAccessibilityElement:YES];
     [accessibilityElement setAccessibilityLabel:[TiUtils stringValue:accessibilityLabel]];
+    [accessibilityElement setAccessibilityIdentifier:[TiUtils composeAccessibilityIdentifier:accessibilityElement]];
   }
 }
 
@@ -346,6 +347,7 @@ DEFINE_EXCEPTIONS
   if (accessibilityElement != nil) {
     [accessibilityElement setIsAccessibilityElement:YES];
     [accessibilityElement setAccessibilityValue:[TiUtils stringValue:accessibilityValue]];
+    [accessibilityElement setAccessibilityIdentifier:[TiUtils composeAccessibilityIdentifier:accessibilityElement]];
   }
 }
 
@@ -355,6 +357,7 @@ DEFINE_EXCEPTIONS
   if (accessibilityElement != nil) {
     [accessibilityElement setIsAccessibilityElement:YES];
     [accessibilityElement setAccessibilityHint:[TiUtils stringValue:accessibilityHint]];
+    [accessibilityElement setAccessibilityIdentifier:[TiUtils composeAccessibilityIdentifier:accessibilityElement]];
   }
 }
 
diff --git a/iphone/TitaniumKit/TitaniumKit/Sources/API/TiUtils.h b/iphone/TitaniumKit/TitaniumKit/Sources/API/TiUtils.h
index a0b77d7..ea878d6 100644
--- a/iphone/TitaniumKit/TitaniumKit/Sources/API/TiUtils.h
+++ b/iphone/TitaniumKit/TitaniumKit/Sources/API/TiUtils.h
@@ -577,6 +577,8 @@ typedef enum {
 
 + (void)applyConstraintToView:(TiUIView *)view forProxy:(TiViewProxy *)proxy withBounds:(CGRect)bounds;
 
++ (NSString *)composeAccessibilityIdentifier:(TiUIView *)view;
+
 + (CGRect)viewPositionRect:(UIView *)view;
 
 + (BOOL)barTranslucencyForColor:(TiColor *)color;
diff --git a/iphone/TitaniumKit/TitaniumKit/Sources/API/TiUtils.m b/iphone/TitaniumKit/TitaniumKit/Sources/API/TiUtils.m
index 0be51cc..774779b 100644
--- a/iphone/TitaniumKit/TitaniumKit/Sources/API/TiUtils.m
+++ b/iphone/TitaniumKit/TitaniumKit/Sources/API/TiUtils.m
@@ -1420,6 +1420,51 @@ If the new path starts with / and the base url is app://..., we have to massage
   ApplyConstraintToViewWithBounds([proxy layoutProperties], view, bounds);
 }
 
++ (NSString *)composeAccessibilityIdentifier:(TiUIView *)view
+{
+  NSString *accessibilityLabel = view.accessibilityLabel;
+  NSString *accessibilityValue = view.accessibilityValue;
+  NSString *accessibilityHint = view.accessibilityHint;
+  NSString *pattern = @"^.*[!\"#$%&'()*+,\\-./:;<=>?@\\[\\]^_`{|}~]\\s*$";
+  NSString *dot = @".";
+  NSString *space = @" ";
+  NSError *error = nil;
+  NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:pattern options:0 error:&error];
+  NSMutableArray *array = [NSMutableArray array];
+  NSUInteger numberOfMatches;
+
+  if (accessibilityLabel != nil && accessibilityLabel.length) {
+    [array addObject:accessibilityLabel];
+    numberOfMatches = [regex numberOfMatchesInString:accessibilityLabel options:0 range:NSMakeRange(0, [accessibilityLabel length])];
+    if (numberOfMatches == 0) {
+      [array addObject:dot];
+    }
+  }
+
+  if (accessibilityValue != nil && accessibilityValue.length) {
+    if ([array count] > 0) {
+      [array addObject:space];
+    }
+    [array addObject:accessibilityValue];
+    numberOfMatches = [regex numberOfMatchesInString:accessibilityValue options:0 range:NSMakeRange(0, [accessibilityValue length])];
+    if (numberOfMatches == 0) {
+      [array addObject:dot];
+    }
+  }
+
+  if (accessibilityHint != nil && accessibilityHint.length) {
+    if ([array count] > 0) {
+      [array addObject:space];
+    }
+    [array addObject:accessibilityHint];
+    numberOfMatches = [regex numberOfMatchesInString:accessibilityHint options:0 range:NSMakeRange(0, [accessibilityHint length])];
+    if (numberOfMatches == 0) {
+      [array addObject:dot];
+    }
+  }
+  return [array componentsJoinedByString:@""];
+}
+
 + (CGRect)viewPositionRect:(UIView *)view
 {
 #if USEFRAME
-- 
2.7.4

