SlideShare a Scribd company logo
Add new commands in
Appium 2.0
Appium Conference 2021
Kazuaki Matsuo (HeadSpin)
About Me
1. Kazuaki Matsuo
○ GitHub: https://github.com/KazuCocoa
2. HeadSpin as a senior software engineer
○ ex-Cookpad, ACCESS as Test/QA/Automation role
3. Maintained Appium project and around
○ Appium server in the appium repository
○ Clients (e.g. Ruby, Python, Dart etc)
○ Appium-flutter-driver in appium-userland organization
1. About Appium commands
2. Appium commands in fake driver
3. Calls an Appium command via curl
4. Add commands in a client (Ruby as an example)
Topics
1. About Appium commands
2. Appium commands in fake driver
3. Calls an Appium command via curl
4. Add commands in a client (Ruby as an example)
Topics
Communication route
Appium
Client
Appium
server
The device under test
Communication route
Appium
Client
Appium
server
The device under test
WebDriver Protocol
(HTTP/S)
HTTP/S
adb/xcrun etc
Appium Commands
Appium
Client
Appium
server
The device under test
driver.find_element :accessibility_id, “happy testing”
(A Ruby command to find an element)
Appium Commands
Appium
Client
Appium
server
The device under test
POST: /session/:sessionId/element
{"using":"accessibility id","value":"happy testing"}
1. About Appium commands
2. Appium commands in fake driver
3. Calls an Appium command via curl
4. Add commands in a client (Ruby as an example)
Topics
A fake driver
https://github.com/appium/appium/blob/2.0/packages/fake-driver
Test driver in Appium project.
{
"deviceName": "fake device",
"automationName": "fake",
"platformName": "fake",
"app": "/Users/kazu/appiumconf/fakedriver.txt"
}
In the fake driver
static newMethodMap = {
'/session/:sessionId/fakedriver': {
GET: {command: 'getFakeThing'},
POST: {command: 'setFakeThing', payloadParams: {required: ['thing']}}
},
'/session/:sessionId/fakedriverargs': {
GET: {command: 'getFakeDriverArgs'}
},
};
static fakeRoute (req, res) {
res.send(JSON.stringify({fakedriver: 'fakeResponse'}));
}
static async updateServer (expressApp/*, httpServer*/) {
expressApp.all('/fakedriver', FakeDriver.fakeRoute);
}
https://github.com/appium/appium/blob/2.0/packages/fake-driver/lib/driver.js
In the fake driver
static newMethodMap = {
'/session/:sessionId/fakedriver': {
GET: {command: 'getFakeThing'},
POST: {command: 'setFakeThing', payloadParams: {required: ['thing']}}
},
'/session/:sessionId/fakedriverargs': {
GET: {command: 'getFakeDriverArgs'}
},
};
static fakeRoute (req, res) {
res.send(JSON.stringify({fakedriver: 'fakeResponse'}));
}
static async updateServer (expressApp/*, httpServer*/) {
expressApp.all('/fakedriver', FakeDriver.fakeRoute);
}
https://github.com/appium/appium/blob/2.0/packages/fake-driver/lib/driver.js
GET: /session/:sessionId/fakedriver
POST: /session/:sessionId/fakedriver + body
In the fake driver
static newMethodMap = {
'/session/:sessionId/fakedriver': {
GET: {command: 'getFakeThing'},
POST: {command: 'setFakeThing', payloadParams: {required: ['thing']}}
},
'/session/:sessionId/fakedriverargs': {
GET: {command: 'getFakeDriverArgs'}
},
};
static fakeRoute (req, res) {
res.send(JSON.stringify({fakedriver: 'fakeResponse'}));
}
static async updateServer (expressApp/*, httpServer*/) {
expressApp.all('/fakedriver', FakeDriver.fakeRoute);
}
https://github.com/appium/appium/blob/2.0/packages/fake-driver/lib/driver.js
GET: /session/:sessionId/fakedriver
POST: /session/:sessionId/fakedriver + body
Any methods: /fakedriver
1. About Appium commands
2. Appium commands in fake driver
3. Calls an Appium command via curl
4. Add commands in a client (Ruby as an example)
Topics
In the fake driver
static newMethodMap = {
'/session/:sessionId/fakedriver': {
GET: {command: 'getFakeThing'},
POST: {command: 'setFakeThing', payloadParams: {required: ['thing']}}
},
'/session/:sessionId/fakedriverargs': {
GET: {command: 'getFakeDriverArgs'}
},
};
static fakeRoute (req, res) {
res.send(JSON.stringify({fakedriver: 'fakeResponse'}));
}
static async updateServer (expressApp/*, httpServer*/) {
expressApp.all('/fakedriver', FakeDriver.fakeRoute);
}
https://github.com/appium/appium/blob/2.0/packages/fake-driver/lib/driver.js
GET: /session/<session id>/fakedriver
POST: /session/<session id>/fakedriver + body
Any methods: /fakedriver
Three commands to use in this session
- GET: /session/:sessionId/fakedriver
- POST: /session/:sessionId/fakedriver + request body
- Payload requires “things” attribute
- Any methods: /fakedriver
Demo with simple “curl” command
- GET: /session/:sessionId/fakedriver
- POST: /session/:sessionId/fakedriver + request body
- Payload requires “things” attribute
- Any methods: /fakedriver
curl -X GET http://localhost:4723/fakedriver
#=> {"fakedriver":"fakeResponse"}
1. About Appium commands
2. Appium commands in fake driver
3. Calls an Appium command via curl
4. Add commands in a client (Ruby as an example)
Topics
1. Launch an appium server with a fake driver
2. Start a session
3. Add methods
Call a few endpoints in Ruby with Demo
1. Launch an appium server with a fake driver
2. Start a session
3. Add methods
Call a few endpoints in Ruby with Demo
appium --drivers=fake
1. Launch an appium server with a fake driver
2. Start a session
3. Add methods
Call a few endpoints in Ruby with Demo
Start a session
require 'appium_lib_core'
caps = {
deviceName: "fake device",
automationName: "fake",
platformName: "fake",
app: "/Users/kazu/appiumconf/fakedriver.txt"
}
core = Appium::Core.for url: 'http://localhost:4723',
capabilities: caps
driver = core.start_driver
Check a regular command response
- driver.page_source
- It returns the file body of the “app”
Command 1: GET without session id
static newMethodMap = {
'/session/:sessionId/fakedriver': {
GET: {command: 'getFakeThing'},
POST: {command: 'setFakeThing', payloadParams: {required: ['thing']}}
},
'/session/:sessionId/fakedriverargs': {
GET: {command: 'getFakeDriverArgs'}
},
};
static fakeRoute (req, res) {
res.send(JSON.stringify({fakedriver: 'fakeResponse'}));
}
static async updateServer (expressApp/*, httpServer*/) {
expressApp.all('/fakedriver', FakeDriver.fakeRoute);
}
https://github.com/appium/appium/blob/2.0/packages/fake-driver/lib/driver.js
Any methods: /fakedriver
Command 1: GET without session id
driver.add_command(
method: :get,
url: '/fakedriver',
name: :get_fakedriver
)
driver.get_fakedriver
#=> {"fakedriver":"fakeResponse"}
Command 2: GET with session id
static newMethodMap = {
'/session/:sessionId/fakedriver': {
GET: {command: 'getFakeThing'},
POST: {command: 'setFakeThing', payloadParams: {required: ['thing']}}
},
'/session/:sessionId/fakedriverargs': {
GET: {command: 'getFakeDriverArgs'}
},
};
static fakeRoute (req, res) {
res.send(JSON.stringify({fakedriver: 'fakeResponse'}));
}
static async updateServer (expressApp/*, httpServer*/) {
expressApp.all('/fakedriver', FakeDriver.fakeRoute);
}
https://github.com/appium/appium/blob/2.0/packages/fake-driver/lib/driver.js
GET: /session/<session id>/fakedriver
Command 2: GET with session id
driver.add_command(
method: :get,
url: 'session/:session_id/fakedriver',
name: :get_fakedriver2
)
driver.get_fakedriver2
#=> nil
Command 2: POST with request body
static newMethodMap = {
'/session/:sessionId/fakedriver': {
GET: {command: 'getFakeThing'},
POST: {command: 'setFakeThing', payloadParams: {required: ['thing']}}
},
'/session/:sessionId/fakedriverargs': {
GET: {command: 'getFakeDriverArgs'}
},
};
static fakeRoute (req, res) {
res.send(JSON.stringify({fakedriver: 'fakeResponse'}));
}
static async updateServer (expressApp/*, httpServer*/) {
expressApp.all('/fakedriver', FakeDriver.fakeRoute);
}
https://github.com/appium/appium/blob/2.0/packages/fake-driver/lib/driver.js
POST: /session/:sessionId/fakedriver + body
Command 2: POST with request body
driver.add_command(
method: :post,
url: 'session/:session_id/fakedriver',
name: :post_fakedriver
) do
def post_fakedriver(thing)
execute(:post_fakedriver, {}, { thing: thing })
end
end
driver.post_fakedriver 'happy appium' #=> nil
Command 2: POST with wrong request body
static newMethodMap = {
'/session/:sessionId/fakedriver': {
GET: {command: 'getFakeThing'},
POST: {command: 'setFakeThing', payloadParams: {required: ['thing']}}
},
'/session/:sessionId/fakedriverargs': {
GET: {command: 'getFakeDriverArgs'}
},
};
static fakeRoute (req, res) {
res.send(JSON.stringify({fakedriver: 'fakeResponse'}));
}
static async updateServer (expressApp/*, httpServer*/) {
expressApp.all('/fakedriver', FakeDriver.fakeRoute);
}
https://github.com/appium/appium/blob/2.0/packages/fake-driver/lib/driver.js
POST: /session/:sessionId/fakedriver + body
Command 2: POST with wrong request body
driver.add_command(
method: :post,
url: 'session/:session_id/fakedriver',
name: :post_fakedriver2
) do
def post_fakedriver2(thing)
execute(:post_fakedriver2, {}, { wrong_value: thing })
end
end
driver.post_fakedriver2 'happy appium' #=> nil
Get back to the fake driver again
static newMethodMap = {
'/session/:sessionId/fakedriver': {
GET: {command: 'getFakeThing'},
POST: {command: 'setFakeThing', payloadParams: {required: ['thing']}}
},
'/session/:sessionId/fakedriverargs': {
GET: {command: 'getFakeDriverArgs'}
},
};
static fakeRoute (req, res) {
res.send(JSON.stringify({fakedriver: 'fakeResponse'}));
}
static async updateServer (expressApp/*, httpServer*/) {
expressApp.all('/fakedriver', FakeDriver.fakeRoute);
}
https://github.com/appium/appium/blob/2.0/packages/fake-driver/lib/driver.js
1. Appium command behind a client
2. Appium 2.0 allows you to add new commands in
drivers/plugins
3. Client also can add them, or you also can define HTTP
request you want
Summary
As a reference
Other clients
- WebdriverIO
- https://webdriver.io/docs/api/browser/addCommand/
- Appium Java client
- https://github.com/appium/java-client/blob/bcd6881efe53713ea339a3e606dc0bc0
04969908/src/test/java/io/appium/java_client/ios/IOSDriverTest.java#L47-L68
- Appium Python client
- https://github.com/appium/python-client/blob/f8d3a38639557081700a273c5dcc64
1e42112aba/appium/webdriver/webdriver.py#L117
etc
You also can define them using vanilla HTTP client.
Thank you

