text:
#import "SJActionUITests.h"
#import "SJActionUITurnSwitchesOnOff.h"
#import "SJActionUIIRDatabaseCommand.h"
#import "SJActionUIlearnedIRCommand.h"
#import "SJActionUIIRQuickstart.h"
#import "SJActionUIBack.h"
#import "TestMocks.h"
#import "TestEnables.h"

@implementation SJActionUITests
- (void)setUp
{
    [super setUp];

    // Set-up code here.
    savedDefaults = [[NSUserDefaults standardUserDefaults] dictionaryRepresentation];
    [[NSUserDefaults standardUserDefaults] setInteger:0 forKey:@"scanningStylePreference"];

}

- (void)tearDown
{
    // Tear-down code here.
    NSString *key;
    for(key in [savedDefaults allKeys]) {
        [[NSUserDefaults standardUserDefaults] setObject:[savedDefaults objectForKey:key] forKey:key];
    }
    [super tearDown];
    [HandyTestStuff logMemUsage];
}

#if RUN_ALL_ACTIONUI_TESTS
- (void)test_003_defineActionViewController_001_Initialization {
    [[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"supportSwitchamajigControllerPreference"];
    [[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"supportSwitchamajigIRPreference"];
    // Create and initialize with no friendly names or actions
    NSMutableArray *actions = [[NSMutableArray alloc] initWithCapacity:5];
    SwitchControlAppDelegate *dummy_app_delegate = [SwitchControlAppDelegate alloc];
    [dummy_app_delegate setFriendlyNameSwitchamajigDictionary:[[NSMutableDictionary alloc] initWithCapacity:5]];
    defineActionViewController *defineVC = [[defineActionViewController alloc] initWithActions:actions appDelegate:dummy_app_delegate];
    [defineVC loadView];
    // Confirm that currently have only "Default", and "No Action"
    STAssertTrue([defineVC->actionPicker numberOfRowsInComponent:0] == 1, @"With no friendly names, defineActionPicker should show only one value: 'Default'");
    STAssertTrue([defineVC->actionPicker numberOfRowsInComponent:1] == 2, @"With no drivers supported, defineActionPicker should show only two actions: 'No Action' and 'Back'");
    [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"supportSwitchamajigControllerPreference"];
    defineVC = [[defineActionViewController alloc] initWithActions:actions appDelegate:dummy_app_delegate];
    [defineVC loadView];
    STAssertTrue([defineVC->actionPicker numberOfRowsInComponent:1] == 4, @"With only controller supported, defineActionPicker should show four actions.");
    [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"supportSwitchamajigIRPreference"];
    defineVC = [[defineActionViewController alloc] initWithActions:actions appDelegate:dummy_app_delegate];
    [defineVC loadView];
    STAssertTrue([defineVC->actionPicker numberOfRowsInComponent:1] == 7, @"With both controller and IR supported, defineActionPicker shows %d actions.", [defineVC->actionPicker numberOfRowsInComponent:1]);

    STAssertTrue([defineVC->actionPicker selectedRowInComponent:0] == 0, @"Default value not selected when no friendly names");
    STAssertTrue([[defineVC pickerView:defineVC->actionPicker titleForRow:0 forComponent:0] isEqualToString:@"Default"], @"With no friendly names, defineActionPicker should show only one value: 'Default'");
    STAssertTrue([[defineVC pickerView:defineVC->actionPicker titleForRow:[defineVC->actionPicker selectedRowInComponent:1] forComponent:1] isEqualToString:@"No Action"], @"Must show 'No Action' when none defined in XML");
    SJActionUITurnSwitchesOn *turnSwitchesOnUI = [defineVC->actionNamesToSJActionUIDict objectForKey:@"Turn Switches On"];
    SJActionUITurnSwitchesOff *turnSwitchesOffUI = [defineVC->actionNamesToSJActionUIDict objectForKey:@"Turn Switches Off"];
    STAssertNotNil(turnSwitchesOnUI, @"Must have a turn switches on UI");
    STAssertNotNil(turnSwitchesOffUI, @"Must have a turn switches off UI");
    for(int i=0; i < 6; ++i) {
        STAssertTrue([turnSwitchesOnUI->switchButtons[i] isHidden], @"Switch on buttons not hidden for no action");
        STAssertTrue([turnSwitchesOffUI->switchButtons[i] isHidden], @"Switch off buttons not hidden for no action");
    }

    // Add a couple of names to the friendly list, and create a "switch on" action
    [[dummy_app_delegate friendlyNameSwitchamajigDictionary] setObject:@"dummy1" forKey:@"hoopy"];
    [[dummy_app_delegate friendlyNameSwitchamajigDictionary] setObject:@"dummy2" forKey:@"frood"];
    NSString *xmlString = @"<actionsequenceondevice><friendlyname>Default</friendlyname> <actionsequence> <turnSwitchesOn>1 3</turnSwitchesOn> </actionsequence></actionsequenceondevice>";
    NSError *xmlError;
    DDXMLDocument *document = [[DDXMLDocument alloc] initWithXMLString:xmlString options:0 error:&xmlError];
    if(xmlError)
        NSLog(@"XML error creating document: %@", xmlError);
    //NSLog(@"xmlString: %@", xmlString);
    //NSLog(@"document XMLString: %@", [document XMLString]);
    DDXMLNode *docChild = [[document children] objectAtIndex:0];
    //NSLog(@"actions count before = %d", [actions count]);
    [actions removeAllObjects];
    [actions addObject:docChild];
    //NSLog(@"actions count after = %d", [actions count]);
    //[actions addObject:[[document children] objectAtIndex:0]];
    //NSLog(@"docchild: %@", [docChild XMLString]);
    //NSLog(@"action[0]: %@", [[actions objectAtIndex:0] XMLString]);
    //DDXMLNode *arrayValue = [actions objectAtIndex:0];
    //NSLog(@"Value from array = %@", [arrayValue XMLString]);
    defineVC = [[defineActionViewController alloc] initWithActions:actions appDelegate:dummy_app_delegate];
    [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:(NSTimeInterval)0.1]];
    [defineVC loadView];
    STAssertTrue([defineVC->actionPicker numberOfRowsInComponent:0] == 3, @"With two friendly names, must have three values in picker including 'Default' Instead have %d", [defineVC->actionPicker numberOfRowsInComponent:0]);
    STAssertTrue([[defineVC pickerView:defineVC->actionPicker titleForRow:[defineVC->actionPicker selectedRowInComponent:0] forComponent:0] isEqualToString:@"Default"], @"Friendly name 'Default' not selected as specified in xml");
    STAssertTrue([[defineVC pickerView:defineVC->actionPicker titleForRow:[defineVC->actionPicker selectedRowInComponent:1] forComponent:1] isEqualToString:@"Turn Switches On"], @"'Turn Switches On' action not selected when in action sequence");
    int switchMask = 0;
    // Check mask and verify the buttons are visible
    turnSwitchesOnUI = [defineVC->actionNamesToSJActionUIDict objectForKey:@"Turn Switches On"];
    turnSwitchesOffUI = [defineVC->actionNamesToSJActionUIDict objectForKey:@"Turn Switches Off"];
    for(int i=0; i < 6; ++i) {
        STAssertFalse([turnSwitchesOnUI->switchButtons[i] isHidden], @"Switch on buttons hidden for switches on");
        STAssertTrue([turnSwitchesOffUI->switchButtons[i] isHidden], @"Switch off buttons not hidden for switches on");
        if([[turnSwitchesOnUI->switchButtons[i] backgroundColor] isEqual:[UIColor redColor]])
            switchMask |= (1 << i);
    }
    STAssertTrue(switchMask == 5, @"Switch mask wrong for turn switches on. Should be 5 instead is %d", switchMask);

    // Repeat for turn switches off
    xmlString = @"<actionsequenceondevice><friendlyname>frood</friendlyname> <actionsequence> <turnSwitchesOff>2 4 5 6</turnSwitchesOff> </actionsequence></actionsequenceondevice>";
    document = [[DDXMLDocument alloc] initWithXMLString:xmlString options:0 error:nil];
    [actions removeAllObjects];
    [actions addObject:[[document children] objectAtIndex:0]];
    defineVC = [[defineActionViewController alloc] initWithActions:actions appDelegate:dummy_app_delegate];
    [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:(NSTimeInterval)0.1]];
    [defineVC loadView];
    STAssertTrue([defineVC->actionPicker numberOfRowsInComponent:0] == 3, @"With two friendly names, must have three values in picker including 'Default'");
    STAssertTrue([[defineVC pickerView:defineVC->actionPicker titleForRow:[defineVC->actionPicker selectedRowInComponent:0] forComponent:0] isEqualToString:@"frood"], @"Friendly name 'frood' not selected as specified in xml");
    STAssertTrue([[defineVC pickerView:defineVC->actionPicker titleForRow:[defineVC->actionPicker selectedRowInComponent:1] forComponent:1] isEqualToString:@"Turn Switches Off"], @"'Turn Switches Off' action not selected when in action sequence");
    switchMask = 0;
    turnSwitchesOnUI = [defineVC->actionNamesToSJActionUIDict objectForKey:@"Turn Switches On"];
    turnSwitchesOffUI = [defineVC->actionNamesToSJActionUIDict objectForKey:@"Turn Switches Off"];
    for(int i=0; i < 6; ++i) {
        STAssertFalse([turnSwitchesOffUI->switchButtons[i] isHidden], @"Switch off buttons hidden for switches off");
        STAssertTrue([turnSwitchesOnUI->switchButtons[i] isHidden], @"Switch on buttons not hidden for switches off");
        if([[turnSwitchesOffUI->switchButtons[i] backgroundColor] isEqual:[UIColor redColor]])
            switchMask |= (1 << i);
    }
    STAssertTrue(switchMask == 58, @"Switch mask wrong for turn switches on. Should be 58 instead is %d", switchMask);

    // Confirm that complex action sequence is interpreted as no action
    xmlString = @"<actionsequenceondevice><friendlyname>frood</friendlyname> <actionsequence> <delay>1.0</delay><turnSwitchesOff>2 4 5 6</turnSwitchesOff> </actionsequence></actionsequenceondevice>";
    document = [[DDXMLDocument alloc] initWithXMLString:xmlString options:0 error:nil];
    [actions removeAllObjects];
    [actions addObject:[[document children] objectAtIndex:0]];
    defineVC = [[defineActionViewController alloc] initWithActions:actions appDelegate:dummy_app_delegate];
    [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:(NSTimeInterval)0.1]];
    [defineVC loadView];
    STAssertTrue([[defineVC pickerView:defineVC->actionPicker titleForRow:[defineVC->actionPicker selectedRowInComponent:1] forComponent:1] isEqualToString:@"No Action"], @"Must show 'No Action' when XML command is complex");
}

