contacts: fix contact creation and tests

This commit is contained in:
Gautier Pelloux-Prayer 2016-01-11 15:29:46 +01:00
parent de2066f71c
commit f4d25742c4
14 changed files with 62 additions and 126 deletions

View file

@ -24,8 +24,8 @@
typedef enum _ContactSections {
ContactSections_None = 0, // first section is empty because we cannot set header for first section
ContactSections_First_Name,
ContactSections_Last_Name,
ContactSections_FirstName,
ContactSections_LastName,
ContactSections_Sip,
ContactSections_Number,
ContactSections_Email,
@ -36,7 +36,6 @@ typedef enum _ContactSections {
@private
NSMutableArray *dataCache;
NSMutableArray *labelArray;
NSIndexPath *editingIndexPath;
}
@property(nonatomic, assign, setter=setContact:) ABRecordRef contact;

View file

@ -53,7 +53,7 @@
#pragma mark - Lifecycle Functions
- (void)initContactDetailsTableViewController {
INIT_WITH_COMMON_C {
dataCache = [[NSMutableArray alloc] init];
// pre-fill the data-cache with empty arrays
@ -66,22 +66,6 @@
[NSString stringWithString:(NSString *)kABPersonPhoneMobileLabel],
[NSString stringWithString:(NSString *)kABPersonPhoneIPhoneLabel],
[NSString stringWithString:(NSString *)kABPersonPhoneMainLabel], nil];
editingIndexPath = nil;
}
- (id)init {
self = [super init];
if (self) {
[self initContactDetailsTableViewController];
}
return self;
}
- (id)initWithCoder:(NSCoder *)decoder {
self = [super initWithCoder:decoder];
if (self) {
[self initContactDetailsTableViewController];
}
return self;
}
@ -93,10 +77,6 @@
#pragma mark -
- (void)updateModification {
[contactDetailsDelegate onModification:nil];
}
- (NSMutableArray *)getSectionData:(NSInteger)section {
if (section == ContactSections_Number) {
return [dataCache objectAtIndex:0];
@ -114,9 +94,9 @@
- (ABPropertyID)propertyIDForSection:(ContactSections)section {
switch (section) {
case ContactSections_First_Name:
case ContactSections_FirstName:
return kABPersonFirstNameProperty;
case ContactSections_Last_Name:
case ContactSections_LastName:
return kABPersonLastNameProperty;
case ContactSections_Sip:
return kABPersonInstantMessageProperty;
@ -482,7 +462,7 @@
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (section == ContactSections_First_Name || section == ContactSections_Last_Name) {
if (section == ContactSections_FirstName || section == ContactSections_LastName) {
return (self.tableView.isEditing) ? 1 : 0 /*no first and last name when not editting */;
} else {
return [[self getSectionData:section] count];
@ -496,19 +476,20 @@
cell = [[UIContactDetailsCell alloc] initWithIdentifier:kCellId];
[cell.editTextfield setDelegate:self];
}
cell.indexPath = indexPath;
NSMutableArray *sectionDict = [self getSectionData:[indexPath section]];
Entry *entry = [sectionDict objectAtIndex:[indexPath row]];
NSString *value = @"";
[cell hideDeleteButton:NO];
if (indexPath.section == ContactSections_First_Name) {
if (indexPath.section == ContactSections_FirstName) {
value = (NSString *)CFBridgingRelease(
ABRecordCopyValue(contact, [self propertyIDForSection:ContactSections_First_Name]));
ABRecordCopyValue(contact, [self propertyIDForSection:ContactSections_FirstName]));
[cell hideDeleteButton:YES];
} else if (indexPath.section == ContactSections_Last_Name) {
} else if (indexPath.section == ContactSections_LastName) {
value = (NSString *)CFBridgingRelease(
ABRecordCopyValue(contact, [self propertyIDForSection:ContactSections_Last_Name]));
ABRecordCopyValue(contact, [self propertyIDForSection:ContactSections_LastName]));
[cell hideDeleteButton:YES];
} else if ([indexPath section] == ContactSections_Number) {
ABMultiValueRef lMap = ABRecordCopyValue(contact, kABPersonPhoneProperty);
@ -565,30 +546,6 @@
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:NO];
NSMutableArray *sectionDict = [self getSectionData:[indexPath section]];
Entry *entry = [sectionDict objectAtIndex:[indexPath row]];
if ([self isEditing]) {
NSString *key = nil;
ABPropertyID property = [self propertyIDForSection:(ContactSections)indexPath.section];
if (property != kABInvalidPropertyType && property != kABPersonFirstNameProperty &&
property != kABPersonLastNameProperty) {
ABMultiValueRef lMap = ABRecordCopyValue(contact, property);
NSInteger index = ABMultiValueGetIndexForIdentifier(lMap, [entry identifier]);
NSString *labelRef = CFBridgingRelease(ABMultiValueCopyLabelAtIndex(lMap, index));
if (labelRef != NULL) {
key = (NSString *)(labelRef);
}
CFRelease(lMap);
}
if (key != nil) {
editingIndexPath = indexPath;
}
}
}
- (void)tableView:(UITableView *)tableView
commitEditingStyle:(UITableViewCellEditingStyle)editingStyle
forRowAtIndexPath:(NSIndexPath *)indexPath {
@ -648,10 +605,10 @@
NSString *text = nil;
BOOL canAddEntry = self.tableView.isEditing;
NSString *addEntryName = nil;
if (section == ContactSections_First_Name && self.tableView.isEditing) {
if (section == ContactSections_FirstName && self.tableView.isEditing) {
text = NSLocalizedString(@"First name", nil);
canAddEntry = NO;
} else if (section == ContactSections_Last_Name && self.tableView.isEditing) {
} else if (section == ContactSections_LastName && self.tableView.isEditing) {
text = NSLocalizedString(@"Last name", nil);
canAddEntry = NO;
} else if ([self getSectionData:section].count > 0 || self.tableView.isEditing) {
@ -711,40 +668,13 @@
forRowAtIndexPath:indexPath];
}
#pragma mark - ContactDetailsLabelDelegate Functions
- (void)changeContactDetailsLabel:(NSString *)value {
if (value != nil) {
NSInteger section = editingIndexPath.section;
NSMutableArray *sectionDict = [self getSectionData:section];
ABPropertyID property = [self propertyIDForSection:(int)section];
Entry *entry = [sectionDict objectAtIndex:editingIndexPath.row];
if (property != kABInvalidPropertyType) {
ABMultiValueRef lcMap = ABRecordCopyValue(contact, kABPersonPhoneProperty);
ABMutableMultiValueRef lMap = ABMultiValueCreateMutableCopy(lcMap);
CFRelease(lcMap);
NSInteger index = ABMultiValueGetIndexForIdentifier(lMap, [entry identifier]);
ABMultiValueReplaceLabelAtIndex(lMap, (__bridge CFStringRef)(value), index);
ABRecordSetValue(contact, kABPersonPhoneProperty, lMap, nil);
CFRelease(lMap);
}
[self.tableView beginUpdates];
[self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:editingIndexPath] withRowAnimation:FALSE];
[self.tableView reloadSectionIndexTitles];
[self.tableView endUpdates];
}
editingIndexPath = nil;
}
#pragma mark - UITextFieldDelegate Functions
- (BOOL)textField:(UITextField *)textField
shouldChangeCharactersInRange:(NSRange)range
replacementString:(NSString *)string {
if (contactDetailsDelegate != nil) {
[self performSelector:@selector(updateModification) withObject:nil afterDelay:0];
[contactDetailsDelegate onModification:nil];
}
return YES;
}
@ -756,26 +686,25 @@
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField {
UIView *view = [textField superview];
// Find TableViewCell
while (view != nil && ![view isKindOfClass:[UIContactDetailsCell class]])
view = [view superview];
if (view != nil) {
UIContactDetailsCell *cell = (UIContactDetailsCell *)view;
NSIndexPath *path = [self.tableView indexPathForCell:cell];
NSMutableArray *sectionDict = [self getSectionData:[path section]];
Entry *entry = [sectionDict objectAtIndex:[path row]];
// we cannot use indexPathForCell method here because if the cell is not visible anymore,
// it will return nil..
NSIndexPath *path = cell.indexPath; // [self.tableView indexPathForCell:cell];
ContactSections sect = (ContactSections)[path section];
ABPropertyID property = [self propertyIDForSection:sect];
NSString *value = [textField text];
NSMutableArray *sectionDict = [self getSectionData:[path section]];
Entry *entry = [sectionDict objectAtIndex:[path row]];
switch (sect) {
case ContactSections_First_Name:
case ContactSections_Last_Name: {
// [cell.detailTextLabel setText:[textField text]];
case ContactSections_FirstName:
case ContactSections_LastName: {
CFErrorRef error = NULL;
ABRecordSetValue(contact, property, (__bridge CFTypeRef)([textField text]), (CFErrorRef *)&error);
ABRecordSetValue(contact, property, (__bridge CFTypeRef)value, (CFErrorRef *)&error);
if (error != NULL) {
LOGE(@"Error when saving property %i in contact %p: Fail(%@)", property, contact,
[(__bridge NSError *)error localizedDescription]);
@ -805,15 +734,15 @@
LOGE(@"Not valid UIEditableTableViewCell");
}
if (contactDetailsDelegate != nil) {
[self performSelector:@selector(updateModification) withObject:nil afterDelay:0];
[contactDetailsDelegate onModification:nil];
}
return TRUE;
}
- (BOOL)isValid {
NSString *firstName = (NSString *)CFBridgingRelease(
ABRecordCopyValue(contact, [self propertyIDForSection:ContactSections_First_Name]));
NSString *lastName = (NSString *)CFBridgingRelease(
ABRecordCopyValue(contact, [self propertyIDForSection:ContactSections_Last_Name]));
ABRecordCopyValue(contact, [self propertyIDForSection:ContactSections_FirstName]));
NSString *lastName =
(NSString *)CFBridgingRelease(ABRecordCopyValue(contact, [self propertyIDForSection:ContactSections_LastName]));
return firstName.length > 0 || lastName.length > 0;
}
@ -829,8 +758,8 @@
}
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
if (section == 0 || (!self.tableView.isEditing &&
(section == ContactSections_First_Name || section == ContactSections_Last_Name))) {
if (section == 0 ||
(!self.tableView.isEditing && (section == ContactSections_FirstName || section == ContactSections_LastName))) {
return 1e-5;
}
return [self tableView:tableView viewForHeaderInSection:section].frame.size.height;

View file

@ -11,7 +11,7 @@
@implementation UIAssistantTextField
INIT_WITH_COMMON {
INIT_WITH_COMMON_CF {
self.delegate = self;
return self;
}

View file

@ -17,7 +17,7 @@ static NSString *const kDisappearAnimation = @"disappear";
@implementation UIBouncingView
INIT_WITH_COMMON {
INIT_WITH_COMMON_CF {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(settingsUpdate:)
name:kLinphoneSettingsUpdate

View file

@ -26,7 +26,7 @@
#pragma mark - Lifecycle Functions
INIT_WITH_COMMON {
INIT_WITH_COMMON_CF {
[self addTarget:self action:@selector(touchUp:) forControlEvents:UIControlEventTouchUpInside];
return self;
}

View file

@ -23,6 +23,10 @@
@interface UIContactDetailsCell : UITableViewCell
// this is broken design... but we need this to know which cell was modified
// last... must be totally revamped
@property(strong) NSIndexPath *indexPath;
@property(weak, nonatomic) IBOutlet UIView *defaultView;
@property(weak, nonatomic) IBOutlet UILabel *addressLabel;
@property(weak, nonatomic) IBOutlet UITextField *editTextfield;

View file

@ -12,7 +12,7 @@
@implementation UIIconButton
INIT_WITH_COMMON {
INIT_WITH_COMMON_CF {
[super setImage:[self imageForState:UIControlStateNormal]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
[super setImage:[self imageForState:UIControlStateDisabled]

View file

@ -14,7 +14,7 @@
UIView *borderView;
}
INIT_WITH_COMMON {
INIT_WITH_COMMON_CF {
borderView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
borderView.layer.borderWidth = 10;
borderView.layer.borderColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"color_A.png"]].CGColor;

View file

@ -39,7 +39,7 @@ static void audioRouteChangeListenerCallback(void *inUserData, // 1
[button update];
}
INIT_WITH_COMMON {
INIT_WITH_COMMON_CF {
AudioSessionInitialize(NULL, NULL, NULL, NULL);
OSStatus lStatus = AudioSessionAddPropertyListener(kAudioSessionProperty_AudioRouteChange,
audioRouteChangeListenerCallback, (__bridge void *)(self));

View file

@ -27,7 +27,7 @@
@synthesize waitView;
INIT_WITH_COMMON {
INIT_WITH_COMMON_CF {
last_update_state = FALSE;
return self;
}

View file

@ -252,7 +252,7 @@
@implementation UINavigationBarEx
INIT_WITH_COMMON {
INIT_WITH_COMMON_CF {
[self setTintColor:[LINPHONE_MAIN_COLOR adjustHue:5.0f / 180.0f saturation:0.0f brightness:0.0f alpha:0.0f]];
return self;
}

View file

@ -94,7 +94,7 @@ typedef enum {
/* Use that macro when you want to invoke a custom initialisation method on your class,
whatever is using it (xib, source code, etc., tableview cell) */
#define INIT_WITH_COMMON \
#define INIT_WITH_COMMON_C \
-(instancetype)init { \
self = [super init]; \
[self commonInit]; \
@ -105,9 +105,12 @@ typedef enum {
[self commonInit]; \
return self; \
} \
-(instancetype)commonInit
#define INIT_WITH_COMMON_CF \
-(instancetype)initWithFrame : (CGRect)frame { \
self = [super initWithFrame:frame]; \
[self commonInit]; \
return self; \
} \
-(instancetype)commonInit
INIT_WITH_COMMON_C

View file

@ -47,13 +47,13 @@
traits:UIAccessibilityTraitButton | UIAccessibilityTraitNotEnabled |
UIAccessibilityTraitSelected];
[self setText:firstName forIndex:0 inSection:ContactSections_First_Name];
[self setText:firstName forIndex:0 inSection:ContactSections_FirstName];
// entering text should enable the "edit" button
[tester waitForViewWithAccessibilityLabel:@"Edit" traits:UIAccessibilityTraitButton | UIAccessibilityTraitSelected];
if (lastName) {
[self setText:lastName forIndex:0 inSection:ContactSections_Last_Name];
[self setText:lastName forIndex:0 inSection:ContactSections_LastName];
}
if (phone) {
@ -70,17 +70,18 @@
- (void)tapCellForRowAtIndexPath:(NSInteger)idx inSection:(NSInteger)section atX:(CGFloat)x {
UITableView *tv = [self findTableView:@"Contact table"];
NSIndexPath *path = [NSIndexPath indexPathForRow:idx inSection:section];
UITableViewCell *last =
UITableViewCell *cell =
[tester waitForCellAtIndexPath:path inTableViewWithAccessibilityIdentifier:@"Contact table"];
XCTAssertNotNil(last);
XCTAssertNotNil(cell);
CGRect cellFrame = [last.contentView convertRect:last.contentView.frame toView:tv];
[tv tapAtPoint:CGPointMake(x > 0 ? x : cellFrame.size.width + x, cellFrame.origin.y + cellFrame.size.height / 2.)];
CGRect cellFrame = [cell.contentView convertRect:cell.contentView.frame toView:tv];
[tv tapAtPoint:CGPointMake(x > 0 ? x : tv.superview.frame.size.width + x,
cellFrame.origin.y + cellFrame.size.height / 2.)];
[tester waitForAnimationsToFinish];
}
- (void)tapRemoveButtonForRowAtIndexPath:(NSInteger)idx inSection:(NSInteger)section {
[self tapCellForRowAtIndexPath:idx inSection:section atX:-10];
[self tapCellForRowAtIndexPath:idx inSection:section atX:-7];
}
- (void)addEntries:(NSArray *)numbers inSection:(NSInteger)section {
@ -100,12 +101,12 @@
}
- (void)deleteContactEntryForRowAtIndexPath:(NSInteger)idx inSection:(NSInteger)section {
if ([tester tryFindingTappableViewWithAccessibilityLabel:@"Delete" error:nil]) {
[tester tapViewWithAccessibilityLabel:@"Delete"];
} else {
// hack: Travis seems to be unable to click on delete for what ever reason
// if ([tester tryFindingTappableViewWithAccessibilityLabel:@"Delete" error:nil]) {
// [tester tapViewWithAccessibilityLabel:@"Delete"];
// } else {
// hack: Travis seems to be unable to click on delete for what ever reason
[self tapRemoveButtonForRowAtIndexPath:idx inSection:section];
}
// }
}
#pragma mark - Tests
@ -129,7 +130,6 @@
[tester tapViewWithAccessibilityLabel:fullName traits:UIAccessibilityTraitStaticText];
[tester tapViewWithAccessibilityLabel:@"Edit"];
[tester scrollViewWithAccessibilityIdentifier:@"Contact table" byFractionOfSizeHorizontal:0 vertical:-0.9];
[tester tapViewWithAccessibilityLabel:@"Delete"];
[tester tapViewWithAccessibilityLabel:@"DELETE"];
@ -148,11 +148,11 @@
[tester tapViewWithAccessibilityLabel:@"Edit"];
// remove all numbers
for (NSInteger i = 0; i < phones.count; i++) {
[self tapRemoveButtonForRowAtIndexPath:0 inSection:ContactSections_Number];
[self deleteContactEntryForRowAtIndexPath:0 inSection:ContactSections_Number];
}
// remove all SIPs
for (NSInteger i = 0; i < SIPs.count; i++) {
[self tapRemoveButtonForRowAtIndexPath:0 inSection:ContactSections_Sip];
[self deleteContactEntryForRowAtIndexPath:0 inSection:ContactSections_Sip];
}
[tester tapViewWithAccessibilityLabel:@"Edit"];

View file

@ -10,6 +10,7 @@
#import <KIF/UIApplication-KIFAdditions.h>
#import "Utils.h"
#import "Log.h"
@interface LinphoneTestCase : KIFTestCase
@property BOOL invalidAccountSet;