More Related Content

PDF
Manage appium dependencies with -appium-home in appium 2.0
PDF
Chrome Devtools Protocol via Selenium/Appium (English)
PDF
Chrome Devtools Protocol via Selenium/Appium (Japanese)
PDF
App development with quasar (pdf)
PDF
Search and play more than 50 clips
PPT
Learn flask in 90mins
PDF
DevOps(3) : Ansible - (MOSG)
PDF
Preparation study of_docker - (MOSG)
Manage appium dependencies with -appium-home in appium 2.0
Chrome Devtools Protocol via Selenium/Appium (English)
Chrome Devtools Protocol via Selenium/Appium (Japanese)
App development with quasar (pdf)
Search and play more than 50 clips
Learn flask in 90mins
DevOps(3) : Ansible - (MOSG)
Preparation study of_docker - (MOSG)

What's hot (20)

PDF
“warpdrive”, making Python web application deployment magically easy.
PPTX
Session on Launching Selenium Grid and Running tests using docker compose and...
PDF
DevOps(4) : Ansible(2) - (MOSG)
PDF
Dependencies Managers in C/C++. Using stdcpp 2014
PDF
Fabric workshop(1) - (MOSG)
PDF
Python Flask app deployed to OPenShift using Wercker CI
PDF
Ansible 實戰:top down 觀點
PDF
Ansible is the simplest way to automate. MoldCamp, 2015
PPTX
Ansible presentation
PPTX
Vagrant WordCamp Hamilton
PDF
appserver.io tutorial
PDF
Node.js vs Play Framework
PDF
DevOpsDaysCPT Ansible Infrastrucutre as Code 2017
PDF
iOS Parallel Automation: run faster than fast — Viktar Karanevich — SeleniumC...
PDF
php & performance
PDF
Create your own composer package
PDF
AMS Node Meetup December presentation Phusion Passenger
PDF
Maven 3.0 at Øredev
PPTX
Angularjs Tutorial for Beginners
PDF
Configuration Surgery with Augeas
“warpdrive”, making Python web application deployment magically easy.
Session on Launching Selenium Grid and Running tests using docker compose and...
DevOps(4) : Ansible(2) - (MOSG)
Dependencies Managers in C/C++. Using stdcpp 2014
Fabric workshop(1) - (MOSG)
Python Flask app deployed to OPenShift using Wercker CI
Ansible 實戰:top down 觀點
Ansible is the simplest way to automate. MoldCamp, 2015
Ansible presentation
Vagrant WordCamp Hamilton
appserver.io tutorial
Node.js vs Play Framework
DevOpsDaysCPT Ansible Infrastrucutre as Code 2017
iOS Parallel Automation: run faster than fast — Viktar Karanevich — SeleniumC...
php & performance
Create your own composer package
AMS Node Meetup December presentation Phusion Passenger
Maven 3.0 at Øredev
Angularjs Tutorial for Beginners
Configuration Surgery with Augeas
Ad