- (void)test_003_defineActionViewController_002_UpdateNoActionAndSwitches {
    [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"supportSwitchamajigControllerPreference"];
    [[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"supportSwitchamajigIRPreference"];
    // Create and initialize with no friendly names or actions
    NSMutableArray *actions = [[NSMutableArray alloc] initWithCapacity:5];
    SwitchControlAppDelegate *dummy_app_delegate = [SwitchControlAppDelegate alloc];
    [dummy_app_delegate setFriendlyNameSwitchamajigDictionary:[[NSMutableDictionary alloc] initWithCapacity:5]];
    [[dummy_app_delegate friendlyNameSwitchamajigDictionary] setObject:@"dummy1" forKey:@"hoopy"];
    defineActionViewController *defineVC = [[defineActionViewController alloc] initWithActions:actions appDelegate:dummy_app_delegate];
    [defineVC loadView];
    // Select Default and no action
    [defineVC->actionPicker selectRow:0 inComponent:0 animated:NO];
    [defineVC->actionPicker selectRow:0 inComponent:1 animated:NO];
    [defineVC pickerView:defineVC->actionPicker didSelectRow:0 inComponent:1];
    [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:(NSTimeInterval)0.1]];
    [defineVC->doneButton sendActionsForControlEvents:UIControlEventTouchUpInside];
    // There should now be an action
    STAssertTrue([actions count], @"Actions count isn't 1 with default sjig and no action");
    NSString *expectedAction = @"<actionsequenceondevice><friendlyname>Default</friendlyname><actionsequence></actionsequence></actionsequenceondevice>";
    NSString *actionString = [[actions objectAtIndex:0] XMLString];
    STAssertTrue([actionString isEqualToString:expectedAction], @"Actions string incorrect for noaction. Expected %@ but got %@", expectedAction, actionString);
    // Select different switchamajig and the turnswitcheson
    [defineVC->actionPicker selectRow:1 inComponent:0 animated:NO];
    [defineVC->actionPicker selectRow:2 inComponent:1 animated:NO];
    [defineVC pickerView:defineVC->actionPicker didSelectRow:1 inComponent:1];
    [defineVC->doneButton sendActionsForControlEvents:UIControlEventTouchUpInside];
    actionString = [[actions objectAtIndex:0] XMLString];
    expectedAction = @"<actionsequenceondevice><friendlyname>hoopy</friendlyname><actionsequence><turnSwitchesOn></turnSwitchesOn></actionsequence></actionsequenceondevice>";
    STAssertTrue([actionString isEqualToString:expectedAction], @"Actions string incorrect for turnswitcheson with no switches. Expected %@ but got %@", expectedAction, actionString);
    // Set a couple of switches
    SJActionUITurnSwitchesOn *turnSwitchesOnUI = [defineVC->actionNamesToSJActionUIDict objectForKey:@"Turn Switches On"];
    SJActionUITurnSwitchesOff *turnSwitchesOffUI = [defineVC->actionNamesToSJActionUIDict objectForKey:@"Turn Switches Off"];
    [turnSwitchesOnUI->switchButtons[0] sendActionsForControlEvents:UIControlEventTouchUpInside];
    [turnSwitchesOnUI->switchButtons[4] sendActionsForControlEvents:UIControlEventTouchUpInside];
    [defineVC->doneButton sendActionsForControlEvents:UIControlEventTouchUpInside];
    actionString = [[actions objectAtIndex:0] XMLString];
    expectedAction = @"<actionsequenceondevice><friendlyname>hoopy</friendlyname><actionsequence><turnSwitchesOn>1 5 </turnSwitchesOn></actionsequence></actionsequenceondevice>";
    STAssertTrue([actionString isEqualToString:expectedAction], @"Actions string incorrect for turnswitcheson with switches 1 and 4. Expected %@ but got %@", expectedAction, actionString);
    [defineVC->actionPicker selectRow:3 inComponent:1 animated:NO];
    [defineVC pickerView:defineVC->actionPicker didSelectRow:2 inComponent:1];
    [turnSwitchesOffUI->switchButtons[0] sendActionsForControlEvents:UIControlEventTouchUpInside];
    [turnSwitchesOffUI->switchButtons[4] sendActionsForControlEvents:UIControlEventTouchUpInside];
    [defineVC->doneButton sendActionsForControlEvents:UIControlEventTouchUpInside];
    actionString = [[actions objectAtIndex:0] XMLString];
    expectedAction = @"<actionsequenceondevice><friendlyname>hoopy</friendlyname><actionsequence><turnSwitchesOff>1 5 </turnSwitchesOff></actionsequence></actionsequenceondevice>";
    STAssertTrue([actionString isEqualToString:expectedAction], @"Actions string incorrect for turnswitchesoff with switches 1 and 4. Expected %@ but got %@", expectedAction, actionString);
    // Change switch selection
    [turnSwitchesOffUI->switchButtons[0] sendActionsForControlEvents:UIControlEventTouchUpInside];
    [turnSwitchesOffUI->switchButtons[1] sendActionsForControlEvents:UIControlEventTouchUpInside];
    [turnSwitchesOffUI->switchButtons[5] sendActionsForControlEvents:UIControlEventTouchUpInside];
    [defineVC->doneButton sendActionsForControlEvents:UIControlEventTouchUpInside];
    actionString = [[actions objectAtIndex:0] XMLString];
    expectedAction = @"<actionsequenceondevice><friendlyname>hoopy</friendlyname><actionsequence><turnSwitchesOff>2 5 6 </turnSwitchesOff></actionsequence></actionsequenceondevice>";
    STAssertTrue([actionString isEqualToString:expectedAction], @"Actions string incorrect for turnswitchesoff with switches 2, 5, and 6. Expected %@ but got %@", expectedAction, actionString);
}

