Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds the ability to run bash script through appium-for-mac #30

Closed
wants to merge 2 commits into from
Closed
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Adds the ability to run bash script through appium-for-mac using the …
…selenium driver.execute_script()
davidmokos committed Nov 16, 2017

Verified

This commit was signed with the committer’s verified signature.
Doctor-wu Doctor Wu
commit 6adbfea217723ebd1b0149cf73c70ffc1086f826
1 change: 1 addition & 0 deletions AppiumForMac/Server/Controller/AfMSessionController.h
Original file line number Diff line number Diff line change
@@ -143,6 +143,7 @@ extern NSString * const kCookieDiagnosticsDirectory;
- (BOOL)isElementDisplayed:(id)element;
-(BOOL) clickElement:(id)element;
-(void) closeWindow;
- (NSString *)runCommand:(NSString *)commandToRun;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use a name like executeShellScript:(NSString *)script. It is more specific, and derived from the "post_execute" web driver command name.

-(NSDictionary*) pageSource;
-(NSInteger) pidForProcessName:(NSString*)processName;
-(SystemEventsProcess*) processForName:(NSString*)processName;
25 changes: 25 additions & 0 deletions AppiumForMac/Server/Controller/AfMSessionController.m
Original file line number Diff line number Diff line change
@@ -574,6 +574,31 @@ -(void) closeWindow
[self.currentWindow performAction:@"AXCancel"];
}

- (NSString *)runCommand:(NSString *)commandToRun
{
NSTask *task = [[NSTask alloc] init];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume NSTask starts with an empty environment by default. Shouldn't we inherit the current system env by default?

[task setLaunchPath:@"/bin/sh"];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you sure 'sh' will run bash? Why not use /bin/bash to be explicit ?


NSArray *arguments = [NSArray arrayWithObjects:
@"-c" ,
[NSString stringWithFormat:@"%@", commandToRun],
nil];
NSLog(@"run command:%@", commandToRun);
[task setArguments:arguments];

NSPipe *pipe = [NSPipe pipe];
[task setStandardOutput:pipe];

NSFileHandle *file = [pipe fileHandleForReading];

[task launch];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The launch method is deprecated. Please use only supported APIs.
https://developer.apple.com/documentation/foundation/nstask/1414189-launch?language=objc


NSData *data = [file readDataToEndOfFile];

NSString *output = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
return output;
}

-(NSString*) currentApplicationName
{
return self._currentApplicationName;
3 changes: 3 additions & 0 deletions AppiumForMac/Server/Handlers/AfMHandlers.h
Original file line number Diff line number Diff line change
@@ -54,7 +54,10 @@
// POST /session/:sessionId/forward
// POST /session/:sessionId/back
// POST /session/:sessionId/refresh

// POST /session/:sessionId/execute
- (AppiumMacHTTPJSONResponse *)post_execute:(NSString*)path data:(NSData*)postData;

// POST /session/:sessionId/execute_async

// GET /session/:sessionId/screenshot
13 changes: 13 additions & 0 deletions AppiumForMac/Server/Handlers/AfMHandlers.m
Original file line number Diff line number Diff line change
@@ -240,6 +240,19 @@ - (AppiumMacHTTPJSONResponse *)post_url:(NSString*)path data:(NSData*)postData
// POST /session/:sessionId/execute
// Inject a snippet of JavaScript into the page for execution in the context of the currently selected frame. The executed script is assumed to be synchronous and the result of evaluating the script is returned to the client.

- (AppiumMacHTTPJSONResponse *)post_execute:(NSString*)path data:(NSData*)postData
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it should be also possible to pass additional environment variables

{
return [self executeWebDriverCommandWithPath:path data:postData onMainThread:YES commandBlock:^(AfMSessionController *session, NSDictionary *commandParams, int *statusCode)
{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if the indentation is from github, but please ensure "return" and the block are aligned.

// The bash command to run
NSString *command = (NSString*)[commandParams objectForKey:@"script"];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename to 'script' or 'scriptString', or something else besides 'command'. In this context, command refers to the web driver command itself.


Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you can, please support the full "execute" command by allowing shell script arguments passed in through the 'args' commandParam. That will allow the same scriptString to have different behaviors without having to rebuild the string in your client script.

NSString *commandResult = [session runCommand:command];

return [AppiumMacHTTPJSONResponse responseWithJson:commandResult status:kAfMStatusCodeSuccess session:session.sessionId];
}];
}

// POST /session/:sessionId/execute_async
// Inject a snippet of JavaScript into the page for execution in the context of the currently selected frame. The executed script is assumed to be asynchronous and must signal that is done by invoking the provided callback, which is always provided as the final argument to the function.