Similar to Add new commands in appium 2.0 (20)

KEY
Intro to PSGI and Plack
KEY
How and why i roll my own node.js framework
PDF
Google Cloud Endpoints: Building Third-Party APIs on Google AppEngine
PDF
Exploring Async PHP (SF Live Berlin 2019)
PDF
Grâce aux tags Varnish, j'ai switché ma prod sur Raspberry Pi
KEY
Psgi Plack Sfpm
KEY
Psgi Plack Sfpm
PPTX
Debugging & profiling node.js
PPTX
Django + Vue, JavaScript de 3ª generación para modernizar Django
KEY
Plack - LPW 2009
PDF
Ruby HTTP clients comparison
KEY
Kansai.pm 10周年記念 Plack/PSGI 入門
PDF
2019 11-bgphp
PDF
Infrastructure = code - 1 year later
KEY
Plack perl superglue for web frameworks and servers
PDF
Nodejs in Production
PDF
20150319 testotipsio
KEY
Plack at YAPC::NA 2010
KEY
PSGI/Plack OSDC.TW
PDF
服务框架: Thrift & PasteScript
Intro to PSGI and Plack
How and why i roll my own node.js framework
Google Cloud Endpoints: Building Third-Party APIs on Google AppEngine
Exploring Async PHP (SF Live Berlin 2019)
Grâce aux tags Varnish, j'ai switché ma prod sur Raspberry Pi
Psgi Plack Sfpm
Psgi Plack Sfpm
Debugging & profiling node.js
Django + Vue, JavaScript de 3ª generación para modernizar Django
Plack - LPW 2009
Ruby HTTP clients comparison
Kansai.pm 10周年記念 Plack/PSGI 入門
2019 11-bgphp
Infrastructure = code - 1 year later
Plack perl superglue for web frameworks and servers
Nodejs in Production
20150319 testotipsio
Plack at YAPC::NA 2010
PSGI/Plack OSDC.TW
服务框架: Thrift & PasteScript
Ad