- (void)test_003_defineActionViewController_003_IR {
    [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"supportSwitchamajigControllerPreference"];
    [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"supportSwitchamajigIRPreference"];
    // Make sure the IR controls aren't visible by default
    NSMutableArray *actions = [[NSMutableArray alloc] initWithCapacity:5];
    SwitchControlAppDelegate *dummy_app_delegate = [SwitchControlAppDelegate alloc];
    [dummy_app_delegate setFriendlyNameSwitchamajigDictionary:[[NSMutableDictionary alloc] initWithCapacity:5]];
    [[dummy_app_delegate friendlyNameSwitchamajigDictionary] setObject:@"dummy1" forKey:@"hoopy"];
    defineActionViewController *defineVC = [[defineActionViewController alloc] initWithActions:actions appDelegate:dummy_app_delegate];
    [defineVC loadView];
    SJActionUIIRDatabaseCommand *actionUI = [defineVC->actionNamesToSJActionUIDict objectForKey:@"IR from Database"];
    STAssertTrue([actionUI->irPicker isHidden] && [actionUI->irPickerLabel isHidden] && [actionUI->filterBrandButton isHidden] && [actionUI->filterFunctionButton isHidden] && [actionUI->testIrButton isHidden], @"IR UI is visible when no action is passed in");
    // Select IR command from action picker
    [defineVC->actionPicker selectRow:5 inComponent:1 animated:NO];
    [defineVC pickerView:defineVC->actionPicker didSelectRow:5 inComponent:1];
    STAssertFalse([actionUI->irPicker isHidden] || [actionUI->irPickerLabel isHidden] || [actionUI->filterBrandButton isHidden] || [actionUI->filterFunctionButton isHidden], @"IR UI not visible after selecting IR action.");
    STAssertTrue([actionUI->testIrButton isHidden], @"Test IR button visible with no IR devices connected");
    // Verify that we got the expected command
    NSString *expectedCommand = @"<actionsequenceondevice><friendlyname>Default</friendlyname><actionsequence><docommand key=\"0\" repeat=\"0\" seq=\"0\" command=\"Apple:Audio Accessory:UEI Setup Code 1115:PAUSE\" ir_data=\"UT111526\" ch=\"0\"></docommand></actionsequence></actionsequenceondevice>";
    [defineVC->doneButton sendActionsForControlEvents:UIControlEventTouchUpInside];
    DDXMLNode *action = [actions objectAtIndex:0];
    NSString *actualCommand = [action XMLString];
    STAssertTrue([actualCommand isEqualToString:expectedCommand], @"Actual command mismatches. Got %@", actualCommand);
    // Verify that more/fewer brands works
    int numBrands = [actionUI pickerView:actionUI->irPicker numberOfRowsInComponent:0];
    STAssertTrue(numBrands == 21, @"Num brands wrong when reduced list shown. Has %d brands.", numBrands);
    STAssertTrue([[actionUI->filterBrandButton titleForState:UIControlStateNormal] isEqualToString:@"Show More Brands"], @"Text wrong on show more brands");
    [actionUI->filterBrandButton sendActionsForControlEvents:UIControlEventTouchUpInside];
    STAssertTrue([[actionUI->filterBrandButton titleForState:UIControlStateNormal] isEqualToString:@"Show Fewer Brands"], @"Text wrong on show fewer brands");
    numBrands = [actionUI pickerView:actionUI->irPicker numberOfRowsInComponent:0];
    STAssertTrue(numBrands == 638, @"Num brands wrong when expanded list shown. Has %d brands.", numBrands);
    [actionUI->filterBrandButton sendActionsForControlEvents:UIControlEventTouchUpInside];
    STAssertTrue([[actionUI->filterBrandButton titleForState:UIControlStateNormal] isEqualToString:@"Show More Brands"], @"Text wrong on show more brands after activating toggle twice");
    numBrands = [actionUI pickerView:actionUI->irPicker numberOfRowsInComponent:0];
    STAssertTrue(numBrands == 21, @"Num brands wrong when reduced list reshown. Has %d brands.", numBrands);
    // Verify that more/fewer functions works
    int numFunctions = [actionUI pickerView:actionUI->irPicker numberOfRowsInComponent:3];
    STAssertTrue(numFunctions == 4, @"Num functions wrong when reduced list shown. Has %d functions.", numFunctions);
    STAssertTrue([[actionUI->filterFunctionButton titleForState:UIControlStateNormal] isEqualToString:@"Show More Functions"], @"Text wrong on show more functions");
    [actionUI->filterFunctionButton sendActionsForControlEvents:UIControlEventTouchUpInside];
    STAssertTrue([[actionUI->filterFunctionButton titleForState:UIControlStateNormal] isEqualToString:@"Show Fewer Functions"], @"Text wrong on show fewer functions");
    numFunctions = [actionUI pickerView:actionUI->irPicker numberOfRowsInComponent:3];
    STAssertTrue(numFunctions == 15, @"Num functions wrong when expanded list shown. Has %d functions.", numFunctions);
    [actionUI->filterFunctionButton sendActionsForControlEvents:UIControlEventTouchUpInside];
    STAssertTrue([[actionUI->filterFunctionButton titleForState:UIControlStateNormal] isEqualToString:@"Show More Functions"], @"Text wrong on show more functions after activating toggle twice");
    numFunctions = [actionUI pickerView:actionUI->irPicker numberOfRowsInComponent:3];
    STAssertTrue(numFunctions == 4, @"Num functions wrong when reduced list reshown. Has %d functions.", numFunctions);
    // Touch every wheel on the UI
    [actionUI->irPicker selectRow:1 inComponent:0 animated:NO];
    [actionUI pickerView:actionUI->irPicker didSelectRow:1 inComponent:0];
    expectedCommand = @"<actionsequenceondevice><friendlyname>Default</friendlyname><actionsequence><docommand key=\"0\" repeat=\"0\" seq=\"0\" command=\"Coby:DTA Converter:UEI Setup Code 2667:CHANNEL DOWN\" ir_data=\"UT26675\" ch=\"0\"></docommand></actionsequence></actionsequenceondevice>";
    [defineVC->doneButton sendActionsForControlEvents:UIControlEventTouchUpInside];
    action = [actions objectAtIndex:0];
    actualCommand = [action XMLString];
    STAssertTrue([actualCommand isEqualToString:expectedCommand], @"Command mismatches. Got %@", actualCommand);
    [actionUI->irPicker selectRow:2 inComponent:1 animated:NO];
    [actionUI pickerView:actionUI->irPicker didSelectRow:2 inComponent:1];
    expectedCommand = @"<actionsequenceondevice><friendlyname>Default</friendlyname><actionsequence><docommand key=\"0\" repeat=\"0\" seq=\"0\" command=\"Coby:DVD:Code Group 1:NEXT\" ir_data=\"P141f 1f26 7e1d 2595 018b 56a8 3032 b9a4 d95c 04e7 037b 83eb 5146 4643 5211 c619 f5d3 201b fc5c be57 a76a e9d5 ae7b 85a3 e2fd 670d 1b21 4432 ec1b b994 12df fcaa e2fd 670d 1b21 4432 ec1b b994 12df fcaa 9898 3e97 2ac3 90f9 5d0b 60b1 9030 2cee 9898 3e97 2ac3 90f9 5d0b 60b1 9030 2cee 5ef0 d152 e750 eb37 9785 838d 5f3b db42 6cb1 e039 98fa 9321 4a15 5627 fe87 486a 3c7c 84e2 390c 7b16 b638 3b12 6903 a545  \" ch=\"0\"></docommand></actionsequence></actionsequenceondevice>";
    [defineVC->doneButton sendActionsForControlEvents:UIControlEventTouchUpInside];
    action = [actions objectAtIndex:0];
    actualCommand = [action XMLString];
    STAssertTrue([actualCommand isEqualToString:expectedCommand], @"Command mismatches. Got %@", actualCommand);
    [actionUI->irPicker selectRow:1 inComponent:2 animated:NO];
    [actionUI pickerView:actionUI->irPicker didSelectRow:1 inComponent:2];
    expectedCommand = @"<actionsequenceondevice><friendlyname>Default</friendlyname><actionsequence><docommand key=\"0\" repeat=\"0\" seq=\"0\" command=\"Coby:DVD:Code Group 2:FORWARD\" ir_data=\"P9464 7681 617b 5328 b4a2 abdd e391 6116 d95c 04e7 037b 83eb 5146 4643 5211 c619 f5d3 201b fc5c be57 a76a e9d5 ae7b 85a3 e2fd 670d 1b21 4432 ec1b b994 12df fcaa e2fd 670d 1b21 4432 ec1b b994 12df fcaa d95c 04e7 037b 83eb 5146 4643 5211 c619 9898 3e97 2ac3 90f9 5d0b 60b1 9030 2cee e2fd 670d 1b21 4432 ec1b b994 12df fcaa 1c3b de22 9f02 46e7 a341 90a8 212c 9071 395d da19 85c7 ad30 ca0b e6c2 27e3 8562  \" ch=\"0\"></docommand></actionsequence></actionsequenceondevice>";
    [defineVC->doneButton sendActionsForControlEvents:UIControlEventTouchUpInside];
    action = [actions objectAtIndex:0];
    actualCommand = [action XMLString];
    STAssertTrue([actualCommand isEqualToString:expectedCommand], @"Command mismatches. Got %@", actualCommand);
    [actionUI->irPicker selectRow:1 inComponent:3 animated:NO];
    [actionUI pickerView:actionUI->irPicker didSelectRow:1 inComponent:3];
    expectedCommand = @"<actionsequenceondevice><friendlyname>Default</friendlyname><actionsequence><docommand key=\"0\" repeat=\"0\" seq=\"0\" command=\"Coby:DVD:Code Group 2:NEXT\" ir_data=\"Pa99a 533c fbc7 4574 b7cd 5bfe 1469 5e76 d95c 04e7 037b 83eb 5146 4643 5211 c619 f5d3 201b fc5c be57 a76a e9d5 ae7b 85a3 e2fd 670d 1b21 4432 ec1b b994 12df fcaa 4a1e 30e8 3e1c 8ea7 f51a fa30 6840 2414 9a09 e9c6 3593 4e7d d90b 9fd7 b774 9c96 9945 1207 d1e0 701d 533d bac8 e2ae d8bc 4a58 3f03 6eb4 4c41 8b69 06de 27bc 5281 65cb 7fa2 bc40 7e47 c758 d9a6 75be 1e10 310b 3e9d 126d d57c f98b d8d3 7504 1c7f  \" ch=\"0\"></docommand></actionsequence></actionsequenceondevice>";
    [defineVC->doneButton sendActionsForControlEvents:UIControlEventTouchUpInside];
    action = [actions objectAtIndex:0];
    actualCommand = [action XMLString];
    STAssertTrue([actualCommand isEqualToString:expectedCommand], @"Command mismatches. Got %@", actualCommand);
    [actionUI->irPicker selectRow:5 inComponent:4 animated:NO];
    [actionUI pickerView:actionUI->irPicker didSelectRow:1 inComponent:3];
    expectedCommand = @"<actionsequenceondevice><friendlyname>Default</friendlyname><actionsequence><docommand key=\"0\" repeat=\"5\" seq=\"0\" command=\"Coby:DVD:Code Group 2:NEXT\" ir_data=\"Pa99a 533c fbc7 4574 b7cd 5bfe 1469 5e76 d95c 04e7 037b 83eb 5146 4643 5211 c619 f5d3 201b fc5c be57 a76a e9d5 ae7b 85a3 e2fd 670d 1b21 4432 ec1b b994 12df fcaa 4a1e 30e8 3e1c 8ea7 f51a fa30 6840 2414 9a09 e9c6 3593 4e7d d90b 9fd7 b774 9c96 9945 1207 d1e0 701d 533d bac8 e2ae d8bc 4a58 3f03 6eb4 4c41 8b69 06de 27bc 5281 65cb 7fa2 bc40 7e47 c758 d9a6 75be 1e10 310b 3e9d 126d d57c f98b d8d3 7504 1c7f  \" ch=\"0\"></docommand></actionsequence></actionsequenceondevice>";
    [defineVC->doneButton sendActionsForControlEvents:UIControlEventTouchUpInside];
    action = [actions objectAtIndex:0];
    actualCommand = [action XMLString];
    STAssertTrue([actualCommand isEqualToString:expectedCommand], @"Command mismatches. Got %@", actualCommand);
    // Verify that testIR button appears when driver is present
    MockSwitchamajigIRDriver *driver = [[MockSwitchamajigIRDriver alloc] initWithHostname:@"localhost"];
    driver->commandsReceived = [[NSMutableArray alloc] initWithCapacity:5];
    [[dummy_app_delegate friendlyNameSwitchamajigDictionary] setObject:driver forKey:@"hoopy"];
    defineVC = [[defineActionViewController alloc] initWithActions:actions appDelegate:dummy_app_delegate];
    [defineVC loadView];
    actionUI = [defineVC->actionNamesToSJActionUIDict objectForKey:@"IR from Database"];
    //STAssertTrue([actionUI->testIrButton isHidden], @"Test IR button visible before IR driver selected");
    [defineVC->actionPicker selectRow:1 inComponent:0 animated:NO];
    [defineVC pickerView:defineVC->actionPicker didSelectRow:1 inComponent:0];
    STAssertFalse([actionUI->irPicker isHidden] || [actionUI->irPickerLabel isHidden] || [actionUI->filterBrandButton isHidden] || [actionUI->filterFunctionButton isHidden], @"IR UI not visible when initialized with IR action.");
    STAssertFalse([actionUI->testIrButton isHidden], @"Test IR button not visible after IR driver selected");
    [actionUI->testIrButton sendActionsForControlEvents:UIControlEventTouchUpInside];
    [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:(NSTimeInterval)0.1]];
    STAssertTrue([driver->commandsReceived count]==1, @"No command received for test IR command");
    expectedCommand = @"<docommand key=\"0\" repeat=\"5\" seq=\"0\" command=\"Coby:DVD:Code Group 2:NEXT\" ir_data=\"Pa99a 533c fbc7 4574 b7cd 5bfe 1469 5e76 d95c 04e7 037b 83eb 5146 4643 5211 c619 f5d3 201b fc5c be57 a76a e9d5 ae7b 85a3 e2fd 670d 1b21 4432 ec1b b994 12df fcaa 4a1e 30e8 3e1c 8ea7 f51a fa30 6840 2414 9a09 e9c6 3593 4e7d d90b 9fd7 b774 9c96 9945 1207 d1e0 701d 533d bac8 e2ae d8bc 4a58 3f03 6eb4 4c41 8b69 06de 27bc 5281 65cb 7fa2 bc40 7e47 c758 d9a6 75be 1e10 310b 3e9d 126d d57c f98b d8d3 7504 1c7f  \" ch=\"0\"></docommand>";
    actualCommand = [driver->commandsReceived objectAtIndex:0];
    STAssertTrue([actualCommand isEqualToString:expectedCommand], @"Command mismatch for test IR. Got %@", actualCommand);
}

