Internal Sync for 2.0
diff --git a/Classes/GTXAccessibilityTree.m b/Classes/GTXAccessibilityTree.m
index c86ff1f..483d1c9 100644
--- a/Classes/GTXAccessibilityTree.m
+++ b/Classes/GTXAccessibilityTree.m
@@ -23,7 +23,7 @@
* UITextEffectsWindow which reports 9223372036854775807 possibly due to internal type conversions
* with -1, we use this bounds value to detect that case..
*/
-const NSInteger kAccessibilityChildrenUpperBound = 50000;
+static const NSInteger kAccessibilityChildrenUpperBound = 50000;
@implementation GTXAccessibilityTree {
// A queue of elements to be visited.
@@ -89,6 +89,10 @@
accessibilityElementsSet,
@([nextInQueue accessibilityElementCount]),
accessibilityElementsFromIndicesSet);
+
+ // Ensure accessibilityElements* are marked as used even if NSAssert is removed.
+ (void)accessibilityElementsSet;
+ (void)accessibilityElementsFromIndicesSet;
} else {
// Set accessibilityElements to whichever is non nil or leave it as is.
axElements = axElementsFromIndices ? axElementsFromIndices : axElements;
diff --git a/Classes/GTXBlacklistBlock.h b/Classes/GTXBlacklistBlock.h
new file mode 100644
index 0000000..1e073cd
--- /dev/null
+++ b/Classes/GTXBlacklistBlock.h
@@ -0,0 +1,51 @@
+//
+// Copyright 2018 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#import <UIKit/UIKit.h>
+
+#import "GTXBlacklisting.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+/**
+ A matcher block that determines if the given element must be ignored for the given check.
+
+ @param element Element to be looked up if it needs to be ignored.
+ @param checkName Name of the check for which element must be looked up.
+ @return @c YES if element needs to be ignored for the given check @c NO other wise.
+ */
+typedef BOOL(^GTXIgnoreElementMatcher)(id element, NSString *checkName);
+
+@interface GTXBlacklistBlock: NSObject<GTXBlacklisting>
+
+/**
+ * GTXBlacklistBlock::init is disabled, instead use GTXBlacklistBlock::blacklistWithBlock:
+ * method to create GTXBlacklists.
+ */
+- (instancetype)init __attribute__((unavailable("Use blacklistWithBlock: instead.")));
+
+/**
+ * Creates an GTXBlacklist with the given @c block that determines if an element should be ignored.
+ *
+ * @param block A block that determines if an element should be ignored.
+ *
+ * @return A GTXBlacklist object.
+ */
++ (id<GTXBlacklisting>)blacklistWithBlock:(GTXIgnoreElementMatcher)block;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/Classes/GTXBlacklistBlock.m b/Classes/GTXBlacklistBlock.m
new file mode 100644
index 0000000..3c16499
--- /dev/null
+++ b/Classes/GTXBlacklistBlock.m
@@ -0,0 +1,47 @@
+//
+// Copyright 2018 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#import "GTXBlacklistBlock.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@implementation GTXBlacklistBlock {
+ GTXIgnoreElementMatcher _block;
+}
+
++ (id<GTXBlacklisting>)blacklistWithBlock:(GTXIgnoreElementMatcher)block {
+ return [[GTXBlacklistBlock alloc] initWithBlock:block];
+}
+
+- (instancetype)initWithBlock:(GTXIgnoreElementMatcher)block {
+ NSParameterAssert(block);
+
+ self = [super init];
+ if (self) {
+ _block = block;
+ }
+ return self;
+}
+
+#pragma mark - GTXBlacklisting
+
+- (BOOL)shouldIgnoreElement:(id)element forCheckNamed:(NSString *)check {
+ return _block(element, check);
+}
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/Classes/GTXBlacklistFactory.h b/Classes/GTXBlacklistFactory.h
new file mode 100644
index 0000000..0fe3a83
--- /dev/null
+++ b/Classes/GTXBlacklistFactory.h
@@ -0,0 +1,61 @@
+//
+// Copyright 2018 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#import <UIKit/UIKit.h>
+
+#import "GTXBlacklisting.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+/**
+ * Factory for GTXBlacklisting objects for blacklisting elements.
+ */
+@interface GTXBlacklistFactory : NSObject
+
+- (instancetype)init NS_UNAVAILABLE;
+/**
+ * Returns a GTXBlacklisting object that ignores all elements that are instances of
+ * a given @c elementClassName.
+ *
+ * @param elementClassName The name of the class that should be blacklisted.
+ * @return A GTXBlacklisting object that ignores all elements of the given class.
+ */
++ (id<GTXBlacklisting>)blacklistWithClassName:(NSString *)elementClassName;
+/**
+ * Returns a GTXBlacklisting object that ignores all elements that are instances of
+ * a given @c elementClassName, but only for GTXChecking objects with a given @c checkName.
+ *
+ * @param elementClassName The name of the class that should be blacklisted.
+ * @param skipCheckName The name of the check that should ignore elements of the given class.
+ * @return A GTXBlacklisting object that ignores all elements of the given class when running the
+ * given check.
+ */
++ (id<GTXBlacklisting>)blacklistWithClassName:(NSString *)elementClassName
+ checkName:(NSString *)skipCheckName;
+/**
+ * Returns a GTXBlacklisting object that ignores all elements with a given accessibility
+ * identifier, but only for GTXChecking objects with a given @c checkName.
+ *
+ * @param accessibilityId The accessibility identifier of the element that should be blacklisted.
+ * @param skipCheckName The name of the check that should ignore elements with the given
+ * accessibility identifier.
+ */
++ (id<GTXBlacklisting>)blacklistWithAccessibilityIdentifier:(NSString *)accessibilityId
+ checkName:(NSString *)skipCheckName;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/Classes/GTXBlacklistFactory.m b/Classes/GTXBlacklistFactory.m
new file mode 100644
index 0000000..5c4d2d8
--- /dev/null
+++ b/Classes/GTXBlacklistFactory.m
@@ -0,0 +1,58 @@
+//
+// Copyright 2018 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#import "GTXBlacklistFactory.h"
+
+#import "GTXBlacklistBlock.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@implementation GTXBlacklistFactory
+
++ (id<GTXBlacklisting>)blacklistWithClassName:(NSString *)elementClassName {
+ Class classObject = NSClassFromString(elementClassName);
+ NSAssert(classObject, @"Class named %@ does not exist!", elementClassName);
+ GTXIgnoreElementMatcher matcher = ^BOOL(id element, NSString *checkName) {
+ return [element isKindOfClass:classObject];
+ };
+ return [GTXBlacklistBlock blacklistWithBlock:matcher];
+}
+
++ (id<GTXBlacklisting>)blacklistWithClassName:(NSString *)elementClassName
+ checkName:(NSString *)skipCheckName {
+ NSParameterAssert(elementClassName);
+ Class classObject = NSClassFromString(elementClassName);
+ NSAssert(classObject, @"Class named %@ does not exist!", elementClassName);
+ GTXIgnoreElementMatcher matcher = ^BOOL(id element, NSString *checkName) {
+ return [element isKindOfClass:classObject] && [checkName isEqualToString:skipCheckName];
+ };
+ return [GTXBlacklistBlock blacklistWithBlock:matcher];
+}
+
++ (id<GTXBlacklisting>)blacklistWithAccessibilityIdentifier:(NSString *)accessibilityId
+ checkName:(NSString *)skipCheckName {
+ NSParameterAssert(accessibilityId);
+ NSParameterAssert(skipCheckName);
+ GTXIgnoreElementMatcher matcher = ^BOOL(id element, NSString *checkName) {
+ return [[element accessibilityIdentifier] isEqualToString:accessibilityId] &&
+ [checkName isEqualToString:skipCheckName];
+ };
+ return [GTXBlacklistBlock blacklistWithBlock:matcher];
+}
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/Classes/GTXBlacklisting.h b/Classes/GTXBlacklisting.h
new file mode 100644
index 0000000..401d86f
--- /dev/null
+++ b/Classes/GTXBlacklisting.h
@@ -0,0 +1,38 @@
+//
+// Copyright 2018 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#import <UIKit/UIKit.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+/**
+ * Protocol for blacklisting certain types of UI elements in accessibility checks.
+ */
+@protocol GTXBlacklisting<NSObject>
+
+/**
+ * Determines if the given @c check should not be run on the given @c element.
+ *
+ * @param element The target element on which the GTX check is to be performed.
+ * @param[out] checkName The name of the check being run.
+ *
+ * @return @c YES if the check should NOT be performed on the given element, NO otherwise.
+ */
+- (BOOL)shouldIgnoreElement:(id)element forCheckNamed:(NSString *)checkName;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/Classes/GTXChecksCollection.h b/Classes/GTXChecksCollection.h
index 3f48a8a..9a4c331 100644
--- a/Classes/GTXChecksCollection.h
+++ b/Classes/GTXChecksCollection.h
@@ -42,7 +42,8 @@
* Organizes all checks provided by GTX, developers can use these as a starting point
* for implementing their own checks. These checks are based on recommendations found in
* "Accessibility Programming Guide for iOS"
- @link https://developer.apple.com/library/content/documentation/UserExperience/Conceptual/iPhoneAccessibility/Introduction/Introduction.html
+ @link
+ https://developer.apple.com/library/content/documentation/UserExperience/Conceptual/iPhoneAccessibility/Introduction/Introduction.html // NOLINT
* and on WCAG.
*/
@interface GTXChecksCollection : NSObject
@@ -50,12 +51,12 @@
/**
* @return An array of all supported GTXChecks for the given @c version.
*/
-+ (NSArray<GTXChecking> *)allChecksForVersion:(GTXVersion)version;
++ (NSArray<id<GTXChecking>> *)allChecksForVersion:(GTXVersion)version;
/**
* @return An array of all supported GTXChecks.
*/
-+ (NSArray<GTXChecking> *)allGTXChecks;
++ (NSArray<id<GTXChecking>> *)allGTXChecks;
/**
* @return a check that verifies that accessibility label is present on all accessibility elements.
@@ -69,6 +70,12 @@
+ (id<GTXChecking>)checkForAXLabelNotPunctuated;
/**
+ * @return a check that verifies that accessibility labels do not end in strings that VoiceOver
+ * announces via the element's accessibility traits.
+ */
++ (id<GTXChecking>)checkForAXLabelNotRedundantWithTraits;
+
+/**
* @return a check that verifies that accessibility traits dont conflict with each other as
* recommended by "Accessibility Programming Guide for iOS" (see class docs).
*/
diff --git a/Classes/GTXChecksCollection.m b/Classes/GTXChecksCollection.m
index 47cf6a9..1d6379d 100644
--- a/Classes/GTXChecksCollection.m
+++ b/Classes/GTXChecksCollection.m
@@ -26,6 +26,8 @@
NSString *const kGTXCheckNameAccessibilityLabelPresent = @"Accessibility Label Present";
NSString *const kGTXCheckNameAccessibilityLabelNotPunctuated =
@"Accessibility Label Not Punctuated";
+NSString *const kGTXCheckNameAccessibilityLabelIsNotRedundantWithTraits =
+ @"Accessibility Label is Not Redundant with Traits";
NSString *const kGTXCheckNameAccessibilityTraitsDontConflict =
@"Accessibility Traits Don't Conflict";
NSString *const kGTXCheckNameMinimumTappableArea = @"Element has Minimum Tappable Area";
@@ -34,21 +36,23 @@
#pragma mark - Globals
/**
- * The minimum size (width or height) for a given element to be easily accessible.
+ * The minimum size (width or height) for a given element to be easily accessible. Based on
+ * Material design guidelines:
+ * https://material.io/design/layout/spacing-methods.html#touch-click-targets
*/
-static const float kMinSizeForAccessibleElements = 48.0;
+static const float kGTXMinSizeForAccessibleElements = 48.0;
/**
* The minimum contrast ratio for any given text to be considered accessible. Note that smaller
* text has even stricter requirement of 4.5:1.
*/
-static const float kMinContrastRatioForAccessibleText = 3.0;
+static const float kGTXMinContrastRatioForAccessibleText = 3.0;
#pragma mark - Implementations
@implementation GTXChecksCollection
-+ (NSArray<GTXChecking> *)allChecksForVersion:(GTXVersion)version {
++ (NSArray<id<GTXChecking>> *)allChecksForVersion:(GTXVersion)version {
switch (version) {
case GTXVersionLatest: return [self allGTXChecks];
case GTXVersionPreRelease: return [self allGTXChecks];
@@ -59,6 +63,7 @@
+ (NSArray<id<GTXChecking>> *)allGTXChecks {
return @[[self checkForAXLabelPresent],
[self checkForAXLabelNotPunctuated],
+ [self checkForAXLabelNotRedundantWithTraits],
[self checkForAXTraitDontConflict],
[self checkForMinimumTappableArea],
[self checkForSufficientContrastRatio]];
@@ -141,6 +146,66 @@
return check;
}
+// @todo Include all UIAccessibilityTraits that announce themselves (image, search
+// field, etc.), and find a more robust way to determine if the label is redundant. Currently, the
+// suffix is compared to a single string, which causes false positives when that string occurs
+// elsewhere in the label or synonyms are used. Additionally, the hardcoded string only works in
+// English. This method also needs to be updated for i18n.
++ (id<GTXChecking>)checkForAXLabelNotRedundantWithTraits {
+ id<GTXChecking> check =
+ [GTXCheckBlock GTXCheckWithName:kGTXCheckNameAccessibilityLabelIsNotRedundantWithTraits
+ block:^BOOL(id element, GTXErrorRefType errorOrNil) {
+ UIAccessibilityTraits elementAXTraits = [element accessibilityTraits];
+ NSString *elementAXLabel = [element accessibilityLabel];
+ NSDictionary<NSNumber *, NSString *> const *redundantLabelsDictionary =
+ [self traitsToRedundantLabelsDictionary];
+ NSMutableArray<NSString *> *redundantTextList = [[NSMutableArray alloc] init];
+ NSMutableArray<NSString *> *redundantTraitNameList = [[NSMutableArray alloc] init];
+ for (NSNumber *testTrait in redundantLabelsDictionary) {
+ NSString* redundantText = [redundantLabelsDictionary objectForKey:testTrait];
+ UIAccessibilityTraits testUITrait = [testTrait unsignedLongLongValue];
+ if ((BOOL)(elementAXTraits & testUITrait)) {
+ if ([GTXChecksCollection caseInsensitive:elementAXLabel hasSuffix:redundantText]) {
+ NSError *error;
+ NSString *stringValue = [self stringValueOfUIAccessibilityTraits:testUITrait
+ error:&error];
+ if (error) {
+ if (errorOrNil) {
+ *errorOrNil = error;
+ }
+ return NO;
+ }
+
+ [redundantTextList addObject:redundantText];
+ [redundantTraitNameList addObject:stringValue];
+ }
+ }
+ }
+ if ([redundantTraitNameList count] > 0) {
+ NSString* stringOfRedundantTextList = [redundantTextList componentsJoinedByString:@", "];
+ NSString* stringOfRedundantTraitNameList =
+ [redundantTraitNameList componentsJoinedByString:@", "];
+ NSString *description = [NSString stringWithFormat:@"Suggest removing '%@' from the "
+ @"accessibility label '%@'. The element "
+ @"already contains the accessibility "
+ @"trait(s) %@. VoiceOver announces those "
+ @"traits to the user, so putting "
+ @"redundant words in the label causes "
+ @"VoiceOver to repeat them.",
+ stringOfRedundantTextList,
+ elementAXLabel,
+ stringOfRedundantTraitNameList];
+ [NSError gtx_logOrSetGTXCheckFailedError:errorOrNil
+ element:element
+ name:kGTXCheckNameAccessibilityLabelIsNotRedundantWithTraits
+ description:description];
+ return NO;
+ }
+ return YES;
+ }];
+ return check;
+}
+
+ (id<GTXChecking>)checkForAXTraitDontConflict {
id<GTXChecking> check =
[GTXCheckBlock GTXCheckWithName:kGTXCheckNameAccessibilityTraitsDontConflict
@@ -200,8 +265,8 @@
}
if ([element respondsToSelector:@selector(accessibilityFrame)]) {
CGRect frame = [element accessibilityFrame];
- BOOL hasSmallWidth = CGRectGetWidth(frame) < kMinSizeForAccessibleElements;
- BOOL hasSmallHeight = CGRectGetHeight(frame) < kMinSizeForAccessibleElements;
+ BOOL hasSmallWidth = CGRectGetWidth(frame) < kGTXMinSizeForAccessibleElements;
+ BOOL hasSmallHeight = CGRectGetHeight(frame) < kGTXMinSizeForAccessibleElements;
if (hasSmallWidth || hasSmallHeight) {
NSString *dimensionsToBeFixed;
// Append a suggestion to the error description.
@@ -219,9 +284,9 @@
[NSString stringWithFormat:@"Suggest increasing element's %@ to at least %d for "
@"a suggested tappable area of at least %dX%d",
dimensionsToBeFixed,
- (int)kMinSizeForAccessibleElements,
- (int)kMinSizeForAccessibleElements,
- (int)kMinSizeForAccessibleElements];
+ (int)kGTXMinSizeForAccessibleElements,
+ (int)kGTXMinSizeForAccessibleElements,
+ (int)kGTXMinSizeForAccessibleElements];
[NSError gtx_logOrSetGTXCheckFailedError:errorOrNil
element:element
@@ -244,13 +309,13 @@
}
CGFloat ratio = [GTXImageAndColorUtils contrastRatioOfUILabel:element];
BOOL hasSufficientContrast =
- (ratio >= kMinContrastRatioForAccessibleText - kContrastRatioAccuracy);
+ (ratio >= kGTXMinContrastRatioForAccessibleText - kGTXContrastRatioAccuracy);
if (!hasSufficientContrast) {
NSString *description =
[NSString stringWithFormat:@"Suggest increasing this element's contrast ratio to at "
"least "
@"%.5f the actual ratio was computed as %.5f",
- (float)kMinContrastRatioForAccessibleText, (float)ratio];
+ (float)kGTXMinContrastRatioForAccessibleText, (float)ratio];
[NSError gtx_logOrSetGTXCheckFailedError:errorOrNil
element:element
name:kGTXCheckNameMinimumContrastRatio
@@ -386,6 +451,17 @@
}
/**
+ * @return The UIAccessibilityTraits to redundant NSString accessibility label mapping dictionary
+ * as type NSDictionary<NSNumber *, NSString *> const *.
+ */
++ (NSDictionary<NSNumber *, NSString *> const *)traitsToRedundantLabelsDictionary {
+ return @{
+ @(UIAccessibilityTraitButton):
+ @"button",
+ };
+}
+
+/**
* @return @c YES if @c element is tappable (for ex button) @c NO otherwise.
*/
+ (BOOL)gtx_isTappableNonLinkElement:(id)element {
@@ -419,4 +495,12 @@
hasTextTrait);
}
+/**
+ * @return @c YES if the last characters of @c string equals @c suffix. Comparison is done case
+ * insensitively.
+ */
++ (BOOL)caseInsensitive:(NSString*)string hasSuffix:(NSString*)suffix {
+ return [[string lowercaseString] hasSuffix:suffix];
+}
+
@end
diff --git a/Classes/GTXImageAndColorUtils.h b/Classes/GTXImageAndColorUtils.h
index 34ce3c4..5d2792c 100644
--- a/Classes/GTXImageAndColorUtils.h
+++ b/Classes/GTXImageAndColorUtils.h
@@ -16,7 +16,7 @@
#import <UIKit/UIKit.h>
-extern const CGFloat kContrastRatioAccuracy;
+extern const CGFloat kGTXContrastRatioAccuracy;
/**
* Collection of accessibility related utils that use colors and/or images.
diff --git a/Classes/GTXImageAndColorUtils.m b/Classes/GTXImageAndColorUtils.m
index 8fd91ff..cd9bb9d 100644
--- a/Classes/GTXImageAndColorUtils.m
+++ b/Classes/GTXImageAndColorUtils.m
@@ -21,7 +21,7 @@
/**
* Accuracy of the contrast ratios provided by the APIs in this class.
*/
-const CGFloat kContrastRatioAccuracy = 0.05f;
+const CGFloat kGTXContrastRatioAccuracy = 0.05f;
@implementation GTXImageAndColorUtils
diff --git a/Classes/GTXPluginXCTestCase.m b/Classes/GTXPluginXCTestCase.m
index a0b25bf..4f52fd8 100644
--- a/Classes/GTXPluginXCTestCase.m
+++ b/Classes/GTXPluginXCTestCase.m
@@ -16,8 +16,9 @@
#import "GTXPluginXCTestCase.h"
-#import "GTXiLibCore.h"
#import "GTXAssertions.h"
+#import "GTXiLibCore.h"
+#import "GTXTestEnvironment.h"
#import <objc/runtime.h>
@@ -44,6 +45,7 @@
[self gtx_swizzleInstanceMethod:@selector(invokeTest)
withMethod:@selector(gtx_invokeTest)
inClass:gXCTestCaseClass];
+ [GTXTestEnvironment setupEnvironment];
});
}
@@ -81,6 +83,7 @@
typeEncoding);
NSAssert(success, @"Failed to add %@ from %@ to %@",
NSStringFromSelector(methodSelector), srcClass, destClass);
+ (void)success; // Ensures 'success' is marked as used even if NSAssert is removed.
}
/**
diff --git a/Classes/GTXTestEnvironment.h b/Classes/GTXTestEnvironment.h
new file mode 100644
index 0000000..bde20a5
--- /dev/null
+++ b/Classes/GTXTestEnvironment.h
@@ -0,0 +1,41 @@
+//
+// Copyright 2018 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#import <Foundation/Foundation.h>
+
+#import "GTXCommon.h"
+
+/**
+ * A class for setting up enviornment (devices, simulators) etc that GTX runs on.
+ */
+@interface GTXTestEnvironment : NSObject
+
+/**
+ * Sets up the enviornment for use by GTX.
+ *
+ * @param[out] errorOrNil A pointer to an NSError object to populate if there is an error, or nil
+ * if errors are not being handled.
+ * @return YES if the environment was set up successfully, NO otherwise, If NO and @c errorOrNil
+ * is not nil, @c errorOrNil is populated with a description of the error.
+ */
++ (BOOL)setupEnvironmentWithError:(GTXErrorRefType)errorOrNil;
+/**
+ * Sets up the enviornment for use by GTX. If the environment cannot be setup, then an exception
+ * is raised.
+ */
++ (void)setupEnvironment;
+
+@end
diff --git a/Classes/GTXTestEnvironment.m b/Classes/GTXTestEnvironment.m
new file mode 100644
index 0000000..7af591f
--- /dev/null
+++ b/Classes/GTXTestEnvironment.m
@@ -0,0 +1,222 @@
+//
+// Copyright 2018 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#import "GTXTestEnvironment.h"
+
+#import "GTXLogging.h"
+#import "NSError+GTXAdditions.h"
+
+#include <dlfcn.h>
+
+#pragma mark - Exposed Interfaces
+
+/**
+ * An Exposed internal class used for enabling accessibility on simulators.
+ */
+@interface AXBackBoardServer
+
+/**
+ * Returns current backboard server instance.
+ */
++ (instancetype)server;
+
+/**
+ * Sets the given preference and posts the given notification.
+ *
+ * @param key Name of the key whose value is to be set.
+ * @param value The value to be set to.
+ * @param notification The notification to be raised.
+ */
+- (void)setAccessibilityPreferenceAsMobile:(CFStringRef)key
+ value:(CFBooleanRef)value
+ notification:(CFStringRef)notification;
+
+@end
+
+#pragma mark - Globals
+
+/**
+ * Path to accessibility utils framework on the simulator.
+ */
+static NSString *const kPathToAXUtils =
+ @"/System/Library/PrivateFrameworks/AccessibilityUtilities.framework/AccessibilityUtilities";
+
+/**
+ * Class name of the private class: XCAXClient_iOS class.
+ */
+static NSString *const kXCAXClientClassName = @"XCAXClient_iOS";
+
+#pragma mark - Implementations
+
+@implementation GTXTestEnvironment
+
++ (BOOL)setupEnvironmentWithError:(GTXErrorRefType)errorOrNil {
+ static dispatch_once_t onceToken;
+ __block BOOL setupSuccessful = YES;
+ dispatch_once(&onceToken, ^{
+#if TARGET_OS_SIMULATOR
+ setupSuccessful = [self _enableAccessibilityForSimulatorWithError:errorOrNil];
+#else
+ setupSuccessful = [self _enableAccessibilityOnDeviceWithError:errorOrNil];
+#endif
+ });
+ return setupSuccessful;
+}
+
++ (void)setupEnvironment {
+ NSAssert([GTXTestEnvironment setupEnvironmentWithError:nil],
+ @"Test environment could not be set up");
+}
+
+/**
+ * Enables accessibility to allow using accessibility properties on simulators.
+ *
+ * @param[out] errorOrNil A pointer to an error object to return information on failure, or nil.
+ * @return YES if accessibility was enabled, NO if there was an error.
+ */
++ (BOOL)_enableAccessibilityForSimulatorWithError:(GTXErrorRefType)errorOrNil {
+ // Set the preferences that turn on Accessibility.
+ BOOL setSuccessful = YES;
+ setSuccessful =
+ [self _setAccessibilityPreference:(CFStringRef) @"ApplicationAccessibilityEnabled"
+ value:kCFBooleanTrue
+ notification:(CFStringRef) @"com.apple.accessibility.cache.app.ax"
+ error:errorOrNil];
+ if (!setSuccessful) {
+ return NO;
+ }
+ setSuccessful =
+ [self _setAccessibilityPreference:(CFStringRef) @"AccessibilityEnabled"
+ value:kCFBooleanTrue
+ notification:(CFStringRef) @"com.apple.accessibility.cache.ax"
+ error:errorOrNil];
+ return setSuccessful;
+}
+
+/**
+ * Sets the given preference and posts the given notification using @c AXBackBoardServer.
+ *
+ * @param key Name of the key whose value is to be set.
+ * @param value The value to be set to.
+ * @param name The name of the notification to be raised.
+ * @param[out] errorOrNil A pointer to an error object to return information on failure, or nil.
+ * @return YES if the preference was set, NO if there was an error.
+ */
++ (BOOL)_setAccessibilityPreference:(CFStringRef)key
+ value:(CFBooleanRef)value
+ notification:(CFStringRef)name
+ error:(GTXErrorRefType)errorOrNil {
+ __block BOOL setupSuccessful = YES;
+ static AXBackBoardServer *server;
+ static dispatch_once_t onceToken;
+ dispatch_once(&onceToken, ^{
+ char const *const localPath = [kPathToAXUtils fileSystemRepresentation];
+ void *handle = dlopen(localPath, RTLD_LOCAL);
+ if (!handle) {
+ NSString *description =
+ [NSString stringWithFormat:@"Could not load AccessibilityUtilities at %s", localPath];
+ [NSError gtx_logOrSetError:errorOrNil
+ description:description
+ code:GTXCheckErrorCodeInvalidTestEnvironment
+ userInfo:nil];
+ setupSuccessful = NO;
+ return;
+ }
+ (void)handle; // Ensures 'handle' is marked as used even if NSError is removed.
+ Class AXBackBoardServerClass = NSClassFromString(@"AXBackBoardServer");
+ if (!AXBackBoardServerClass) {
+ [NSError gtx_logOrSetError:errorOrNil
+ description:@"AXBackBoardServer class not found"
+ code:GTXCheckErrorCodeInvalidTestEnvironment
+ userInfo:nil];
+ setupSuccessful = NO;
+ return;
+ }
+ server = [AXBackBoardServerClass performSelector:@selector(server)];
+ if (!server) {
+ [NSError gtx_logOrSetError:errorOrNil
+ description:@"Could not retrieve AXBackBoardServer object"
+ code:GTXCheckErrorCodeInvalidTestEnvironment
+ userInfo:nil];
+ setupSuccessful = NO;
+ return;
+ }
+ });
+ [server setAccessibilityPreferenceAsMobile:key
+ value:value
+ notification:name];
+ return setupSuccessful;
+}
+
+/**
+ * Enables accessibility to allow using accessibility properties on devices.
+ */
++ (BOOL)_enableAccessibilityOnDeviceWithError:(GTXErrorRefType)errorOrNil {
+ Class XCAXClientClass = NSClassFromString(kXCAXClientClassName);
+ if (XCAXClientClass == nil) {
+ NSString *description = [NSString stringWithFormat:@"%@ class not found", kXCAXClientClassName];
+ [NSError gtx_logOrSetError:errorOrNil
+ description:description
+ code:GTXCheckErrorCodeInvalidTestEnvironment
+ userInfo:nil];
+ return NO;
+ }
+ id XCAXClient = [XCAXClientClass sharedClient];
+ if (XCAXClient == nil) {
+ NSString *description =
+ [NSString stringWithFormat:@"%@ sharedClient doesn't exist", kXCAXClientClassName];
+ [NSError gtx_logOrSetError:errorOrNil
+ description:description
+ code:GTXCheckErrorCodeInvalidTestEnvironment
+ userInfo:nil];
+ return NO;
+ }
+ // The method may not be available on versions older than iOS 9.1
+ if ([XCAXClient respondsToSelector:@selector(loadAccessibility:)]) {
+ typedef void (*MethodType)(id, SEL, void*);
+ SEL selector = @selector(loadAccessibility:);
+ static void *unused = 0;
+ MethodType method = (MethodType)[XCAXClient methodForSelector:selector];
+ method(XCAXClient, selector, &unused);
+ } else {
+ [NSError gtx_logOrSetError:errorOrNil
+ description:@"Could not enable accessibility! iOS version must be >= 9.1"
+ code:GTXCheckErrorCodeInvalidTestEnvironment
+ userInfo:nil];
+ return NO;
+ }
+ return YES;
+}
+
+#pragma mark - unused methods
+
+/**
+ * Unused method only used for selector name.
+ */
+- (id)sharedClient {
+ NSAssert(NO, @"This method must not be invoked directly, its only used for exposing selector");
+ return nil;
+}
+
+/**
+ * Unused method only used for selector name.
+ */
+- (BOOL)loadAccessibility:(void **)unused {
+ NSAssert(NO, @"This method must not be invoked directly, its only used for exposing selector");
+ return NO;
+}
+
+@end
diff --git a/Classes/GTXToolKit.h b/Classes/GTXToolKit.h
index 6f20081..ac9ea49 100644
--- a/Classes/GTXToolKit.h
+++ b/Classes/GTXToolKit.h
@@ -16,8 +16,10 @@
#import <UIKit/UIKit.h>
-#import "GTXChecking.h"
+#import "GTXBlacklistBlock.h"
+#import "GTXBlacklisting.h"
#import "GTXCheckBlock.h"
+#import "GTXChecking.h"
NS_ASSUME_NONNULL_BEGIN
@@ -45,9 +47,17 @@
*/
- (void)registerCheck:(id<GTXChecking>)check;
+/**
+ Registers the given blacklist to be executed on all elements this instance is used on. Registered
+ checks are not performed on blacklisted elements.
+
+ @param blacklist The blacklist to be registered.
+ */
+- (void)registerBlacklist:(id<GTXBlacklisting>)blacklist;
+
/**
- Applies the registered checks on the given element while respecting ignored elements.
+ Applies the registered checks on the given element while respecting blacklisted elements.
@param element element to be checked.
@param errorOrNil Error object to be filled with error info on check failures.
@@ -58,7 +68,7 @@
/**
Applies the registered checks on all elements in the accessibility tree under the given root
- elements while respecting ignored elements.
+ elements while respecting blacklisted elements.
@param rootElements An array of root elements whose accessibility trees are to be checked.
@param errorOrNil Error object to be filled with error info on check failures.
@@ -67,21 +77,6 @@
- (BOOL)checkAllElementsFromRootElements:(NSArray *)rootElements
error:(GTXErrorRefType)errorOrNil;
-/**
- Configures this instance to skip elements of the given class name from all checks.
-
- @param className The name of the class to be ignored.
- */
-- (void)ignoreElementsOfClassNamed:(NSString *)className;
-
-/**
- Configures this instance to skip elements of the given class name from a specific check.
-
- @param className The name of the class to be ignored.
- @param skipCheckName The name of the check for which this element is to be ignored.
- */
-- (void)ignoreElementsOfClassNamed:(NSString *)className forCheckNamed:(NSString *)skipCheckName;
-
@end
NS_ASSUME_NONNULL_END
diff --git a/Classes/GTXToolKit.m b/Classes/GTXToolKit.m
index 414e552..6857114 100644
--- a/Classes/GTXToolKit.m
+++ b/Classes/GTXToolKit.m
@@ -18,29 +18,22 @@
#import "GTXAccessibilityTree.h"
#import "GTXAnalytics.h"
+#import "GTXBlacklistBlock.h"
+#import "GTXBlacklistFactory.h"
#import "NSError+GTXAdditions.h"
-/**
- A matcher block that determines if the given element must be ignored for the given check.
-
- @param element Element to be looked up if it needs to be ignored.
- @param checkName Name of the check for which element must be looked up.
- @return @c YES if element needs to be ignored for the given check @c NO other wise.
- */
-typedef BOOL(^GTXIgnoreElementMatcher)(id element, NSString *checkName);
-
#pragma mark - Implementation
@implementation GTXToolKit {
NSMutableArray<id<GTXChecking>> *_checks;
- NSMutableArray<GTXIgnoreElementMatcher> *_blackListMatchers;
+ NSMutableArray<id<GTXBlacklisting>> *_blacklists;
}
- (instancetype)init {
self = [super init];
if (self) {
_checks = [[NSMutableArray alloc] init];
- _blackListMatchers = [[NSMutableArray alloc] init];
+ _blacklists = [[NSMutableArray alloc] init];
}
return self;
}
@@ -54,10 +47,15 @@
for (id<GTXChecking> existingCheck in _checks) {
NSAssert(![[existingCheck name] isEqualToString:[check name]],
@"Check named %@ already exists!", [check name]);
+ (void)existingCheck; // Ensures 'existingCheck' is marked as used even if NSAssert is removed.
}
[_checks addObject:check];
}
+- (void)registerBlacklist:(id<GTXBlacklisting>)blacklist {
+ [_blacklists addObject:blacklist];
+}
+
- (BOOL)checkElement:(id)element error:(GTXErrorRefType)errorOrNil {
return [self _checkElement:element analyticsEnabled:YES error:errorOrNil];
}
@@ -125,29 +123,10 @@
return errors == nil;
}
-- (void)ignoreElementsOfClassNamed:(NSString *)className {
- Class classObject = NSClassFromString(className);
- NSAssert(classObject, @"Class named %@ does not exist!", className);
- GTXIgnoreElementMatcher matcher = ^BOOL(id element, NSString *checkName) {
- return [element isKindOfClass:classObject];
- };
- [_blackListMatchers addObject:matcher];
-}
-
-- (void)ignoreElementsOfClassNamed:(NSString *)className forCheckNamed:(NSString *)skipCheckName {
- NSParameterAssert(skipCheckName);
- Class classObject = NSClassFromString(className);
- NSAssert(classObject, @"Class named %@ does not exist!", className);
- GTXIgnoreElementMatcher matcher = ^BOOL(id element, NSString *checkName) {
- return [element isKindOfClass:classObject] && [checkName isEqualToString:skipCheckName];
- };
- [_blackListMatchers addObject:matcher];
-}
-
#pragma mark - private
/**
- Applies the registered checks on the given element while respecting ignored elements.
+ Applies the registered checks on the given element while respecting blacklisted elements.
@param element element to be checked.
@param checkAnalyticsEnabled Boolean that indicates if analytics events are to be invoked.
@@ -167,8 +146,8 @@
NSMutableArray *failedCheckErrors;
for (id<GTXChecking> checker in _checks) {
BOOL shouldSkipThisCheck = NO;
- for (GTXIgnoreElementMatcher matcher in _blackListMatchers) {
- if (matcher(element, [checker name])) {
+ for (id<GTXBlacklisting> blacklist in _blacklists) {
+ if ([blacklist shouldIgnoreElement:element forCheckNamed:[checker name]]) {
shouldSkipThisCheck = YES;
break;
}
@@ -186,7 +165,8 @@
@"check implementation.", [checker name]];
error = [NSError errorWithDomain:kGTXErrorDomain
code:GTXCheckErrorCodeAccessibilityCheckFailed
- userInfo:@{ NSLocalizedDescriptionKey: errorDescription }];
+ userInfo:@{ NSLocalizedDescriptionKey: errorDescription,
+ kGTXErrorFailingElementKey: element }];
}
if (!failedCheckErrors) {
failedCheckErrors = [[NSMutableArray alloc] init];
diff --git a/Classes/GTXiLib.h b/Classes/GTXiLib.h
index 4a84dee..22964be 100644
--- a/Classes/GTXiLib.h
+++ b/Classes/GTXiLib.h
@@ -33,7 +33,7 @@
#import <GTXiLib/GTXCheckBlock.h>
#import <GTXiLib/GTXChecksCollection.h>
#import <GTXiLib/GTXCommon.h>
-#import <GTXiLib/GTXElementBlacklist.h>
+#import <GTXiLib/GTXBlacklistFactory.h>
#import <GTXiLib/GTXErrorReporter.h>
#import <GTXiLib/GTXImageRGBAData.h>
#import <GTXiLib/GTXImageAndColorUtils.h>
diff --git a/Classes/GTXiLibCore.h b/Classes/GTXiLibCore.h
index 56ea83b..a601a22 100644
--- a/Classes/GTXiLibCore.h
+++ b/Classes/GTXiLibCore.h
@@ -16,10 +16,10 @@
#import "GTXAnalytics.h"
#import "GTXAccessibilityTree.h"
+#import "GTXBlacklisting.h"
#import "GTXCheckBlock.h"
#import "GTXChecksCollection.h"
#import "GTXCommon.h"
-#import "GTXElementBlacklist.h"
#import "GTXErrorReporter.h"
#import "GTXTestSuite.h"
#import "NSError+GTXAdditions.h"
@@ -78,7 +78,7 @@
*/
+ (void)installOnTestSuite:(GTXTestSuite *)suite
checks:(NSArray<id<GTXChecking>> *)checks
- elementBlacklists:(NSArray<GTXElementBlacklist *> *)blacklists;
+ elementBlacklists:(NSArray<id<GTXBlacklisting>> *)blacklists;
/**
Creates a check with the given name and block.
@@ -91,24 +91,6 @@
+ (id<GTXChecking>)checkWithName:(NSString *)name block:(GTXCheckHandlerBlock)block;
/**
- Creates a blacklist matcher that skips elements of the given class from all checks.
-
- @param className The class name of the element.
- @return The newly created blacklist matcher.
- */
-+ (GTXElementBlacklist *)blacklistForElementsOfClassNamed:(NSString *)className;
-
-/**
- Creates a blacklist matcher that skips elements of the given class from the given check.
-
- @param className The class name of the element.
- @param skipCheckName The name of the check from which to skip the elements.
- @return The newly created blacklist matcher.
- */
-+ (GTXElementBlacklist *)blacklistForElementsOfClassNamed:(NSString *)className
- forCheckNamed:(NSString *)skipCheckName;
-
-/**
The failure handler to be invoked when checks fail, by default if checks fail an Assertion is
raised.
*/
diff --git a/Classes/GTXiLibCore.m b/Classes/GTXiLibCore.m
index 68858c0..015b3fa 100644
--- a/Classes/GTXiLibCore.m
+++ b/Classes/GTXiLibCore.m
@@ -16,12 +16,12 @@
#import "GTXiLibCore.h"
-#import "GTXToolKit.h"
#import "GTXAssertions.h"
#import "GTXChecking.h"
#import "GTXChecksCollection.h"
#import "GTXLogging.h"
#import "GTXPluginXCTestCase.h"
+#import "GTXToolKit.h"
#import "NSError+GTXAdditions.h"
#pragma mark - Global definitions.
@@ -81,7 +81,7 @@
+ (void)installOnTestSuite:(GTXTestSuite *)suite
checks:(NSArray<id<GTXChecking>> *)checks
- elementBlacklists:(NSArray<GTXElementBlacklist *> *)blacklists {
+ elementBlacklists:(NSArray<id<GTXBlacklisting>> *)blacklists {
[GTXPluginXCTestCase installPlugin];
if (!gIntsallOptions) {
gIntsallOptions = [[NSMutableArray alloc] init];
@@ -98,6 +98,7 @@
NSAssert(intersection.tests.count == 0,
@"Error! Attempting to install GTXChecks multiple times on the same test cases: %@",
intersection);
+ (void)intersection; // Ensures 'intersection' is marked as used even if NSAssert is removed.
}
[gIntsallOptions addObject:options];
@@ -143,17 +144,6 @@
return [GTXToolKit checkWithName:name block:block];
}
-+ (GTXElementBlacklist *)blacklistForElementsOfClassNamed:(NSString *)className {
- return [[GTXElementBlacklist alloc] initWithElementClassName:className
- checkName:nil];
-}
-
-+ (GTXElementBlacklist *)blacklistForElementsOfClassNamed:(NSString *)className
- forCheckNamed:(NSString *)skipCheckName {
- return [[GTXElementBlacklist alloc] initWithElementClassName:className
- checkName:skipCheckName];
-}
-
#pragma mark - Private
/**
@@ -216,13 +206,8 @@
for (id<GTXChecking> check in gCurrentOptions.checks) {
[gToolkit registerCheck:check];
}
- for (GTXElementBlacklist *blacklist in gCurrentOptions.elementBlacklist) {
- if (blacklist.checkName) {
- [gToolkit ignoreElementsOfClassNamed:blacklist.elementClassName
- forCheckNamed:blacklist.checkName];
- } else {
- [gToolkit ignoreElementsOfClassNamed:blacklist.elementClassName];
- }
+ for (id<GTXBlacklisting> blacklist in gCurrentOptions.elementBlacklist) {
+ [gToolkit registerBlacklist:blacklist];
}
}
}
diff --git a/Classes/NSError+GTXAdditions.h b/Classes/NSError+GTXAdditions.h
index 0cfe713..731d87f 100644
--- a/Classes/NSError+GTXAdditions.h
+++ b/Classes/NSError+GTXAdditions.h
@@ -58,6 +58,10 @@
*/
GTXCheckErrorCodeNotFocusableElement,
/**
+ * The test environment could not be set up before tests are run.
+ */
+ GTXCheckErrorCodeInvalidTestEnvironment,
+ /**
* An error code for all errors not related to the above.
*/
GTXCheckErrorCodeGenericError,
diff --git a/Classes/NSError+GTXAdditions.m b/Classes/NSError+GTXAdditions.m
index 0e35935..2c43da9 100644
--- a/Classes/NSError+GTXAdditions.m
+++ b/Classes/NSError+GTXAdditions.m
@@ -59,7 +59,7 @@
[NSString stringWithFormat:@"Check \"%@\" failed, %@",
name, description];
NSDictionary *userInfo = @{ NSLocalizedDescriptionKey : fullDescription,
- kGTXErrorFailingElementKey: [element description],
+ kGTXErrorFailingElementKey: element,
kGTXErrorCheckNameKey: name };
NSError *error = [NSError errorWithDomain:kGTXErrorDomain
code:GTXCheckErrorCodeAccessibilityCheckFailed
diff --git a/GTXiLib.xcodeproj/project.pbxproj b/GTXiLib.xcodeproj/project.pbxproj
index 33f7a2c..6650126 100644
--- a/GTXiLib.xcodeproj/project.pbxproj
+++ b/GTXiLib.xcodeproj/project.pbxproj
@@ -18,6 +18,31 @@
6115E7A0204F5BC9003E32F9 /* GTXTestAccessibilityElements.m in Sources */ = {isa = PBXBuildFile; fileRef = 6115E798204F5BC8003E32F9 /* GTXTestAccessibilityElements.m */; };
6115E7A1204F5BC9003E32F9 /* GTXImageAndColorUtilsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6115E799204F5BC8003E32F9 /* GTXImageAndColorUtilsTests.m */; };
6115E7A2204F5BC9003E32F9 /* GTXBaseTestCase.m in Sources */ = {isa = PBXBuildFile; fileRef = 6115E79A204F5BC9003E32F9 /* GTXBaseTestCase.m */; };
+ 61284DCB211E3FE400F8FF29 /* GTXTestViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 61284DC3211E3FE100F8FF29 /* GTXTestViewController.m */; };
+ 61284DCC211E3FE400F8FF29 /* GTXTestViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 61284DC4211E3FE200F8FF29 /* GTXTestViewController.xib */; };
+ 61284DCD211E3FE400F8FF29 /* GTXTestAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 61284DC5211E3FE200F8FF29 /* GTXTestAppDelegate.m */; };
+ 61284DCE211E3FE400F8FF29 /* GTXTestStepperButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 61284DC6211E3FE200F8FF29 /* GTXTestStepperButton.m */; };
+ 61284DCF211E3FE400F8FF29 /* GTXTestApp.m in Sources */ = {isa = PBXBuildFile; fileRef = 61284DCA211E3FE400F8FF29 /* GTXTestApp.m */; };
+ 61284DD5211E42CF00F8FF29 /* GTXBlacklistBlock.m in Sources */ = {isa = PBXBuildFile; fileRef = 61284DD2211E42CD00F8FF29 /* GTXBlacklistBlock.m */; };
+ 61284DD6211E42CF00F8FF29 /* GTXBlacklistBlock.h in Headers */ = {isa = PBXBuildFile; fileRef = 61284DD3211E42CE00F8FF29 /* GTXBlacklistBlock.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 61284DD7211E42CF00F8FF29 /* GTXBlacklisting.h in Headers */ = {isa = PBXBuildFile; fileRef = 61284DD4211E42CE00F8FF29 /* GTXBlacklisting.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 61284DDA211E437800F8FF29 /* GTXTestEnvironment.m in Sources */ = {isa = PBXBuildFile; fileRef = 61284DD8211E437700F8FF29 /* GTXTestEnvironment.m */; };
+ 61284DDB211E437800F8FF29 /* GTXTestEnvironment.h in Headers */ = {isa = PBXBuildFile; fileRef = 61284DD9211E437800F8FF29 /* GTXTestEnvironment.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 61284DF9211E447E00F8FF29 /* GTXTestGtxWorksForPassingTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 61284DEA211E447800F8FF29 /* GTXTestGtxWorksForPassingTests.m */; };
+ 61284DFA211E447E00F8FF29 /* GTXTestFailingClassFailCheck.m in Sources */ = {isa = PBXBuildFile; fileRef = 61284DEB211E447900F8FF29 /* GTXTestFailingClassFailCheck.m */; };
+ 61284DFB211E447E00F8FF29 /* GTXTestAnalyticsBaseTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 61284DEC211E447900F8FF29 /* GTXTestAnalyticsBaseTest.m */; };
+ 61284DFC211E447E00F8FF29 /* GTXTestGtxCanBlacklistTestCases.m in Sources */ = {isa = PBXBuildFile; fileRef = 61284DED211E447900F8FF29 /* GTXTestGtxCanBlacklistTestCases.m */; };
+ 61284DFD211E447E00F8FF29 /* GTXTestGtxCanDetectFailuresInInheritedTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 61284DEE211E447A00F8FF29 /* GTXTestGtxCanDetectFailuresInInheritedTests.m */; };
+ 61284DFE211E447E00F8FF29 /* GTXTestGtxCanIgnoreElements.m in Sources */ = {isa = PBXBuildFile; fileRef = 61284DEF211E447A00F8FF29 /* GTXTestGtxCanIgnoreElements.m */; };
+ 61284DFF211E447E00F8FF29 /* GTXTestGtxWithDefaultChecks.m in Sources */ = {isa = PBXBuildFile; fileRef = 61284DF0211E447A00F8FF29 /* GTXTestGtxWithDefaultChecks.m */; };
+ 61284E00211E447E00F8FF29 /* GTXTestBaseTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 61284DF1211E447B00F8FF29 /* GTXTestBaseTest.m */; };
+ 61284E01211E447E00F8FF29 /* GTXTestGtxCanWhitelistTestCases.m in Sources */ = {isa = PBXBuildFile; fileRef = 61284DF2211E447C00F8FF29 /* GTXTestGtxCanWhitelistTestCases.m */; };
+ 61284E02211E447E00F8FF29 /* GTXTestAnalyticsIsTriggered.m in Sources */ = {isa = PBXBuildFile; fileRef = 61284DF3211E447C00F8FF29 /* GTXTestAnalyticsIsTriggered.m */; };
+ 61284E03211E447E00F8FF29 /* GTXTestAnalyticsCanBeDisabled.m in Sources */ = {isa = PBXBuildFile; fileRef = 61284DF5211E447C00F8FF29 /* GTXTestAnalyticsCanBeDisabled.m */; };
+ 61284E04211E447E00F8FF29 /* GTXTestGtxCanIgnoreElementsOnSpecificCheck.m in Sources */ = {isa = PBXBuildFile; fileRef = 61284DF6211E447D00F8FF29 /* GTXTestGtxCanIgnoreElementsOnSpecificCheck.m */; };
+ 61284E05211E447E00F8FF29 /* GTXTestGtxCanDetectFailures.m in Sources */ = {isa = PBXBuildFile; fileRef = 61284DF8211E447D00F8FF29 /* GTXTestGtxCanDetectFailures.m */; };
+ 61284E0A211E45C600F8FF29 /* GTXBlacklistFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = 61284E08211E45C500F8FF29 /* GTXBlacklistFactory.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 61284E0B211E45C600F8FF29 /* GTXBlacklistFactory.m in Sources */ = {isa = PBXBuildFile; fileRef = 61284E09211E45C600F8FF29 /* GTXBlacklistFactory.m */; };
61A0C4DE2061896300DF0169 /* GTXiLibCore.m in Sources */ = {isa = PBXBuildFile; fileRef = 61A0C4DB2061896300DF0169 /* GTXiLibCore.m */; };
61A0C4DF2061896300DF0169 /* GTXiLib.h in Headers */ = {isa = PBXBuildFile; fileRef = 61A0C4DC2061896300DF0169 /* GTXiLib.h */; settings = {ATTRIBUTES = (Public, ); }; };
61A0C4E02061896300DF0169 /* GTXiLibCore.h in Headers */ = {isa = PBXBuildFile; fileRef = 61A0C4DD2061896300DF0169 /* GTXiLibCore.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -31,7 +56,6 @@
61ABAEB7204A0B0B006DBF0A /* GTXLogging.h in Headers */ = {isa = PBXBuildFile; fileRef = 61ABAE95204A0B03006DBF0A /* GTXLogging.h */; settings = {ATTRIBUTES = (Public, ); }; };
61ABAEB8204A0B0B006DBF0A /* GTXAnalyticsUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 61ABAE96204A0B03006DBF0A /* GTXAnalyticsUtils.m */; };
61ABAEB9204A0B0B006DBF0A /* GTXChecking.h in Headers */ = {isa = PBXBuildFile; fileRef = 61ABAE97204A0B04006DBF0A /* GTXChecking.h */; settings = {ATTRIBUTES = (Public, ); }; };
- 61ABAEBA204A0B0B006DBF0A /* GTXElementBlacklist.m in Sources */ = {isa = PBXBuildFile; fileRef = 61ABAE98204A0B04006DBF0A /* GTXElementBlacklist.m */; };
61ABAEBB204A0B0B006DBF0A /* GTXTestCase.m in Sources */ = {isa = PBXBuildFile; fileRef = 61ABAE99204A0B04006DBF0A /* GTXTestCase.m */; };
61ABAEBC204A0B0B006DBF0A /* GTXAccessibilityTree.m in Sources */ = {isa = PBXBuildFile; fileRef = 61ABAE9A204A0B04006DBF0A /* GTXAccessibilityTree.m */; };
61ABAEBD204A0B0B006DBF0A /* GTXAssertions.h in Headers */ = {isa = PBXBuildFile; fileRef = 61ABAE9B204A0B05006DBF0A /* GTXAssertions.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -50,7 +74,6 @@
61ABAECC204A0B0B006DBF0A /* GTXErrorReporter.m in Sources */ = {isa = PBXBuildFile; fileRef = 61ABAEAA204A0B09006DBF0A /* GTXErrorReporter.m */; };
61ABAECD204A0B0B006DBF0A /* GTXToolKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 61ABAEAB204A0B09006DBF0A /* GTXToolKit.h */; settings = {ATTRIBUTES = (Public, ); }; };
61ABAECE204A0B0B006DBF0A /* GTXImageRGBAData.m in Sources */ = {isa = PBXBuildFile; fileRef = 61ABAEAC204A0B0A006DBF0A /* GTXImageRGBAData.m */; };
- 61ABAED1204A0B0B006DBF0A /* GTXElementBlacklist.h in Headers */ = {isa = PBXBuildFile; fileRef = 61ABAEAF204A0B0A006DBF0A /* GTXElementBlacklist.h */; settings = {ATTRIBUTES = (Public, ); }; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@@ -61,6 +84,20 @@
remoteGlobalIDString = 613C3F40204A09E7007D44A8;
remoteInfo = GTAxe;
};
+ 61284DE5211E442800F8FF29 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 613C3F38204A09E7007D44A8 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 61284DAC211E3F8300F8FF29;
+ remoteInfo = TestApp;
+ };
+ 61284E06211E448F00F8FF29 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 613C3F38204A09E7007D44A8 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 613C3F40204A09E7007D44A8;
+ remoteInfo = GTXiLib;
+ };
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
@@ -77,6 +114,39 @@
6115E798204F5BC8003E32F9 /* GTXTestAccessibilityElements.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXTestAccessibilityElements.m; path = Tests/UnitTests/GTXTestAccessibilityElements.m; sourceTree = SOURCE_ROOT; };
6115E799204F5BC8003E32F9 /* GTXImageAndColorUtilsTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXImageAndColorUtilsTests.m; path = Tests/UnitTests/GTXImageAndColorUtilsTests.m; sourceTree = SOURCE_ROOT; };
6115E79A204F5BC9003E32F9 /* GTXBaseTestCase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXBaseTestCase.m; path = Tests/UnitTests/GTXBaseTestCase.m; sourceTree = SOURCE_ROOT; };
+ 61284DAD211E3F8300F8FF29 /* TestApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TestApp.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ 61284DC3211E3FE100F8FF29 /* GTXTestViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXTestViewController.m; path = Tests/FunctionalTests/TestApp/Sources/GTXTestViewController.m; sourceTree = SOURCE_ROOT; };
+ 61284DC4211E3FE200F8FF29 /* GTXTestViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = GTXTestViewController.xib; path = Tests/FunctionalTests/TestApp/Sources/GTXTestViewController.xib; sourceTree = SOURCE_ROOT; };
+ 61284DC5211E3FE200F8FF29 /* GTXTestAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXTestAppDelegate.m; path = Tests/FunctionalTests/TestApp/Sources/GTXTestAppDelegate.m; sourceTree = SOURCE_ROOT; };
+ 61284DC6211E3FE200F8FF29 /* GTXTestStepperButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXTestStepperButton.m; path = Tests/FunctionalTests/TestApp/Sources/GTXTestStepperButton.m; sourceTree = SOURCE_ROOT; };
+ 61284DC7211E3FE300F8FF29 /* GTXTestViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTXTestViewController.h; path = Tests/FunctionalTests/TestApp/Sources/GTXTestViewController.h; sourceTree = SOURCE_ROOT; };
+ 61284DC8211E3FE300F8FF29 /* GTXTestStepperButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTXTestStepperButton.h; path = Tests/FunctionalTests/TestApp/Sources/GTXTestStepperButton.h; sourceTree = SOURCE_ROOT; };
+ 61284DC9211E3FE300F8FF29 /* GTXTestAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTXTestAppDelegate.h; path = Tests/FunctionalTests/TestApp/Sources/GTXTestAppDelegate.h; sourceTree = SOURCE_ROOT; };
+ 61284DCA211E3FE400F8FF29 /* GTXTestApp.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXTestApp.m; path = Tests/FunctionalTests/TestApp/Sources/GTXTestApp.m; sourceTree = SOURCE_ROOT; };
+ 61284DD0211E3FF400F8FF29 /* GTXTestApp-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "GTXTestApp-Info.plist"; path = "Tests/FunctionalTests/TestApp/GTXTestApp-Info.plist"; sourceTree = SOURCE_ROOT; };
+ 61284DD2211E42CD00F8FF29 /* GTXBlacklistBlock.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXBlacklistBlock.m; path = Classes/GTXBlacklistBlock.m; sourceTree = SOURCE_ROOT; };
+ 61284DD3211E42CE00F8FF29 /* GTXBlacklistBlock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTXBlacklistBlock.h; path = Classes/GTXBlacklistBlock.h; sourceTree = SOURCE_ROOT; };
+ 61284DD4211E42CE00F8FF29 /* GTXBlacklisting.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTXBlacklisting.h; path = Classes/GTXBlacklisting.h; sourceTree = SOURCE_ROOT; };
+ 61284DD8211E437700F8FF29 /* GTXTestEnvironment.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXTestEnvironment.m; path = Classes/GTXTestEnvironment.m; sourceTree = SOURCE_ROOT; };
+ 61284DD9211E437800F8FF29 /* GTXTestEnvironment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTXTestEnvironment.h; path = Classes/GTXTestEnvironment.h; sourceTree = SOURCE_ROOT; };
+ 61284DE0211E442700F8FF29 /* FunctionalTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = FunctionalTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
+ 61284DEA211E447800F8FF29 /* GTXTestGtxWorksForPassingTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXTestGtxWorksForPassingTests.m; path = Tests/FunctionalTests/TestApp/TestSources/GTXTestGtxWorksForPassingTests.m; sourceTree = SOURCE_ROOT; };
+ 61284DEB211E447900F8FF29 /* GTXTestFailingClassFailCheck.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXTestFailingClassFailCheck.m; path = Tests/FunctionalTests/TestApp/TestSources/GTXTestFailingClassFailCheck.m; sourceTree = SOURCE_ROOT; };
+ 61284DEC211E447900F8FF29 /* GTXTestAnalyticsBaseTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXTestAnalyticsBaseTest.m; path = Tests/FunctionalTests/TestApp/TestSources/GTXTestAnalyticsBaseTest.m; sourceTree = SOURCE_ROOT; };
+ 61284DED211E447900F8FF29 /* GTXTestGtxCanBlacklistTestCases.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXTestGtxCanBlacklistTestCases.m; path = Tests/FunctionalTests/TestApp/TestSources/GTXTestGtxCanBlacklistTestCases.m; sourceTree = SOURCE_ROOT; };
+ 61284DEE211E447A00F8FF29 /* GTXTestGtxCanDetectFailuresInInheritedTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXTestGtxCanDetectFailuresInInheritedTests.m; path = Tests/FunctionalTests/TestApp/TestSources/GTXTestGtxCanDetectFailuresInInheritedTests.m; sourceTree = SOURCE_ROOT; };
+ 61284DEF211E447A00F8FF29 /* GTXTestGtxCanIgnoreElements.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXTestGtxCanIgnoreElements.m; path = Tests/FunctionalTests/TestApp/TestSources/GTXTestGtxCanIgnoreElements.m; sourceTree = SOURCE_ROOT; };
+ 61284DF0211E447A00F8FF29 /* GTXTestGtxWithDefaultChecks.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXTestGtxWithDefaultChecks.m; path = Tests/FunctionalTests/TestApp/TestSources/GTXTestGtxWithDefaultChecks.m; sourceTree = SOURCE_ROOT; };
+ 61284DF1211E447B00F8FF29 /* GTXTestBaseTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXTestBaseTest.m; path = Tests/FunctionalTests/TestApp/TestSources/GTXTestBaseTest.m; sourceTree = SOURCE_ROOT; };
+ 61284DF2211E447C00F8FF29 /* GTXTestGtxCanWhitelistTestCases.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXTestGtxCanWhitelistTestCases.m; path = Tests/FunctionalTests/TestApp/TestSources/GTXTestGtxCanWhitelistTestCases.m; sourceTree = SOURCE_ROOT; };
+ 61284DF3211E447C00F8FF29 /* GTXTestAnalyticsIsTriggered.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXTestAnalyticsIsTriggered.m; path = Tests/FunctionalTests/TestApp/TestSources/GTXTestAnalyticsIsTriggered.m; sourceTree = SOURCE_ROOT; };
+ 61284DF4211E447C00F8FF29 /* GTXTestAnalyticsBaseTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTXTestAnalyticsBaseTest.h; path = Tests/FunctionalTests/TestApp/TestSources/GTXTestAnalyticsBaseTest.h; sourceTree = SOURCE_ROOT; };
+ 61284DF5211E447C00F8FF29 /* GTXTestAnalyticsCanBeDisabled.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXTestAnalyticsCanBeDisabled.m; path = Tests/FunctionalTests/TestApp/TestSources/GTXTestAnalyticsCanBeDisabled.m; sourceTree = SOURCE_ROOT; };
+ 61284DF6211E447D00F8FF29 /* GTXTestGtxCanIgnoreElementsOnSpecificCheck.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXTestGtxCanIgnoreElementsOnSpecificCheck.m; path = Tests/FunctionalTests/TestApp/TestSources/GTXTestGtxCanIgnoreElementsOnSpecificCheck.m; sourceTree = SOURCE_ROOT; };
+ 61284DF7211E447D00F8FF29 /* GTXTestBaseTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTXTestBaseTest.h; path = Tests/FunctionalTests/TestApp/TestSources/GTXTestBaseTest.h; sourceTree = SOURCE_ROOT; };
+ 61284DF8211E447D00F8FF29 /* GTXTestGtxCanDetectFailures.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXTestGtxCanDetectFailures.m; path = Tests/FunctionalTests/TestApp/TestSources/GTXTestGtxCanDetectFailures.m; sourceTree = SOURCE_ROOT; };
+ 61284E08211E45C500F8FF29 /* GTXBlacklistFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTXBlacklistFactory.h; path = Classes/GTXBlacklistFactory.h; sourceTree = SOURCE_ROOT; };
+ 61284E09211E45C600F8FF29 /* GTXBlacklistFactory.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXBlacklistFactory.m; path = Classes/GTXBlacklistFactory.m; sourceTree = SOURCE_ROOT; };
613C3F41204A09E8007D44A8 /* GTXiLib.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = GTXiLib.framework; sourceTree = BUILT_PRODUCTS_DIR; };
61A0C4DB2061896300DF0169 /* GTXiLibCore.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXiLibCore.m; path = Classes/GTXiLibCore.m; sourceTree = SOURCE_ROOT; };
61A0C4DC2061896300DF0169 /* GTXiLib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTXiLib.h; path = Classes/GTXiLib.h; sourceTree = SOURCE_ROOT; };
@@ -92,7 +162,6 @@
61ABAE95204A0B03006DBF0A /* GTXLogging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTXLogging.h; path = Classes/GTXLogging.h; sourceTree = SOURCE_ROOT; };
61ABAE96204A0B03006DBF0A /* GTXAnalyticsUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXAnalyticsUtils.m; path = Classes/GTXAnalyticsUtils.m; sourceTree = SOURCE_ROOT; };
61ABAE97204A0B04006DBF0A /* GTXChecking.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTXChecking.h; path = Classes/GTXChecking.h; sourceTree = SOURCE_ROOT; };
- 61ABAE98204A0B04006DBF0A /* GTXElementBlacklist.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXElementBlacklist.m; path = Classes/GTXElementBlacklist.m; sourceTree = SOURCE_ROOT; };
61ABAE99204A0B04006DBF0A /* GTXTestCase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXTestCase.m; path = Classes/GTXTestCase.m; sourceTree = SOURCE_ROOT; };
61ABAE9A204A0B04006DBF0A /* GTXAccessibilityTree.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXAccessibilityTree.m; path = Classes/GTXAccessibilityTree.m; sourceTree = SOURCE_ROOT; };
61ABAE9B204A0B05006DBF0A /* GTXAssertions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTXAssertions.h; path = Classes/GTXAssertions.h; sourceTree = SOURCE_ROOT; };
@@ -111,7 +180,6 @@
61ABAEAA204A0B09006DBF0A /* GTXErrorReporter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXErrorReporter.m; path = Classes/GTXErrorReporter.m; sourceTree = SOURCE_ROOT; };
61ABAEAB204A0B09006DBF0A /* GTXToolKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTXToolKit.h; path = Classes/GTXToolKit.h; sourceTree = SOURCE_ROOT; };
61ABAEAC204A0B0A006DBF0A /* GTXImageRGBAData.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXImageRGBAData.m; path = Classes/GTXImageRGBAData.m; sourceTree = SOURCE_ROOT; };
- 61ABAEAF204A0B0A006DBF0A /* GTXElementBlacklist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTXElementBlacklist.h; path = Classes/GTXElementBlacklist.h; sourceTree = SOURCE_ROOT; };
61B7F4A2204A15D30062DF65 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Platforms/iPhoneOS.platform/Developer/Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; };
/* End PBXFileReference section */
@@ -124,6 +192,20 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
+ 61284DAA211E3F8300F8FF29 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 61284DDD211E442700F8FF29 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
613C3F3D204A09E7007D44A8 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
@@ -134,11 +216,51 @@
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
+ 61284DAE211E3F8300F8FF29 /* TestApp */ = {
+ isa = PBXGroup;
+ children = (
+ 61284DD0211E3FF400F8FF29 /* GTXTestApp-Info.plist */,
+ 61284DCA211E3FE400F8FF29 /* GTXTestApp.m */,
+ 61284DC9211E3FE300F8FF29 /* GTXTestAppDelegate.h */,
+ 61284DC5211E3FE200F8FF29 /* GTXTestAppDelegate.m */,
+ 61284DC8211E3FE300F8FF29 /* GTXTestStepperButton.h */,
+ 61284DC6211E3FE200F8FF29 /* GTXTestStepperButton.m */,
+ 61284DC7211E3FE300F8FF29 /* GTXTestViewController.h */,
+ 61284DC3211E3FE100F8FF29 /* GTXTestViewController.m */,
+ 61284DC4211E3FE200F8FF29 /* GTXTestViewController.xib */,
+ );
+ path = TestApp;
+ sourceTree = "<group>";
+ };
+ 61284DE1211E442700F8FF29 /* FunctionalTests */ = {
+ isa = PBXGroup;
+ children = (
+ 61284DF4211E447C00F8FF29 /* GTXTestAnalyticsBaseTest.h */,
+ 61284DEC211E447900F8FF29 /* GTXTestAnalyticsBaseTest.m */,
+ 61284DF5211E447C00F8FF29 /* GTXTestAnalyticsCanBeDisabled.m */,
+ 61284DF3211E447C00F8FF29 /* GTXTestAnalyticsIsTriggered.m */,
+ 61284DF7211E447D00F8FF29 /* GTXTestBaseTest.h */,
+ 61284DF1211E447B00F8FF29 /* GTXTestBaseTest.m */,
+ 61284DEB211E447900F8FF29 /* GTXTestFailingClassFailCheck.m */,
+ 61284DED211E447900F8FF29 /* GTXTestGtxCanBlacklistTestCases.m */,
+ 61284DF8211E447D00F8FF29 /* GTXTestGtxCanDetectFailures.m */,
+ 61284DEE211E447A00F8FF29 /* GTXTestGtxCanDetectFailuresInInheritedTests.m */,
+ 61284DEF211E447A00F8FF29 /* GTXTestGtxCanIgnoreElements.m */,
+ 61284DF6211E447D00F8FF29 /* GTXTestGtxCanIgnoreElementsOnSpecificCheck.m */,
+ 61284DF2211E447C00F8FF29 /* GTXTestGtxCanWhitelistTestCases.m */,
+ 61284DF0211E447A00F8FF29 /* GTXTestGtxWithDefaultChecks.m */,
+ 61284DEA211E447800F8FF29 /* GTXTestGtxWorksForPassingTests.m */,
+ );
+ path = FunctionalTests;
+ sourceTree = "<group>";
+ };
613C3F37204A09E7007D44A8 = {
isa = PBXGroup;
children = (
613C3F43204A09E8007D44A8 /* GTXiLib */,
61BC5526204E2736004D2FB9 /* GTXiUnitTests */,
+ 61284DAE211E3F8300F8FF29 /* TestApp */,
+ 61284DE1211E442700F8FF29 /* FunctionalTests */,
613C3F42204A09E8007D44A8 /* Products */,
61B7F4A1204A15D30062DF65 /* Frameworks */,
);
@@ -149,6 +271,8 @@
children = (
613C3F41204A09E8007D44A8 /* GTXiLib.framework */,
6115E786204F5BA2003E32F9 /* GTXiUnitTests.xctest */,
+ 61284DAD211E3F8300F8FF29 /* TestApp.app */,
+ 61284DE0211E442700F8FF29 /* FunctionalTests.xctest */,
);
name = Products;
sourceTree = "<group>";
@@ -168,6 +292,8 @@
61A0C4DC2061896300DF0169 /* GTXiLib.h */,
61A0C4DD2061896300DF0169 /* GTXiLibCore.h */,
61A0C4DB2061896300DF0169 /* GTXiLibCore.m */,
+ 61284E08211E45C500F8FF29 /* GTXBlacklistFactory.h */,
+ 61284E09211E45C600F8FF29 /* GTXBlacklistFactory.m */,
61ABAE93204A0B03006DBF0A /* GTXAccessibilityTree.h */,
61ABAE9A204A0B04006DBF0A /* GTXAccessibilityTree.m */,
61ABAE8F204A0B02006DBF0A /* GTXAnalytics.h */,
@@ -175,6 +301,9 @@
61ABAE8E204A0B02006DBF0A /* GTXAnalyticsUtils.h */,
61ABAE96204A0B03006DBF0A /* GTXAnalyticsUtils.m */,
61ABAE9B204A0B05006DBF0A /* GTXAssertions.h */,
+ 61284DD3211E42CE00F8FF29 /* GTXBlacklistBlock.h */,
+ 61284DD2211E42CD00F8FF29 /* GTXBlacklistBlock.m */,
+ 61284DD4211E42CE00F8FF29 /* GTXBlacklisting.h */,
61ABAEA9204A0B09006DBF0A /* GTXCheckBlock.h */,
61ABAE9E204A0B06006DBF0A /* GTXCheckBlock.m */,
610CA3FB204DFC76008BAAA1 /* GTXPluginXCTestCase.h */,
@@ -183,8 +312,6 @@
61ABAEA8204A0B08006DBF0A /* GTXChecksCollection.h */,
61ABAEA4204A0B07006DBF0A /* GTXChecksCollection.m */,
61ABAE94204A0B03006DBF0A /* GTXCommon.h */,
- 61ABAEAF204A0B0A006DBF0A /* GTXElementBlacklist.h */,
- 61ABAE98204A0B04006DBF0A /* GTXElementBlacklist.m */,
61ABAE90204A0B02006DBF0A /* GTXErrorReporter.h */,
61ABAEAA204A0B09006DBF0A /* GTXErrorReporter.m */,
61ABAEA2204A0B06006DBF0A /* GTXImageAndColorUtils.h */,
@@ -192,6 +319,8 @@
61ABAE9C204A0B05006DBF0A /* GTXImageRGBAData.h */,
61ABAEAC204A0B0A006DBF0A /* GTXImageRGBAData.m */,
61ABAE95204A0B03006DBF0A /* GTXLogging.h */,
+ 61284DD9211E437800F8FF29 /* GTXTestEnvironment.h */,
+ 61284DD8211E437700F8FF29 /* GTXTestEnvironment.m */,
61ABAEA1204A0B06006DBF0A /* GTXTestCase.h */,
61ABAE99204A0B04006DBF0A /* GTXTestCase.m */,
61ABAE9F204A0B06006DBF0A /* GTXTestSuite.h */,
@@ -236,8 +365,8 @@
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
+ 61284DDB211E437800F8FF29 /* GTXTestEnvironment.h in Headers */,
61ABAEB5204A0B0B006DBF0A /* GTXAccessibilityTree.h in Headers */,
- 61ABAED1204A0B0B006DBF0A /* GTXElementBlacklist.h in Headers */,
61ABAECD204A0B0B006DBF0A /* GTXToolKit.h in Headers */,
61ABAEC8204A0B0B006DBF0A /* NSError+GTXAdditions.h in Headers */,
61ABAEC4204A0B0B006DBF0A /* GTXImageAndColorUtils.h in Headers */,
@@ -245,11 +374,14 @@
61ABAEBD204A0B0B006DBF0A /* GTXAssertions.h in Headers */,
610CA3FD204DFC76008BAAA1 /* GTXPluginXCTestCase.h in Headers */,
61ABAECB204A0B0B006DBF0A /* GTXCheckBlock.h in Headers */,
+ 61284DD6211E42CF00F8FF29 /* GTXBlacklistBlock.h in Headers */,
61ABAEB9204A0B0B006DBF0A /* GTXChecking.h in Headers */,
+ 61284E0A211E45C600F8FF29 /* GTXBlacklistFactory.h in Headers */,
61ABAEBE204A0B0B006DBF0A /* GTXImageRGBAData.h in Headers */,
61ABAEB2204A0B0B006DBF0A /* GTXErrorReporter.h in Headers */,
61ABAEC3204A0B0B006DBF0A /* GTXTestCase.h in Headers */,
61ABAEB1204A0B0B006DBF0A /* GTXAnalytics.h in Headers */,
+ 61284DD7211E42CF00F8FF29 /* GTXBlacklisting.h in Headers */,
61A0C4E02061896300DF0169 /* GTXiLibCore.h in Headers */,
61A0C4DF2061896300DF0169 /* GTXiLib.h in Headers */,
61ABAECA204A0B0B006DBF0A /* GTXChecksCollection.h in Headers */,
@@ -280,6 +412,42 @@
productReference = 6115E786204F5BA2003E32F9 /* GTXiUnitTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
+ 61284DAC211E3F8300F8FF29 /* TestApp */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 61284DC2211E3F8600F8FF29 /* Build configuration list for PBXNativeTarget "TestApp" */;
+ buildPhases = (
+ 61284DA9211E3F8300F8FF29 /* Sources */,
+ 61284DAA211E3F8300F8FF29 /* Frameworks */,
+ 61284DAB211E3F8300F8FF29 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = TestApp;
+ productName = TestApp;
+ productReference = 61284DAD211E3F8300F8FF29 /* TestApp.app */;
+ productType = "com.apple.product-type.application";
+ };
+ 61284DDF211E442700F8FF29 /* FunctionalTests */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 61284DE7211E442800F8FF29 /* Build configuration list for PBXNativeTarget "FunctionalTests" */;
+ buildPhases = (
+ 61284DDC211E442700F8FF29 /* Sources */,
+ 61284DDD211E442700F8FF29 /* Frameworks */,
+ 61284DDE211E442700F8FF29 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ 61284E07211E448F00F8FF29 /* PBXTargetDependency */,
+ 61284DE6211E442800F8FF29 /* PBXTargetDependency */,
+ );
+ name = FunctionalTests;
+ productName = FunctionalTests;
+ productReference = 61284DE0211E442700F8FF29 /* FunctionalTests.xctest */;
+ productType = "com.apple.product-type.bundle.unit-test";
+ };
613C3F40204A09E7007D44A8 /* GTXiLib */ = {
isa = PBXNativeTarget;
buildConfigurationList = 613C3F49204A09E8007D44A8 /* Build configuration list for PBXNativeTarget "GTXiLib" */;
@@ -311,6 +479,15 @@
CreatedOnToolsVersion = 9.1;
ProvisioningStyle = Automatic;
};
+ 61284DAC211E3F8300F8FF29 = {
+ CreatedOnToolsVersion = 9.4.1;
+ ProvisioningStyle = Automatic;
+ };
+ 61284DDF211E442700F8FF29 = {
+ CreatedOnToolsVersion = 9.4.1;
+ ProvisioningStyle = Automatic;
+ TestTargetID = 61284DAC211E3F8300F8FF29;
+ };
613C3F40204A09E7007D44A8 = {
CreatedOnToolsVersion = 9.1;
ProvisioningStyle = Automatic;
@@ -323,6 +500,7 @@
hasScannedForEncodings = 0;
knownRegions = (
en,
+ Base,
);
mainGroup = 613C3F37204A09E7007D44A8;
productRefGroup = 613C3F42204A09E8007D44A8 /* Products */;
@@ -331,6 +509,8 @@
targets = (
613C3F40204A09E7007D44A8 /* GTXiLib */,
6115E785204F5BA2003E32F9 /* GTXiUnitTests */,
+ 61284DAC211E3F8300F8FF29 /* TestApp */,
+ 61284DDF211E442700F8FF29 /* FunctionalTests */,
);
};
/* End PBXProject section */
@@ -343,6 +523,21 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
+ 61284DAB211E3F8300F8FF29 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 61284DCC211E3FE400F8FF29 /* GTXTestViewController.xib in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 61284DDE211E442700F8FF29 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
613C3F3F204A09E7007D44A8 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
@@ -368,6 +563,37 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
+ 61284DA9211E3F8300F8FF29 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 61284DCD211E3FE400F8FF29 /* GTXTestAppDelegate.m in Sources */,
+ 61284DCE211E3FE400F8FF29 /* GTXTestStepperButton.m in Sources */,
+ 61284DCB211E3FE400F8FF29 /* GTXTestViewController.m in Sources */,
+ 61284DCF211E3FE400F8FF29 /* GTXTestApp.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 61284DDC211E442700F8FF29 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 61284E05211E447E00F8FF29 /* GTXTestGtxCanDetectFailures.m in Sources */,
+ 61284DFD211E447E00F8FF29 /* GTXTestGtxCanDetectFailuresInInheritedTests.m in Sources */,
+ 61284DFC211E447E00F8FF29 /* GTXTestGtxCanBlacklistTestCases.m in Sources */,
+ 61284E00211E447E00F8FF29 /* GTXTestBaseTest.m in Sources */,
+ 61284DFA211E447E00F8FF29 /* GTXTestFailingClassFailCheck.m in Sources */,
+ 61284E02211E447E00F8FF29 /* GTXTestAnalyticsIsTriggered.m in Sources */,
+ 61284DFF211E447E00F8FF29 /* GTXTestGtxWithDefaultChecks.m in Sources */,
+ 61284DFE211E447E00F8FF29 /* GTXTestGtxCanIgnoreElements.m in Sources */,
+ 61284DF9211E447E00F8FF29 /* GTXTestGtxWorksForPassingTests.m in Sources */,
+ 61284DFB211E447E00F8FF29 /* GTXTestAnalyticsBaseTest.m in Sources */,
+ 61284E04211E447E00F8FF29 /* GTXTestGtxCanIgnoreElementsOnSpecificCheck.m in Sources */,
+ 61284E03211E447E00F8FF29 /* GTXTestAnalyticsCanBeDisabled.m in Sources */,
+ 61284E01211E447E00F8FF29 /* GTXTestGtxCanWhitelistTestCases.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
613C3F3C204A09E7007D44A8 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
@@ -376,11 +602,13 @@
61ABAECC204A0B0B006DBF0A /* GTXErrorReporter.m in Sources */,
61ABAEB4204A0B0B006DBF0A /* GTXTestSuite.m in Sources */,
61ABAEB3204A0B0B006DBF0A /* GTXImageAndColorUtils.m in Sources */,
+ 61284E0B211E45C600F8FF29 /* GTXBlacklistFactory.m in Sources */,
61ABAEC2204A0B0B006DBF0A /* GTXToolKit.m in Sources */,
61ABAEC9204A0B0B006DBF0A /* GTXAnalytics.m in Sources */,
- 61ABAEBA204A0B0B006DBF0A /* GTXElementBlacklist.m in Sources */,
610CA3FE204DFC76008BAAA1 /* GTXPluginXCTestCase.m in Sources */,
+ 61284DDA211E437800F8FF29 /* GTXTestEnvironment.m in Sources */,
61ABAEB8204A0B0B006DBF0A /* GTXAnalyticsUtils.m in Sources */,
+ 61284DD5211E42CF00F8FF29 /* GTXBlacklistBlock.m in Sources */,
61ABAEBF204A0B0B006DBF0A /* NSError+GTXAdditions.m in Sources */,
61ABAEBC204A0B0B006DBF0A /* GTXAccessibilityTree.m in Sources */,
61ABAEC0204A0B0B006DBF0A /* GTXCheckBlock.m in Sources */,
@@ -398,6 +626,16 @@
target = 613C3F40204A09E7007D44A8 /* GTXiLib */;
targetProxy = 6115E78C204F5BA3003E32F9 /* PBXContainerItemProxy */;
};
+ 61284DE6211E442800F8FF29 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 61284DAC211E3F8300F8FF29 /* TestApp */;
+ targetProxy = 61284DE5211E442800F8FF29 /* PBXContainerItemProxy */;
+ };
+ 61284E07211E448F00F8FF29 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 613C3F40204A09E7007D44A8 /* GTXiLib */;
+ targetProxy = 61284E06211E448F00F8FF29 /* PBXContainerItemProxy */;
+ };
/* End PBXTargetDependency section */
/* Begin XCBuildConfiguration section */
@@ -425,6 +663,76 @@
};
name = Release;
};
+ 61284DC0211E3F8600F8FF29 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CODE_SIGN_STYLE = Automatic;
+ INFOPLIST_FILE = "$(SRCROOT)/Tests/FunctionalTests/TestApp/GTXTestApp-Info.plist";
+ IPHONEOS_DEPLOYMENT_TARGET = 11.4;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+ PRODUCT_BUNDLE_IDENTIFIER = com.google.gtx.dev.TestApp;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Debug;
+ };
+ 61284DC1211E3F8600F8FF29 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CODE_SIGN_STYLE = Automatic;
+ INFOPLIST_FILE = "$(SRCROOT)/Tests/FunctionalTests/TestApp/GTXTestApp-Info.plist";
+ IPHONEOS_DEPLOYMENT_TARGET = 11.4;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+ PRODUCT_BUNDLE_IDENTIFIER = com.google.gtx.dev.TestApp;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Release;
+ };
+ 61284DE8211E442800F8FF29 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ BUNDLE_LOADER = "$(TEST_HOST)";
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CODE_SIGN_STYLE = Automatic;
+ INFOPLIST_FILE = "Tests/FunctionalTests/TestApp/GTXTestApp-Info.plist";
+ IPHONEOS_DEPLOYMENT_TARGET = 11.4;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+ PRODUCT_BUNDLE_IDENTIFIER = com.google.gtx.dev.FunctionalTests;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ TARGETED_DEVICE_FAMILY = "1,2";
+ TEST_HOST = "$(BUILT_PRODUCTS_DIR)/TestApp.app/TestApp";
+ };
+ name = Debug;
+ };
+ 61284DE9211E442800F8FF29 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ BUNDLE_LOADER = "$(TEST_HOST)";
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CODE_SIGN_STYLE = Automatic;
+ INFOPLIST_FILE = "Tests/FunctionalTests/TestApp/GTXTestApp-Info.plist";
+ IPHONEOS_DEPLOYMENT_TARGET = 11.4;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+ PRODUCT_BUNDLE_IDENTIFIER = com.google.gtx.dev.FunctionalTests;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ TARGETED_DEVICE_FAMILY = "1,2";
+ TEST_HOST = "$(BUILT_PRODUCTS_DIR)/TestApp.app/TestApp";
+ };
+ name = Release;
+ };
613C3F47204A09E8007D44A8 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
@@ -585,6 +893,24 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
+ 61284DC2211E3F8600F8FF29 /* Build configuration list for PBXNativeTarget "TestApp" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 61284DC0211E3F8600F8FF29 /* Debug */,
+ 61284DC1211E3F8600F8FF29 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 61284DE7211E442800F8FF29 /* Build configuration list for PBXNativeTarget "FunctionalTests" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 61284DE8211E442800F8FF29 /* Debug */,
+ 61284DE9211E442800F8FF29 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
613C3F3B204A09E7007D44A8 /* Build configuration list for PBXProject "GTXiLib" */ = {
isa = XCConfigurationList;
buildConfigurations = (
diff --git a/Tests/FunctionalTests/TestApp/Sources/GTXTestViewController.m b/Tests/FunctionalTests/TestApp/Sources/GTXTestViewController.m
index b1e7268..2b67d4a 100644
--- a/Tests/FunctionalTests/TestApp/Sources/GTXTestViewController.m
+++ b/Tests/FunctionalTests/TestApp/Sources/GTXTestViewController.m
@@ -76,7 +76,8 @@
actionsToHandlers = [[NSMutableDictionary alloc] init];
[self.navigationController setNavigationBarHidden:YES animated:NO];
- [self axetest_addActionNamed:kAddNoLabelElementActionName handler:^(GTXTestViewController *sSelf) {
+ [self axetest_addActionNamed:kAddNoLabelElementActionName
+ handler:^(GTXTestViewController *sSelf) {
[sSelf axetest_addElementWithLabel:@""];
}];
[self axetest_addActionNamed:kAddPunctuatedLabelElementActionName
@@ -152,6 +153,7 @@
CGRect buttonFrame = newButton.frame;
buttonFrame.size.height = kMinimumElementSize;
newButton.frame = buttonFrame;
+ newButton.accessibilityIdentifier = name;
CGSize contentSize = self.actionsContainerView.contentSize;
buttonFrame.origin.y = contentSize.height + kMargin;
diff --git a/Tests/FunctionalTests/TestApp/TestSources/GTXTestBaseTest.h b/Tests/FunctionalTests/TestApp/TestSources/GTXTestBaseTest.h
index fec8e1a..641ac32 100644
--- a/Tests/FunctionalTests/TestApp/TestSources/GTXTestBaseTest.h
+++ b/Tests/FunctionalTests/TestApp/TestSources/GTXTestBaseTest.h
@@ -24,17 +24,17 @@
/**
Check that fails if the element is of Class @c GTXTestFailingClass.
*/
-id<GTXChecking> checkFailsIfFailingClass;
+extern id<GTXChecking> checkFailsIfFailingClass;
/**
Check that always passes.
*/
-id<GTXChecking> alwaysFail;
+extern id<GTXChecking> alwaysFail;
/**
Check that always fails.
*/
-id<GTXChecking> alwaysPass;
+extern id<GTXChecking> alwaysPass;
/**
Base test for all GTXiLib functional/integration tests used to setup GTXiLib and capture check
diff --git a/Tests/FunctionalTests/TestApp/TestSources/GTXTestBaseTest.m b/Tests/FunctionalTests/TestApp/TestSources/GTXTestBaseTest.m
index d0665a3..07d8c9f 100644
--- a/Tests/FunctionalTests/TestApp/TestSources/GTXTestBaseTest.m
+++ b/Tests/FunctionalTests/TestApp/TestSources/GTXTestBaseTest.m
@@ -19,6 +19,9 @@
#import "GTXTestViewController.h"
static NSInteger gFailureCount = 0;
+id<GTXChecking> checkFailsIfFailingClass;
+id<GTXChecking> alwaysFail;
+id<GTXChecking> alwaysPass;
@implementation GTXTestBaseTest
diff --git a/Tests/FunctionalTests/TestApp/TestSources/GTXTestGtxCanIgnoreElements.m b/Tests/FunctionalTests/TestApp/TestSources/GTXTestGtxCanIgnoreElements.m
index e3dc768..b39c3a2 100644
--- a/Tests/FunctionalTests/TestApp/TestSources/GTXTestGtxCanIgnoreElements.m
+++ b/Tests/FunctionalTests/TestApp/TestSources/GTXTestGtxCanIgnoreElements.m
@@ -15,6 +15,7 @@
//
#import "GTXTestBaseTest.h"
+#import "GTXBlacklistFactory.h"
#import "GTXiLib.h"
@interface GTXTestGtxCanIgnoreElements : GTXTestBaseTest
@@ -24,8 +25,9 @@
+ (void)setUp {
[super setUp];
+ NSString *className = NSStringFromClass([GTXTestFailingClass class]);
NSArray *blacklist =
- @[[GTXiLib blacklistForElementsOfClassNamed:NSStringFromClass([GTXTestFailingClass class])]];
+ @[[GTXBlacklistFactory blacklistWithClassName:className]];
[GTXiLib installOnTestSuite:[GTXTestSuite suiteWithAllTestsInClass:self]
checks:@[checkFailsIfFailingClass]
elementBlacklists:blacklist];
diff --git a/Tests/FunctionalTests/TestApp/TestSources/GTXTestGtxCanIgnoreElementsOnSpecificCheck.m b/Tests/FunctionalTests/TestApp/TestSources/GTXTestGtxCanIgnoreElementsOnSpecificCheck.m
index fafe612..8d3cde0 100644
--- a/Tests/FunctionalTests/TestApp/TestSources/GTXTestGtxCanIgnoreElementsOnSpecificCheck.m
+++ b/Tests/FunctionalTests/TestApp/TestSources/GTXTestGtxCanIgnoreElementsOnSpecificCheck.m
@@ -24,9 +24,10 @@
+ (void)setUp {
[super setUp];
+ NSString *className = NSStringFromClass([GTXTestFailingClass class]);
NSArray *blacklist =
- @[[GTXiLib blacklistForElementsOfClassNamed:NSStringFromClass([GTXTestFailingClass class])
- forCheckNamed:checkFailsIfFailingClass.name]];
+ @[[GTXBlacklistFactory blacklistWithClassName:className
+ checkName:checkFailsIfFailingClass.name]];
id<GTXChecking> secondFailingCheck = [GTXiLib checkWithName:@"secondFailingCheck"
block:^BOOL(id element, GTXErrorRefType errorOrNil) {
return ![element isKindOfClass:[GTXTestFailingClass class]];
diff --git a/Tests/FunctionalTests/TestApp/TestSources/GTXTestGtxWithDefaultChecks.m b/Tests/FunctionalTests/TestApp/TestSources/GTXTestGtxWithDefaultChecks.m
index 534d00d..20260f5 100644
--- a/Tests/FunctionalTests/TestApp/TestSources/GTXTestGtxWithDefaultChecks.m
+++ b/Tests/FunctionalTests/TestApp/TestSources/GTXTestGtxWithDefaultChecks.m
@@ -28,10 +28,16 @@
+ (void)setUp {
[super setUp];
+ NSString *notRedundantCheckName = [[GTXChecksCollection checkForAXLabelNotRedundantWithTraits]
+ name];
+ NSArray<id<GTXBlacklisting>> *blacklists = @[
+ [GTXBlacklistFactory blacklistWithAccessibilityIdentifier:kAddInaccessibleButton
+ checkName:notRedundantCheckName]
+ ];
// Install all the default checks on the current test class.
[GTXiLib installOnTestSuite:[GTXTestSuite suiteWithAllTestsInClass:self]
checks:[GTXChecksCollection allGTXChecks]
- elementBlacklists:@[]];
+ elementBlacklists:blacklists];
}
- (void)setUp {
diff --git a/Tests/UnitTests/GTXChecksCollectionTests.m b/Tests/UnitTests/GTXChecksCollectionTests.m
index 5c359f0..b209668 100644
--- a/Tests/UnitTests/GTXChecksCollectionTests.m
+++ b/Tests/UnitTests/GTXChecksCollectionTests.m
@@ -160,6 +160,61 @@
errorDescription:nil];
}
+- (void)testGtxCheckForAXLabelNotRedundantWithTraits {
+ // Label is not redundant with traits.
+ [self assertGtxCheck:[GTXChecksCollection checkForAXLabelNotRedundantWithTraits]
+ succeeds:YES
+ withElement:[self uiAccessibilityElementWithLabel:@"foo"
+ traits:UIAccessibilityTraitButton]
+ errorDescription:nil];
+ // Label is redundant with traits (uppercase).
+ [self assertGtxCheck:[GTXChecksCollection checkForAXLabelNotRedundantWithTraits]
+ succeeds:NO
+ withElement:[self uiAccessibilityElementWithLabel:@"FOO BUTTON"
+ traits:UIAccessibilityTraitButton]
+ errorDescription:nil];
+ // Label is redundant with traits (lowercase).
+ [self assertGtxCheck:[GTXChecksCollection checkForAXLabelNotRedundantWithTraits]
+ succeeds:NO
+ withElement:[self uiAccessibilityElementWithLabel:@"foo button"
+ traits:UIAccessibilityTraitButton]
+ errorDescription:nil];
+ // Label is not redundant with traits (not suffix).
+ [self assertGtxCheck:[GTXChecksCollection checkForAXLabelNotRedundantWithTraits]
+ succeeds:YES
+ withElement:[self uiAccessibilityElementWithLabel:@"button foo"
+ traits:UIAccessibilityTraitButton]
+ errorDescription:nil];
+ // Empty label (not redundant).
+ [self assertGtxCheck:[GTXChecksCollection checkForAXLabelNotRedundantWithTraits]
+ succeeds:YES
+ withElement:[self uiAccessibilityElementWithLabel:@""
+ traits:UIAccessibilityTraitButton]
+ errorDescription:nil];
+ // Whitespace label (not redundant).
+ [self assertGtxCheck:[GTXChecksCollection checkForAXLabelNotRedundantWithTraits]
+ succeeds:YES
+ withElement:[self uiAccessibilityElementWithLabel:@" "
+ traits:UIAccessibilityTraitButton]
+ errorDescription:nil];
+ // No traits or violating label (not redundant).
+ [self assertGtxCheck:[GTXChecksCollection checkForAXLabelNotRedundantWithTraits]
+ succeeds:YES
+ withElement:[self uiAccessibilityElementWithLabel:@"foo"]
+ errorDescription:nil];
+ // No traits (not redundant).
+ [self assertGtxCheck:[GTXChecksCollection checkForAXLabelNotRedundantWithTraits]
+ succeeds:YES
+ withElement:[self uiAccessibilityElementWithLabel:@"foo button"]
+ errorDescription:nil];
+ // Wrong traits (not redundant).
+ [self assertGtxCheck:[GTXChecksCollection checkForAXLabelNotRedundantWithTraits]
+ succeeds:YES
+ withElement:[self uiAccessibilityElementWithLabel:@"foo button"
+ traits:UIAccessibilityTraitStaticText]
+ errorDescription:nil];
+}
+
- (void)testGtxCheckForAXTraitsConflict {
NSString * const expectedErrorDescription =
@"Check \"Accessibility Traits Don't Conflict\" failed";
@@ -215,6 +270,17 @@
}
/**
+ * @return An accessibility element whose accessibility label is set to the specified @c label
+ * and accessibility trait is set to the specified @c traits.
+ */
+- (UIAccessibilityElement *)uiAccessibilityElementWithLabel:(id)label
+ traits:(UIAccessibilityTraits)traits {
+ UIAccessibilityElement *element = [self uiAccessibilityElementWithLabel:label];
+ element.accessibilityTraits = traits;
+ return element;
+}
+
+/**
* Asserts that the given GTXCheck succeeds or fails with the specified element.
*
* @param check The check to be tested.
@@ -234,9 +300,11 @@
XCTAssertNil(error);
} else {
XCTAssertNotNil(error);
- XCTAssertTrue([[error description] containsString:descriptionOrNil],
- @"[Expected] was not present in [Actual]!\n Expected: %@\n Actual: %@",
- descriptionOrNil, [error description]);
+ if (descriptionOrNil != nil) {
+ XCTAssertTrue([[error description] containsString:descriptionOrNil],
+ @"[Expected] was not present in [Actual]!\n Expected: %@\n Actual: %@",
+ descriptionOrNil, [error description]);
+ }
}
}
diff --git a/Tests/UnitTests/GTXImageAndColorUtilsTests.m b/Tests/UnitTests/GTXImageAndColorUtilsTests.m
index fedb2d6..f406032 100644
--- a/Tests/UnitTests/GTXImageAndColorUtilsTests.m
+++ b/Tests/UnitTests/GTXImageAndColorUtilsTests.m
@@ -129,7 +129,9 @@
CGFloat contrastRatioInImage =
[GTXImageAndColorUtils gtx_contrastRatioWithTextElementImage:imageWithRect
textElementColorShiftedImage:imageWithShiftedColorRect];
- XCTAssertEqualWithAccuracy(contrastRatioInImage, contrastRatioOfColors, kContrastRatioAccuracy);
+ XCTAssertEqualWithAccuracy(contrastRatioInImage,
+ contrastRatioOfColors,
+ kGTXContrastRatioAccuracy);
}
/**
diff --git a/Tests/UnitTests/GTXToolKitTests.m b/Tests/UnitTests/GTXToolKitTests.m
index 7712494..224f253 100644
--- a/Tests/UnitTests/GTXToolKitTests.m
+++ b/Tests/UnitTests/GTXToolKitTests.m
@@ -19,20 +19,27 @@
#import "GTXToolKit.h"
#import "GTXAnalytics.h"
+#import "GTXBlacklistFactory.h"
#import "GTXBaseTestCase.h"
-@interface GTXTestElementClass1 : NSObject
+@interface GTXTestElementClass1 : UIAccessibilityElement
@end
@implementation GTXTestElementClass1
@end
-@interface GTXTestElementClass2 : NSObject
+@interface GTXTestElementClass2 : UIAccessibilityElement
@end
@implementation GTXTestElementClass2
@end
+@interface GTXTestElementClass3 : UIAccessibilityElement
+@end
+
+@implementation GTXTestElementClass3
+@end
+
@interface GTXToolKitTests : GTXBaseTestCase
@end
@@ -104,7 +111,7 @@
XCTAssertTrue([toolkit checkAllElementsFromRootElements:@[root] error:&error]);
}
-- (void)testIgnoreElementAPIIgnoresElementsFromChecks {
+- (void)testBlacklistAPICanSkipElementsFromChecks {
GTXToolKit *toolkit = [[GTXToolKit alloc] init];
NSObject *failingElement = [self newAccessibleElement];
id<GTXChecking> check = [GTXToolKit checkWithName:@"Foo"
@@ -114,17 +121,23 @@
}];
[toolkit registerCheck:check];
XCTAssertFalse([toolkit checkElement:failingElement error:nil]);
- [toolkit ignoreElementsOfClassNamed:NSStringFromClass([failingElement class])];
+ [toolkit registerBlacklist:
+ [GTXBlacklistFactory blacklistWithClassName:NSStringFromClass([failingElement class])]];
XCTAssertTrue([toolkit checkElement:failingElement error:nil]);
}
-- (void)testIgnoreElementAPIIgnoresElementsFromSpecificChecks {
+- (void)testBlacklistAPICanSkipElementsFromSpecificChecks {
GTXTestElementClass1 *check1FailingElement = [[GTXTestElementClass1 alloc] init];
check1FailingElement.isAccessibilityElement = YES;
+ check1FailingElement.accessibilityIdentifier = @"check1FailingElement";
GTXTestElementClass2 *allChecksFailingElement = [[GTXTestElementClass2 alloc] init];
allChecksFailingElement.isAccessibilityElement = YES;
+ GTXTestElementClass3 *check3FailingElement = [[GTXTestElementClass3 alloc] init];
+ check3FailingElement.isAccessibilityElement = YES;
+ check3FailingElement.accessibilityIdentifier = @"check3FailingElement";
+
NSString *check1Name = @"Check 1";
NSString *check2Name = @"Check 2";
id<GTXChecking> check1 = [GTXToolKit checkWithName:check1Name
@@ -143,12 +156,26 @@
[toolkit1 registerCheck:check2];
XCTAssertFalse([toolkit1 checkElement:check1FailingElement error:nil]);
XCTAssertFalse([toolkit1 checkElement:allChecksFailingElement error:nil]);
+ XCTAssertFalse([toolkit1 checkElement:check3FailingElement error:nil]);
- [toolkit1 ignoreElementsOfClassNamed:NSStringFromClass([check1FailingElement class])];
+ [toolkit1 registerBlacklist:
+ [GTXBlacklistFactory blacklistWithAccessibilityIdentifier:@"check3FailingElement"
+ checkName:check1Name]];
+ XCTAssertFalse([toolkit1 checkElement:check1FailingElement error:nil]);
+ XCTAssertFalse([toolkit1 checkElement:allChecksFailingElement error:nil]);
+ XCTAssertTrue([toolkit1 checkElement:check3FailingElement error:nil]);
+
+ [toolkit1 registerBlacklist:
+ [GTXBlacklistFactory blacklistWithClassName:NSStringFromClass([check1FailingElement class])]];
+ [toolkit1 registerBlacklist:
+ [GTXBlacklistFactory blacklistWithClassName:NSStringFromClass([check1FailingElement class])]];
XCTAssertTrue([toolkit1 checkElement:check1FailingElement error:nil]);
XCTAssertFalse([toolkit1 checkElement:allChecksFailingElement error:nil]);
+ XCTAssertTrue([toolkit1 checkElement:check3FailingElement error:nil]);
- [toolkit1 ignoreElementsOfClassNamed:NSStringFromClass([allChecksFailingElement class])];
+ NSString *allChecksFailingElementClass = NSStringFromClass([allChecksFailingElement class]);
+ [toolkit1 registerBlacklist:
+ [GTXBlacklistFactory blacklistWithClassName:allChecksFailingElementClass]];
XCTAssertTrue([toolkit1 checkElement:allChecksFailingElement error:nil]);
}