More from Kazuaki Matsuo (20)

PDF
2022-jasst-tohoku.pdf
PDF
20210616-career-example-at-icare
PDF
Xcode 11におけるXCUITestの挙動
PDF
20191130 system-automation-conference
PDF
Uncovering breaking changes behind UI on mobile applications
PDF
Start contributing to OSS projects on your way
PDF
Go ahead outside Japan
PDF
CookpadTechConf2018-(Mobile)TestAutomation
PDF
20171215 andoird-test-night
PDF
20170726 ios test_night_no
PDF
20170701 lets-step-into-the-oss-community
PDF
20170613 tech easy
PDF
20170529 clem kazuaki_matsuo
PDF
20150423 m3
PDF
20170302 tryswift tasting_tests
PDF
20161126 to ruby
PDF
20160914 te engineer
PDF
20160913 cookpad ios_jp
PDF
20160913 cookpad ios_en
PDF
Toteka 04
2022-jasst-tohoku.pdf
20210616-career-example-at-icare
Xcode 11におけるXCUITestの挙動
20191130 system-automation-conference
Uncovering breaking changes behind UI on mobile applications
Start contributing to OSS projects on your way
Go ahead outside Japan
CookpadTechConf2018-(Mobile)TestAutomation
20171215 andoird-test-night
20170726 ios test_night_no
20170701 lets-step-into-the-oss-community
20170613 tech easy
20170529 clem kazuaki_matsuo
20150423 m3
20170302 tryswift tasting_tests
20161126 to ruby
20160914 te engineer
20160913 cookpad ios_jp
20160913 cookpad ios_en
Toteka 04