- (void)test_003_defineActionViewController_004_IRLearning {
    [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"supportSwitchamajigControllerPreference"];
    [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"supportSwitchamajigIRPreference"];
    // Make sure the IR controls aren't visible by default
    NSMutableArray *actions = [[NSMutableArray alloc] initWithCapacity:5];
    SwitchControlAppDelegate *dummy_app_delegate = [SwitchControlAppDelegate alloc];
    [dummy_app_delegate setFriendlyNameSwitchamajigDictionary:[[NSMutableDictionary alloc] initWithCapacity:5]];
    [[dummy_app_delegate friendlyNameSwitchamajigDictionary] setObject:@"dummy1" forKey:@"hoopy"];
    defineActionViewController *defineVC = [[defineActionViewController alloc] initWithActions:actions appDelegate:dummy_app_delegate];
    [defineVC loadView];
    SJActionUIlearnedIRCommand *actionUI = [defineVC->actionNamesToSJActionUIDict objectForKey:@"Learned IR Command"];
    STAssertTrue([actionUI->learnedIrPicker isHidden] && [actionUI->learnedIRPickerLabel isHidden] && [actionUI->learningIRInstructionsLabel isHidden] && [actionUI->learnIRButton isHidden] && [actionUI->testLearnedIRButton isHidden], @"Learned IR UI is visible when no action is passed in");
    // Select IR command from action picker
    [defineVC->actionPicker selectRow:6 inComponent:1 animated:NO];
    [defineVC pickerView:defineVC->actionPicker didSelectRow:6 inComponent:1];
    STAssertFalse([actionUI->learnedIrPicker isHidden] || [actionUI->learnedIRPickerLabel isHidden], @"Learned IR UI not visible after selecting IR action.");
    STAssertTrue([actionUI->testLearnedIRButton isHidden], @"Test IR button visible with no IR devices connected");
    STAssertTrue([actionUI->learnIRButton isHidden], @"Learn IR button visible with no IR devices connected");
    STAssertTrue([actionUI->learningIRInstructionsLabel isHidden] /*&& [actionUI->learningIRCancelButton isHidden]*/ && [actionUI->learnIRImage isHidden], @"IR learning UI visible without activating IR learning");
    NSString *xmlCommandString = [actionUI XMLStringForAction];
    // With no commands, action should be nil
    STAssertNil(xmlCommandString, @"Should not have valid action when nothing has been learned");
    // Re-open the UI when a driver is present
    MockSwitchamajigIRDriver *driver = [[MockSwitchamajigIRDriver alloc] initWithHostname:@"localhost"];
    driver->commandsReceived = [[NSMutableArray alloc] initWithCapacity:5];
    [[dummy_app_delegate friendlyNameSwitchamajigDictionary] setObject:driver forKey:@"hoopy"];
    defineVC = [[defineActionViewController alloc] initWithActions:actions appDelegate:dummy_app_delegate];
    [defineVC loadView];
    [defineVC->actionPicker selectRow:6 inComponent:1 animated:NO];
    [defineVC pickerView:defineVC->actionPicker didSelectRow:6 inComponent:1];
    actionUI = [defineVC->actionNamesToSJActionUIDict objectForKey:@"Learned IR Command"];
    STAssertFalse([actionUI->testLearnedIRButton isHidden], @"Test Learned IR button not visible after IR driver selected");
    STAssertFalse([actionUI->learnIRButton isHidden], @"Learn IR button not visible after IR driver selected");
    // This is 1 only because of a workaround because returning 0 in ios6 crashes the app
    STAssertTrue([actionUI->learnedIrPicker numberOfRowsInComponent:0] == 1, @"Command present before IR learning");
    [actionUI->learnIRButton sendActionsForControlEvents:UIControlEventTouchUpInside];
    [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:(NSTimeInterval)0.1]];
    // Verify that the learn IR UI is now visible
    STAssertFalse([actionUI->learningIRInstructionsLabel isHidden] /*|| [actionUI->learningIRCancelButton isHidden]*/ || [actionUI->learnIRImage isHidden], @"IR learning UI not visible after pressing IR learning button");
    // Verify that other buttons are disabled
    STAssertFalse([defineVC->doneButton isUserInteractionEnabled] || [defineVC->cancelButton isUserInteractionEnabled] || [defineVC->cancelButton isUserInteractionEnabled] || [defineVC->actionPicker isUserInteractionEnabled] || [actionUI->testLearnedIRButton isUserInteractionEnabled], @"Rest of UI not disabled during IR learning");
    // Learn an IR command
    [dummy_app_delegate SwitchamajigIRDeviceDriverDelegateDidReceiveLearnedIRCommand:driver irCommand:@"L30 12d00 da0400da 92cc06d0 36f00da 29000da dbb213 23333333 33332333 33322323 33333332 32222332 32233320"];
    [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:(NSTimeInterval)0.5]];
    // Verify that the learn IR UI disappeared
    STAssertTrue([actionUI->learningIRInstructionsLabel isHidden] /*&& [actionUI->learningIRCancelButton isHidden]*/ && [actionUI->learnIRImage isHidden], @"Learned IR UI is visible after learned IR command arrived.");
    // Verify that rest of UI now enabled
    STAssertTrue([defineVC->doneButton isUserInteractionEnabled] && [defineVC->cancelButton isUserInteractionEnabled] && [defineVC->cancelButton isUserInteractionEnabled] && [defineVC->actionPicker isUserInteractionEnabled] && [actionUI->testLearnedIRButton isUserInteractionEnabled], @"UI not re-enabled after IR learning command arrived");
    // Verify that the IR picker now has a command
    STAssertTrue([actionUI->learnedIrPicker numberOfRowsInComponent:0] != 0, @"No command present after learned IR command arrived");
    STAssertTrue([actionUI->learnedIrPicker numberOfRowsInComponent:0] < 2, @"More than one command present after IR learning");
    // Confirm that command is correct
    [defineVC->doneButton sendActionsForControlEvents:UIControlEventTouchUpInside];
    xmlCommandString = [actionUI XMLStringForAction];
    NSString *expectedCommand = @"<docommand key=\"0\" repeat=\"0\" seq=\"0\" command=\"Learned:Learned IR Command 1\" ir_data=\"L30 12d00 da0400da 92cc06d0 36f00da 29000da dbb213 23333333 33332333 33322323 33333332 32222332 32233320\" ch=\"0\"></docommand>";
    STAssertTrue([xmlCommandString isEqualToString:expectedCommand], @"Actual command mismatches. Got %@", xmlCommandString);
    // Set the picker wheel to repeat five times
    [actionUI->learnedIrPicker selectRow:5 inComponent:1 animated:NO];
    [defineVC->doneButton sendActionsForControlEvents:UIControlEventTouchUpInside];
    xmlCommandString = [actionUI XMLStringForAction];

    expectedCommand = @"<docommand key=\"0\" repeat=\"5\" seq=\"0\" command=\"Learned:Learned IR Command 1\" ir_data=\"L30 12d00 da0400da 92cc06d0 36f00da 29000da dbb213 23333333 33332333 33322323 33333332 32222332 32233320\" ch=\"0\"></docommand>";
    STAssertTrue([xmlCommandString isEqualToString:expectedCommand], @"Actual command mismatches with repeat count = 5. Got %@", xmlCommandString);

    // Re-initialize the UI with with the command
    defineVC = [[defineActionViewController alloc] initWithActions:actions appDelegate:dummy_app_delegate];
    [defineVC loadView];
    actionUI = [defineVC->actionNamesToSJActionUIDict objectForKey:@"Learned IR Command"];
    xmlCommandString = [actionUI XMLStringForAction];
    STAssertTrue([xmlCommandString isEqualToString:expectedCommand], @"Command is wrong after reloading it. Got %@", xmlCommandString);
    // Confirm that picker is properly initialized
    int currentRepeatCount = [actionUI->learnedIrPicker selectedRowInComponent:1];
    STAssertTrue(currentRepeatCount == 5, @"Repeat count did not initialize correctly. Value is %d", currentRepeatCount);
}

- (void)test_003_defineActionViewController_005_QuickIR {
    [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"supportSwitchamajigControllerPreference"];
    [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"supportSwitchamajigIRPreference"];
    // Make sure the IR controls aren't visible by default
    NSMutableArray *actions = [[NSMutableArray alloc] initWithCapacity:5];
    MockSwitchControlDelegate *dummy_app_delegate = [MockSwitchControlDelegate alloc];
    dummy_app_delegate->irCodeSetToSend = nil;
    [dummy_app_delegate setFriendlyNameSwitchamajigDictionary:[[NSMutableDictionary alloc] initWithCapacity:5]];
    [[dummy_app_delegate friendlyNameSwitchamajigDictionary] setObject:@"dummy1" forKey:@"hoopy"];
    defineActionViewController *defineVC = [[defineActionViewController alloc] initWithActions:actions appDelegate:dummy_app_delegate];
    [defineVC loadView];
    [defineVC viewDidLoad];
    SJActionUIIRQuickstart *actionUI = [defineVC->actionNamesToSJActionUIDict objectForKey:@"Quickstart IR"];
    STAssertTrue([actionUI->irPicker isHidden] && [actionUI->irPickerLabel isHidden] && [actionUI->filterFunctionButton isHidden] && [actionUI->testIrButton isHidden], @"Quick IR UI is visible when no action is passed in");
    // Select Quick IR command from action picker
    [defineVC->actionPicker selectRow:4 inComponent:1 animated:NO];
    [defineVC pickerView:defineVC->actionPicker didSelectRow:4 inComponent:1];
    STAssertFalse([actionUI->irPicker isHidden] || [actionUI->irPickerLabel isHidden] || [actionUI->filterFunctionButton isHidden], @"IR UI not visible after selecting IR action.");
    STAssertTrue([actionUI->testIrButton isHidden], @"Test IR button visible with no IR devices connected");
    // Verify that we got the expected command
    NSString *expectedCommand = @"<actionsequenceondevice><friendlyname>Default</friendlyname><actionsequence><quickIrCommand><deviceType>TV</deviceType><function>POWER TOGGLE</function></quickIrCommand></actionsequence></actionsequenceondevice>";
    [defineVC->doneButton sendActionsForControlEvents:UIControlEventTouchUpInside];
    DDXMLNode *action = [actions objectAtIndex:0];
    NSString *actualCommand = [action XMLString];
    STAssertTrue([actualCommand isEqualToString:expectedCommand], @"Actual command mismatches. Got %@", actualCommand);
    // Verify that we have the right number of device types
    int numDeviceTypes = [actionUI pickerView:actionUI->irPicker numberOfRowsInComponent:0];
    STAssertTrue(numDeviceTypes == 3, @"Num device types wrong. Has %d device types.", numDeviceTypes);
    // Verify that more/fewer functions works
    int numFunctions = [actionUI pickerView:actionUI->irPicker numberOfRowsInComponent:1];
    STAssertTrue(numFunctions == 24, @"Num functions wrong when reduced list shown. Has %d functions.", numFunctions);
    STAssertTrue([[actionUI->filterFunctionButton titleForState:UIControlStateNormal] isEqualToString:@"Show More Functions"], @"Text wrong on show more functions");
    [actionUI->filterFunctionButton sendActionsForControlEvents:UIControlEventTouchUpInside];
    STAssertTrue([[actionUI->filterFunctionButton titleForState:UIControlStateNormal] isEqualToString:@"Show Fewer Functions"], @"Text wrong on show fewer functions");
    numFunctions = [actionUI pickerView:actionUI->irPicker numberOfRowsInComponent:1];
    STAssertTrue(numFunctions == 24, @"Num functions wrong when expanded list shown. Has %d functions.", numFunctions);
    [actionUI->filterFunctionButton sendActionsForControlEvents:UIControlEventTouchUpInside];
    STAssertTrue([[actionUI->filterFunctionButton titleForState:UIControlStateNormal] isEqualToString:@"Show More Functions"], @"Text wrong on show more functions after activating toggle twice");
    numFunctions = [actionUI pickerView:actionUI->irPicker numberOfRowsInComponent:1];
    STAssertTrue(numFunctions == 24, @"Num functions wrong when reduced list reshown. Has %d functions.", numFunctions);
    // Touch every wheel on the UI
    [actionUI->irPicker selectRow:1 inComponent:0 animated:NO];
    [actionUI pickerView:actionUI->irPicker didSelectRow:1 inComponent:0];
    expectedCommand = @"<actionsequenceondevice><friendlyname>Default</friendlyname><actionsequence><quickIrCommand><deviceType>Cable/Satellite</deviceType><function>POWER TOGGLE</function></quickIrCommand></actionsequence></actionsequenceondevice>";
    [defineVC->doneButton sendActionsForControlEvents:UIControlEventTouchUpInside];
    action = [actions objectAtIndex:0];
    actualCommand = [action XMLString];
    STAssertTrue([actualCommand isEqualToString:expectedCommand], @"Command mismatches. Got %@", actualCommand);
    [actionUI->irPicker selectRow:2 inComponent:1 animated:NO];
    [actionUI pickerView:actionUI->irPicker didSelectRow:2 inComponent:1];
    expectedCommand = @"<actionsequenceondevice><friendlyname>Default</friendlyname><actionsequence><quickIrCommand><deviceType>Cable/Satellite</deviceType><function>PLAY</function></quickIrCommand></actionsequence></actionsequenceondevice>";
    [defineVC->doneButton sendActionsForControlEvents:UIControlEventTouchUpInside];
    action = [actions objectAtIndex:0];
    actualCommand = [action XMLString];
    STAssertTrue([actualCommand isEqualToString:expectedCommand], @"Command mismatches. Got %@", actualCommand);
    // Verify setActions
    expectedCommand = @"<quickIrCommand><deviceType>DVD/Blu Ray</deviceType><function>PAUSE</function></quickIrCommand>";
    DDXMLDocument *initialActionDoc = [[DDXMLDocument alloc] initWithXMLString:expectedCommand options:0 error:nil];
    DDXMLNode *initialActionNode = [[initialActionDoc children] objectAtIndex:0];
    STAssertTrue([actionUI setAction:initialActionNode], @"Quick start UI doesn't recognize action");
    actualCommand = [actionUI XMLStringForAction];
    STAssertTrue([actualCommand isEqualToString:expectedCommand], @"Command mismatches. Got %@", actualCommand);

    // Verify that testIR button appears when driver is present
    MockSwitchamajigIRDriver *driver = [[MockSwitchamajigIRDriver alloc] initWithHostname:@"localhost"];
    driver->commandsReceived = [[NSMutableArray alloc] initWithCapacity:5];
    [[dummy_app_delegate friendlyNameSwitchamajigDictionary] setObject:driver forKey:@"hoopy"];
    defineVC = [[defineActionViewController alloc] initWithActions:actions appDelegate:dummy_app_delegate];
    [defineVC loadView];
    actionUI = [defineVC->actionNamesToSJActionUIDict objectForKey:@"Quickstart IR"];
    //STAssertTrue([actionUI->testIrButton isHidden], @"Test IR button visible before IR driver selected");
    [defineVC->actionPicker selectRow:1 inComponent:0 animated:NO];
    [defineVC pickerView:defineVC->actionPicker didSelectRow:1 inComponent:0];
    STAssertFalse([actionUI->testIrButton isHidden], @"Test IR button not visible after IR driver selected");
    dummy_app_delegate->irCodeSetToSend = @"All Models";
    [actionUI->testIrButton sendActionsForControlEvents:UIControlEventTouchUpInside];
    [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:(NSTimeInterval)0.1]];
    STAssertTrue([driver->commandsReceived count]==1, @"No command received for test IR command");
    expectedCommand = @"<docommand key=\"0\" repeat=\"1\" seq=\"0\" command=\"0\" ir_data=\"Pedc4 89d6 7d56 a9c8 a757 0d59 5a57 6131 69ad f67f 1603 f1f0 03f1 8e2e 91d6 dc80 1cdd f511 21fa 5dd2 c024 97e3 d947 3a3e 1cdd f511 21fa 5dd2 c024 97e3 d947 3a3e 69ad f67f 1603 f1f0 03f1 8e2e 91d6 dc80 1cdd f511 21fa 5dd2 c024 97e3 d947 3a3e 915c 0451 0974 21e5 9629 07aa 26af 1aa7 bf23 820c c3fd c3ea 054c 350c 9fe1 2b02 1cdd f511 21fa 5dd2 c024 97e3 d947 3a3e 1cdd f511 21fa 5dd2 c024 97e3 d947 3a3e 11b4 6bc6 beac b29a 1d62 6584 cd9a 8f1e bf23 820c c3fd c3ea 054c 350c 9fe1 2b02 28bc 7199 bf62 289d 84f6 24d6 e8ae add2  \" ch=\"0\"></docommand>";
    actualCommand = [driver->commandsReceived objectAtIndex:0];
    STAssertTrue([actualCommand isEqualToString:expectedCommand], @"Command mismatch for test IR. Got %@", actualCommand);
}