Recently uploaded (20)

PDF
2025 Textile ERP Trends: SAP, Odoo & Oracle
PDF
Addressing The Cult of Project Management Tools-Why Disconnected Work is Hold...
PDF
How to Choose the Right IT Partner for Your Business in Malaysia
PDF
T3DD25 TYPO3 Content Blocks - Deep Dive by André Kraus
PDF
Design an Analysis of Algorithms I-SECS-1021-03
PPTX
Essential Infomation Tech presentation.pptx
PPTX
CHAPTER 2 - PM Management and IT Context
PDF
Wondershare Filmora 15 Crack With Activation Key [2025
PDF
Audit Checklist Design Aligning with ISO, IATF, and Industry Standards — Omne...
PDF
System and Network Administraation Chapter 3
PDF
SAP S4 Hana Brochure 3 (PTS SYSTEMS AND SOLUTIONS)
PDF
How Creative Agencies Leverage Project Management Software.pdf
PDF
How to Migrate SBCGlobal Email to Yahoo Easily
PDF
AI in Product Development-omnex systems
PPTX
Introduction to Artificial Intelligence
PDF
Navsoft: AI-Powered Business Solutions & Custom Software Development
PPTX
Operating system designcfffgfgggggggvggggggggg
PDF
Internet Downloader Manager (IDM) Crack 6.42 Build 42 Updates Latest 2025
PPTX
Oracle E-Business Suite: A Comprehensive Guide for Modern Enterprises
PDF
Flood Susceptibility Mapping Using Image-Based 2D-CNN Deep Learnin. Overview ...
2025 Textile ERP Trends: SAP, Odoo & Oracle
Addressing The Cult of Project Management Tools-Why Disconnected Work is Hold...
How to Choose the Right IT Partner for Your Business in Malaysia
T3DD25 TYPO3 Content Blocks - Deep Dive by André Kraus
Design an Analysis of Algorithms I-SECS-1021-03
Essential Infomation Tech presentation.pptx
CHAPTER 2 - PM Management and IT Context
Wondershare Filmora 15 Crack With Activation Key [2025
Audit Checklist Design Aligning with ISO, IATF, and Industry Standards — Omne...
System and Network Administraation Chapter 3
SAP S4 Hana Brochure 3 (PTS SYSTEMS AND SOLUTIONS)
How Creative Agencies Leverage Project Management Software.pdf
How to Migrate SBCGlobal Email to Yahoo Easily
AI in Product Development-omnex systems
Introduction to Artificial Intelligence
Navsoft: AI-Powered Business Solutions & Custom Software Development
Operating system designcfffgfgggggggvggggggggg
Internet Downloader Manager (IDM) Crack 6.42 Build 42 Updates Latest 2025
Oracle E-Business Suite: A Comprehensive Guide for Modern Enterprises
Flood Susceptibility Mapping Using Image-Based 2D-CNN Deep Learnin. Overview ...

Add new commands in appium 2.0

  • 1. Add new commands in Appium 2.0 Appium Conference 2021 Kazuaki Matsuo (HeadSpin)
  • 2. About Me 1. Kazuaki Matsuo ○ GitHub: https://github.com/KazuCocoa 2. HeadSpin as a senior software engineer ○ ex-Cookpad, ACCESS as Test/QA/Automation role 3. Maintained Appium project and around ○ Appium server in the appium repository ○ Clients (e.g. Ruby, Python, Dart etc) ○ Appium-flutter-driver in appium-userland organization
  • 3. 1. About Appium commands 2. Appium commands in fake driver 3. Calls an Appium command via curl 4. Add commands in a client (Ruby as an example) Topics
  • 4. 1. About Appium commands 2. Appium commands in fake driver 3. Calls an Appium command via curl 4. Add commands in a client (Ruby as an example) Topics
  • 6. Communication route Appium Client Appium server The device under test WebDriver Protocol (HTTP/S) HTTP/S adb/xcrun etc
  • 7. Appium Commands Appium Client Appium server The device under test driver.find_element :accessibility_id, “happy testing” (A Ruby command to find an element)
  • 8. Appium Commands Appium Client Appium server The device under test POST: /session/:sessionId/element {"using":"accessibility id","value":"happy testing"}
  • 9. 1. About Appium commands 2. Appium commands in fake driver 3. Calls an Appium command via curl 4. Add commands in a client (Ruby as an example) Topics
  • 10. A fake driver https://github.com/appium/appium/blob/2.0/packages/fake-driver Test driver in Appium project. { "deviceName": "fake device", "automationName": "fake", "platformName": "fake", "app": "/Users/kazu/appiumconf/fakedriver.txt" }
  • 11. In the fake driver static newMethodMap = { '/session/:sessionId/fakedriver': { GET: {command: 'getFakeThing'}, POST: {command: 'setFakeThing', payloadParams: {required: ['thing']}} }, '/session/:sessionId/fakedriverargs': { GET: {command: 'getFakeDriverArgs'} }, }; static fakeRoute (req, res) { res.send(JSON.stringify({fakedriver: 'fakeResponse'})); } static async updateServer (expressApp/*, httpServer*/) { expressApp.all('/fakedriver', FakeDriver.fakeRoute); } https://github.com/appium/appium/blob/2.0/packages/fake-driver/lib/driver.js
  • 12. In the fake driver static newMethodMap = { '/session/:sessionId/fakedriver': { GET: {command: 'getFakeThing'}, POST: {command: 'setFakeThing', payloadParams: {required: ['thing']}} }, '/session/:sessionId/fakedriverargs': { GET: {command: 'getFakeDriverArgs'} }, }; static fakeRoute (req, res) { res.send(JSON.stringify({fakedriver: 'fakeResponse'})); } static async updateServer (expressApp/*, httpServer*/) { expressApp.all('/fakedriver', FakeDriver.fakeRoute); } https://github.com/appium/appium/blob/2.0/packages/fake-driver/lib/driver.js GET: /session/:sessionId/fakedriver POST: /session/:sessionId/fakedriver + body
  • 13. In the fake driver static newMethodMap = { '/session/:sessionId/fakedriver': { GET: {command: 'getFakeThing'}, POST: {command: 'setFakeThing', payloadParams: {required: ['thing']}} }, '/session/:sessionId/fakedriverargs': { GET: {command: 'getFakeDriverArgs'} }, }; static fakeRoute (req, res) { res.send(JSON.stringify({fakedriver: 'fakeResponse'})); } static async updateServer (expressApp/*, httpServer*/) { expressApp.all('/fakedriver', FakeDriver.fakeRoute); } https://github.com/appium/appium/blob/2.0/packages/fake-driver/lib/driver.js GET: /session/:sessionId/fakedriver POST: /session/:sessionId/fakedriver + body Any methods: /fakedriver
  • 14. 1. About Appium commands 2. Appium commands in fake driver 3. Calls an Appium command via curl 4. Add commands in a client (Ruby as an example) Topics
  • 15. In the fake driver static newMethodMap = { '/session/:sessionId/fakedriver': { GET: {command: 'getFakeThing'}, POST: {command: 'setFakeThing', payloadParams: {required: ['thing']}} }, '/session/:sessionId/fakedriverargs': { GET: {command: 'getFakeDriverArgs'} }, }; static fakeRoute (req, res) { res.send(JSON.stringify({fakedriver: 'fakeResponse'})); } static async updateServer (expressApp/*, httpServer*/) { expressApp.all('/fakedriver', FakeDriver.fakeRoute); } https://github.com/appium/appium/blob/2.0/packages/fake-driver/lib/driver.js GET: /session/<session id>/fakedriver POST: /session/<session id>/fakedriver + body Any methods: /fakedriver
  • 16. Three commands to use in this session - GET: /session/:sessionId/fakedriver - POST: /session/:sessionId/fakedriver + request body - Payload requires “things” attribute - Any methods: /fakedriver
  • 17. Demo with simple “curl” command - GET: /session/:sessionId/fakedriver - POST: /session/:sessionId/fakedriver + request body - Payload requires “things” attribute - Any methods: /fakedriver curl -X GET http://localhost:4723/fakedriver #=> {"fakedriver":"fakeResponse"}
  • 18. 1. About Appium commands 2. Appium commands in fake driver 3. Calls an Appium command via curl 4. Add commands in a client (Ruby as an example) Topics
  • 19. 1. Launch an appium server with a fake driver 2. Start a session 3. Add methods Call a few endpoints in Ruby with Demo
  • 20. 1. Launch an appium server with a fake driver 2. Start a session 3. Add methods Call a few endpoints in Ruby with Demo appium --drivers=fake
  • 21. 1. Launch an appium server with a fake driver 2. Start a session 3. Add methods Call a few endpoints in Ruby with Demo
  • 22. Start a session require 'appium_lib_core' caps = { deviceName: "fake device", automationName: "fake", platformName: "fake", app: "/Users/kazu/appiumconf/fakedriver.txt" } core = Appium::Core.for url: 'http://localhost:4723', capabilities: caps driver = core.start_driver
  • 23. Check a regular command response - driver.page_source - It returns the file body of the “app”
  • 24. Command 1: GET without session id static newMethodMap = { '/session/:sessionId/fakedriver': { GET: {command: 'getFakeThing'}, POST: {command: 'setFakeThing', payloadParams: {required: ['thing']}} }, '/session/:sessionId/fakedriverargs': { GET: {command: 'getFakeDriverArgs'} }, }; static fakeRoute (req, res) { res.send(JSON.stringify({fakedriver: 'fakeResponse'})); } static async updateServer (expressApp/*, httpServer*/) { expressApp.all('/fakedriver', FakeDriver.fakeRoute); } https://github.com/appium/appium/blob/2.0/packages/fake-driver/lib/driver.js Any methods: /fakedriver
  • 25. Command 1: GET without session id driver.add_command( method: :get, url: '/fakedriver', name: :get_fakedriver ) driver.get_fakedriver #=> {"fakedriver":"fakeResponse"}
  • 26. Command 2: GET with session id static newMethodMap = { '/session/:sessionId/fakedriver': { GET: {command: 'getFakeThing'}, POST: {command: 'setFakeThing', payloadParams: {required: ['thing']}} }, '/session/:sessionId/fakedriverargs': { GET: {command: 'getFakeDriverArgs'} }, }; static fakeRoute (req, res) { res.send(JSON.stringify({fakedriver: 'fakeResponse'})); } static async updateServer (expressApp/*, httpServer*/) { expressApp.all('/fakedriver', FakeDriver.fakeRoute); } https://github.com/appium/appium/blob/2.0/packages/fake-driver/lib/driver.js GET: /session/<session id>/fakedriver
  • 27. Command 2: GET with session id driver.add_command( method: :get, url: 'session/:session_id/fakedriver', name: :get_fakedriver2 ) driver.get_fakedriver2 #=> nil
  • 28. Command 2: POST with request body static newMethodMap = { '/session/:sessionId/fakedriver': { GET: {command: 'getFakeThing'}, POST: {command: 'setFakeThing', payloadParams: {required: ['thing']}} }, '/session/:sessionId/fakedriverargs': { GET: {command: 'getFakeDriverArgs'} }, }; static fakeRoute (req, res) { res.send(JSON.stringify({fakedriver: 'fakeResponse'})); } static async updateServer (expressApp/*, httpServer*/) { expressApp.all('/fakedriver', FakeDriver.fakeRoute); } https://github.com/appium/appium/blob/2.0/packages/fake-driver/lib/driver.js POST: /session/:sessionId/fakedriver + body
  • 29. Command 2: POST with request body driver.add_command( method: :post, url: 'session/:session_id/fakedriver', name: :post_fakedriver ) do def post_fakedriver(thing) execute(:post_fakedriver, {}, { thing: thing }) end end driver.post_fakedriver 'happy appium' #=> nil
  • 30. Command 2: POST with wrong request body static newMethodMap = { '/session/:sessionId/fakedriver': { GET: {command: 'getFakeThing'}, POST: {command: 'setFakeThing', payloadParams: {required: ['thing']}} }, '/session/:sessionId/fakedriverargs': { GET: {command: 'getFakeDriverArgs'} }, }; static fakeRoute (req, res) { res.send(JSON.stringify({fakedriver: 'fakeResponse'})); } static async updateServer (expressApp/*, httpServer*/) { expressApp.all('/fakedriver', FakeDriver.fakeRoute); } https://github.com/appium/appium/blob/2.0/packages/fake-driver/lib/driver.js POST: /session/:sessionId/fakedriver + body
  • 31. Command 2: POST with wrong request body driver.add_command( method: :post, url: 'session/:session_id/fakedriver', name: :post_fakedriver2 ) do def post_fakedriver2(thing) execute(:post_fakedriver2, {}, { wrong_value: thing }) end end driver.post_fakedriver2 'happy appium' #=> nil
  • 32. Get back to the fake driver again static newMethodMap = { '/session/:sessionId/fakedriver': { GET: {command: 'getFakeThing'}, POST: {command: 'setFakeThing', payloadParams: {required: ['thing']}} }, '/session/:sessionId/fakedriverargs': { GET: {command: 'getFakeDriverArgs'} }, }; static fakeRoute (req, res) { res.send(JSON.stringify({fakedriver: 'fakeResponse'})); } static async updateServer (expressApp/*, httpServer*/) { expressApp.all('/fakedriver', FakeDriver.fakeRoute); } https://github.com/appium/appium/blob/2.0/packages/fake-driver/lib/driver.js
  • 33. 1. Appium command behind a client 2. Appium 2.0 allows you to add new commands in drivers/plugins 3. Client also can add them, or you also can define HTTP request you want Summary
  • 34. As a reference Other clients - WebdriverIO - https://webdriver.io/docs/api/browser/addCommand/ - Appium Java client - https://github.com/appium/java-client/blob/bcd6881efe53713ea339a3e606dc0bc0 04969908/src/test/java/io/appium/java_client/ios/IOSDriverTest.java#L47-L68 - Appium Python client - https://github.com/appium/python-client/blob/f8d3a38639557081700a273c5dcc64 1e42112aba/appium/webdriver/webdriver.py#L117 etc You also can define them using vanilla HTTP client.