- (void)test_003_defineActionViewController_006_Back {
    [[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"supportSwitchamajigControllerPreference"];
    [[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"supportSwitchamajigIRPreference"];
    // Create and initialize with no friendly names or actions
    NSMutableArray *actions = [[NSMutableArray alloc] initWithCapacity:5];
    SwitchControlAppDelegate *dummy_app_delegate = [SwitchControlAppDelegate alloc];
    defineActionViewController *defineVC = [[defineActionViewController alloc] initWithActions:actions appDelegate:dummy_app_delegate];
    [defineVC loadView];
    // Select Default and Back
    [defineVC->actionPicker selectRow:0 inComponent:0 animated:NO];
    [defineVC->actionPicker selectRow:1 inComponent:1 animated:NO];
    [defineVC pickerView:defineVC->actionPicker didSelectRow:1 inComponent:1];
    [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:(NSTimeInterval)0.1]];
    [defineVC->doneButton sendActionsForControlEvents:UIControlEventTouchUpInside];
    // There should now be an action
    STAssertTrue([actions count], @"Actions count isn't 1 with default sjig and back");
    NSString *expectedAction = @"<actionsequenceondevice><friendlyname>Default</friendlyname><actionsequence><back></back></actionsequence></actionsequenceondevice>";
    NSString *actionString = [[actions objectAtIndex:0] XMLString];
    STAssertTrue([actionString isEqualToString:expectedAction], @"Actions string incorrect for noaction. Expected %@ but got %@", expectedAction, actionString);
    // Confirm that the app delegate pops the nav controller when it gets this command
    MockNavigationController *navController = [[MockNavigationController alloc] init];
    navController->didReceivePopToRootViewController = false;
    DDXMLDocument *initialActionDoc = [[DDXMLDocument alloc] initWithXMLString:expectedAction options:0 error:nil];
    DDXMLNode *initialActionNode = [[initialActionDoc children] objectAtIndex:0];
    [dummy_app_delegate setNavigationController:navController];
    [dummy_app_delegate performActionSequence:initialActionNode];
    [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:(NSTimeInterval)0.1]];
    STAssertTrue(navController->didReceivePopToRootViewController, @"Back action did not cause app delegate to pop the navigation controller");
    SJActionUIBack *back = [[SJActionUIBack alloc] init];
    DDXMLDocument *backActionDoc = [[DDXMLDocument alloc] initWithXMLString:@"<back></back>" options:0 error:nil];
    DDXMLNode *backActionNode = [[backActionDoc children] objectAtIndex:0];
    STAssertTrue([back setAction:backActionNode], @"Back action didn't accept xml node");
}

#endif // RUN_ALL_ACTIONUI_TESTS
@end

redpajama_set_name: RedPajamaGithub


Hi! I'm Tyffanie, a Spanish-speaking Registered Dietitian Nutritionist.
My mission is to empower you to achieve digestive wellness.
I will help you feel the best you can while eating the foods you love!
I help manage a variety of conditions that affect the digestive tract. You may be experiencing some unpleasant symptoms that make it hard to lead the life you want.
By working one-on-one with me, we'll figure out the cause of your discomfort and discover what foods make you feel good. I'll also teach you how to manage symptoms when they arise. Together, we'll identify the steps you can take to feel like your best self.
I also work with women who have gastrointestinal symptoms during or after pregnancy. Some women may even want to get their symptoms under control before getting pregnant.
Let's work together to maximize your health and minimize digestive discomfort.
1. Let's Connect. We'll grab a virtual coffee and chat. We will talk about your symptoms and your health goals. I will share how I can help you make sustainable changes to achieve those goals. Then, we'll figure out which of my packages best suits your needs.
2. First Session. In our initial session, I'll do a full nutrition assessment to better understand you. We will dig deep into what you have been experiencing and how it's affecting your life. Together, we'll hone in on your goals and come up with a plan for achieving them.
3. Follow-up Sessions. We'll check in with each other at defined intervals to see how things are going. This will give your body some time to respond to the changes. We'll also address challenges you are facing and tweak the plan as needed to help you meet your goals.


text:
What is great about ourselves
Pankaj Mishra writes: Is it finally closing time in the gardens of the West? The wails that have rent the air since the Brexit vote and Trump's victory rise from the same parts of Anglo-America that hosted, post-1989, the noisiest celebrations of liberalism, democracy, free markets and globalisation. Edward Luce, a Financial Times columnist based in Washington DC, isn't sure 'whether the Western way of life, and our liberal democratic systems, can survive'. Many commentators now share the view of Bill Emmott, the former editor of the Economist, who writes in his new book that we are 'present at the destruction' of 'the West', the 'world's most successful political idea'. Donald Trump has also chimed in, asking 'whether the West has the will to survive'. These apocalyptic Westernists long to turn things around, to make their shattered world whole again. David Goodhart, the founding editor of Prospect, told the New York Times just before the general election that he believed Theresa May could dominate British politics for a generation. Mark Lilla, a professor at Columbia and a regular contributor to the New York Review of Books, wants the Democratic Party, which under Bill Clinton captured 'Americans' imaginations about our shared destiny', to abandon identity politics and help liberalism become once more a 'unifying force' for the 'common good'. Douglas Murray, associate editor of the Spectator, thinks that Trump might just save Western civilisation.
The ideas and commitments of the new prophets of decline do not emerge from any personal experience of it, let alone adversity of the kind suffered by many voters of Brexit and Trump. These men were ideologically formed during the reign of Reagan and Thatcher, and their influence and prestige have grown in step with the expansion of Anglo-America's intellectual and cultural capital. Lilla, a self-declared 'centrist liberal', arrived at his present position by way of working-class Detroit, evangelical Christianity and an early flirtation with neoconservatism. The British writers belong to a traditional elite; shared privilege transcends ideological discrepancies between centrist liberalism and nativism, the Financial Times and the Spectator. Murray and Goodhart were educated at Eton; the fathers of both Luce and Goodhart were Conservative MPs; and all three went to Oxford. Inhabitants of a transatlantic ecosystem of corporate philanthropy, think-tanks and high-altitude conclaves, they can also be found backslapping in the review pages and on Twitter: Murray calls Goodhart's writing 'superb' and Luce's 'beautiful'; Emmott thanks Murray for his 'nice' review in the Times. [Continue reading…]
This entry was posted in Analysis on September 17, 2017 by News Sources.
← Aid group warns of lives at risk among Rohingya in Bangladesh Conflicting statements on Trump administration's position on Paris climate accord →

redpajama_set_name: RedPajamaCommonCrawl


There was an "unprecedented contraction" in 2016 and 2015 in face of stubbornly low energy prices, the organisation says.
(AFP) Investment in the oil and gas industry will see a tentative recovery in 2017 after an "unprecedented contraction" in 2016 and 2015 in face of stubbornly low energy prices, the International Energy Agency said in a report on Tuesday.
The IEA said upstream oil and gas investment -- such as in exploration and production facilities -- fell 26 percent in 2016 in nominal terms to $434 billion (€380 billion), similar to the decline seen 2015.
The IEA, an intergovernmental group set up to ensure the reliable supply of energy, released the report at the World Petroleum Congress in Istanbul, where energy bosses are debating the consequences of the dramatic plunge in oil prices.
Participants have warned that the sharply lower investment levels seen in the last two years risk compromising security of supply for consumers, as discoveries and development of new oilfields falter.
According to the IEA, investment in oil and gas in 2016 was little more than "half the peak level of 2014, when oil prices started to fall sharply."
It described the fall in investment in 2015 and 2016 totalling $345 billion as "an unprecedented contraction" and was partly due to reduced drilling activity.
But asking whether there could now be "light at the end of the tunnel", it said that the oil industry has reacted to the price crisis by drastically ramping up efficiency.
This improved the financial health of companies and their cash flow, creating the chance of a slight recovery in investment in 2017.
It estimated, on the basis of company announcements, that global oil and gas upstream investment in 2017 is set to increase by almost six per cent to just below $460 billion in nominal terms.
"Many of the largest oil and gas companies are still implementing a cautious approach in scaling up their spending plans," the IEA said.
It said that firms would be less ambitious in their planning were oil to fail to recover to above $50 a barrel.


Cape Town, South Africa: so far, 2018 is delivering a mother load of touring bands to our humble shoreline. Another on that list is Californian metalcore band called Secrets, playing three dates in April.
Of course, this is not to say that changes come easy, as Richard's longest cohort in the band and founding member Michael Sherman departed from Secrets in recent months owing to growing commitments at home. This album will serve as something of a legacy.
For present members, Secrets is conquering the world. Whilst the Northern Hemisphere, even including parts of Asia, is becoming familiar touring territory, 2018 sees conquest into the South. The band's arrival in South Africa is the first time in the continent, and the Secrets album tour will include other Southern Hemisphere shows in Australia and New Zealand.
Tickets prices range from R170 – R190 from webtickets and R250 at the door.


This beautiful stallion is pure southern. Terrific gait, brio, strength and arrogance. His foals are look-alikes, very strong and show class quality, capable of being foundation breeding horses for any ranch. We have 23 of his foals on the ranch many of which will be in our 2007 show string. He is the best breeding stallion we have ever seen. Watch for his oldest son DrB Vivido a palomino .
Rocky Mountain Peruvian Show Bosal Winner.
Our first imported stallion from Peru. He has the lineage of Jose and Edwardo Risso, and Alfredo Elias.
This is a beautiful, strong, athletic stallion with the looseness in his shoulders of the JRM lineage and the strength and beauty of the Elias lineage. His offspring are very similar. We have 14 of his foals on the ranch many of whom will be in our 2007 showstring.
This grey stallion, with black mane and tail, may be the most beautiful of any grey Peruvian stallion we have seen in the U.S. or Peru. His beauty, arrogance and gait, induce statements like- "When I saw him, chills went through me!" or, "He is the most beautiful Peruvian horse I have seen!"
His get are all grey, tall and beautiful with excellent gait.
This great-grandson of the famous Mantequilla (Peru) is a golden palomino as his father, grandfather, great-grandfather were.
He has a superb gait, arrogance, strength and beauty with a calm easy to handle behavior.
mannered and strong. Terrific for show, trail or breeding.
This outcross stallion brings together the strength of Piloto with the looseness and reach of LV Sol Brilliante who was the last laureado breeding stallion at the Peruvian National Show. He has won many bosal stallion awards and was 2nd place at the 2006 National Show. We are crossing him with several of our better mares. Watch for him in the show ring in 2007.


text:
Q: Re-Exporting entire module in ES6/Babel Let's say I have a module I want to re-export:
//exportme.js
export default 'EXPORTME';
export const test = () => console.log('test function');

//reexport.js
export * from './exportme.js'

When I import reexport.js, the default from exportme.js is not available.
//app.js
import reexport from './reexport.js'

console.log(reexport) //undefined

I have to make reexport.js to be the following for it to work.
export * from './exportme.js'
export default from './exportme.js'

Is there an easier way to do this or can this be consolidated into one statement?
export default, * from './exportme.js' does not work.
I am using latest babel with transform-export-extensions

A:
The default from exportme.js is not available

Yes, default exports are not re-exported by star exports. The purpose of export * from … is to allow re-exports from multiple modules, exporting the default from multiple modules would only lead to collisions. You therefore have to specifiy it explicitly (if you need it at all, often there is no default export alongside named exports).

Is there an easier way to do this or can this be consolidated into one statement?

No, the two lines you have are the way to go.

A: As Bergi wrote, there is no way to do this in one line using ES 6 exports. You can, however, simply require the module you want to re-export and assign the result to module.exports:
module.exports = require('./exportme.js')

redpajama_set_name: RedPajamaStackExchange


We are looking to start a super chill, weekly soccer pick-up game for women & non-binary people. Not super competitive, just an hour or so of easy soccer with however many people show up. We will provide a ball, cones, & small goals, but if you have any supplies you want to bring, please do!
Games will be on Mondays at 6pm.
We are two roommates living in Boston who have both played soccer in our lives, but no longer do competitively. We love exercise, poetry, tattoos, art, & film, and want to make soccer a part of our weekly schedule!


I can't tell you how often my patients present their food addictions to me as though it were nothing more than a lack of discipline. Yet no one would look at a meth-head as someone who could just use a little more willpower—we would likely all agree that this was a full-blown addiction and an extremely dangerous problem. We would probably immediately suggest he get some help and wouldn't dream of merely suggesting he just cut back a little. With food addiction, however, the problem is rarely taken as seriously and the suggestion to go on a diet is often handed out with a condescending shrug. Problems with drugs and alcohol are just more pronounced than problems with food, and we can probably attribute that to both legality and safety issues. Drugs and alcohol are mind-altering substances, and, yes, you could die the first time you try them. Binge-eating, however, is a beast that is likely get you over time, and, no you're not likely to drop dead on a weekend-long McDonalds bender. What do they have in common, however? Our ultimate indulgences do serve a function. In my work I see it almost daily, the very undeniable underlying reason for addiction: Avoidance. If you're struggling with addiction—any addiction—I'm sorry to be the one to tell you this, but there's something going on in your life and mind that you're simply not dealing with.
People don't realize how their vices con them into thinking they're happy. One of the big warning signs I often listen out for is any derivative of a 'can't complain' statement as a response when I ask friends how they're doing. Some people are happy. Some people are seemingly happy. Some people are unhappy. Some people are downright miserable. The miserable ones are fairly easy to spot. The quieter ones are the ones who often slip through the cracks. You might misread a slight vacancy in their eyes as a sign of a previously bad night's sleep but not realize that your friend is experiencing well-masked pain. The truth is we simply don't know what our friends are doing behind closed doors. Whether they're eating too much, spending too much, smoking too much, over-exercising, or even dipping their toes into darker pools such as self-mutilation, we really just don't know. People present well and most of the people we know are functional. They make it to work each day, they look after their children, they pay their bills and they keep their houses clean. Yet as a therapist, I get to see and hear each day about how many of these seemingly happy people who get things done and handle their business are secretly finding ways to self-soothe each night after work. It makes me wonder if Thoreau was right about "the mass of men lead[ing] lives of quiet desperation." The problem isn't that our friends are withholding their pain—the problem is they may not even realize they're in pain to begin with. The addictive behavior they've discovered can serve to take the edge off just enough to make someone get through the day—thinking they're alright enough.
The litmus test I would use to discuss with any patient whether or not their behavior was, indeed, addictive in nature was whether or not they could not do it. If you can't not do something, then maybe this behavior has gotten problematic. If you can't not have dessert one night. If you can't not have a drink (or 2 or 3 or 6) after work, then you should look at that. The problem is that such patterns of destructive behaviors are a mask, a hiding place. The trick is to challenge yourself to actually feel your feelings. Many of us drink too much when going through a break up. Or we eat too much or exercise too much or do whatever we think we need to do, excessively, to cope with whatever we've got going on. The problem, and the irony of it all, is that the key is to be able to actually sit and cope with our feelings until we don't need to go do something else. To get to the point where you can actually tolerate your own emotions is where the real freedom lies. Indulging on the short-term, however, such as in response to horrible news and events is different than using on the long-term. The habitual nature of addiction is the indicator that something isn't working for you in your life if you need to incorporate these substances into your routine.
A patient recently asked me "Is it better to cry?" She then added, "if I couldn't reward myself with sweets at the end of the day, then I really think I might spend my evenings crying—even though I already do cry over being at a weight I don't want to be at." Most of us wouldn't like the idea of sitting and crying each night, but here is the thing with that: If you fell into crying episodes, unpleasant and awful as they can be, you probably wouldn't cry everyday for the rest of your life. Crying is a release, and the more present you are with your emotions, rather than stuffing them down with food or booze, the more likely you might be to get in touch with what's really going on. You might have a better shot to get to the bottom of the critical question of your life's problems. Why do you feel so emotional? What is the void in your life that you're choosing to fill with something? Even if you didn't become closer to answering these questions on your own maybe you would at least elect to go talk to someone.
"Wow, I guess I'm not happy with my life", said Donna*. "I think I've just been going about my days making the best of a bad situation." Donna had a historical struggle with Binge Eating Disorder and had had a particularly hard time with it for the past few years. She didn't realize that her weight struggles actually telegraphed more of a message to herself and to the world that things weren't quite right. Donna isn't alone. I can't tell you how many people I see who eat or drink or spend or smoke or snort over bad marriages, toxic work environments, tensions with their in-laws or family members, or just general anxiety and malaise. It doesn't matter what you're using—if the behavior feels at all out of control, it probably is. Addiction is a delay—a procrastination. This maladaptive behavior, however, does serve a purpose—to get you through the day. Realizing your dependence on this behavior, however, is an opportunity to wake-up and take charge of the fact that this is your life and it's up to only you to make it better. Addiction doesn't have to be something as indulgently obvious as heroin or deep-fried Snickers bars. Anything you're using that you feel you can't do without should be looked at. Yes, it would be great to replace our bad behaviors with healthier ones. I tell my patients all the time, "I'd love to see you paint a picture or go take a bubble bath in response to feeling sad, but I know that behavior isn't likely to take the pain away like a cocktail would." The instant gratification is often what one is addicted to, but it prevents long-term satisfaction, and that is the trap. It's a scary thing to admit to yourself that you might not be happy, and I think that is the reason people hide from it. It's ok to be unhappy. And if you're addicted to something you know you shouldn't be, then, no, you just aren't happy. If you are lucky enough to figure that out, perhaps you can, eventually, leave the donut-cave behind and start living the actual life you want.