├── .github └── workflows │ ├── Semgrep.yml │ └── gem-push.yml ├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── CODEOWNERS ├── Gemfile ├── Gemfile.lock ├── MIT-LICENSE.txt ├── README.md ├── Rakefile ├── browserstack-local.gemspec ├── lib └── browserstack │ ├── local.rb │ ├── localbinary.rb │ └── localexception.rb └── test └── browserstack-local-test.rb /.github/workflows/Semgrep.yml: -------------------------------------------------------------------------------- 1 | # Name of this GitHub Actions workflow. 2 | name: Semgrep 3 | 4 | on: 5 | # Scan changed files in PRs (diff-aware scanning): 6 | # The branches below must be a subset of the branches above 7 | pull_request: 8 | branches: ["master", "main"] 9 | push: 10 | branches: ["master", "main"] 11 | schedule: 12 | - cron: '0 6 * * *' 13 | 14 | 15 | permissions: 16 | contents: read 17 | 18 | jobs: 19 | semgrep: 20 | # User definable name of this GitHub Actions job. 21 | permissions: 22 | contents: read # for actions/checkout to fetch code 23 | security-events: write # for github/codeql-action/upload-sarif to upload SARIF results 24 | name: semgrep/ci 25 | # If you are self-hosting, change the following `runs-on` value: 26 | runs-on: ubuntu-latest 27 | 28 | container: 29 | # A Docker image with Semgrep installed. Do not change this. 30 | image: returntocorp/semgrep 31 | 32 | # Skip any PR created by dependabot to avoid permission issues: 33 | if: (github.actor != 'dependabot[bot]') 34 | 35 | steps: 36 | # Fetch project source with GitHub Actions Checkout. 37 | - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 38 | # Run the "semgrep ci" command on the command line of the docker image. 39 | - run: semgrep ci --sarif --output=semgrep.sarif 40 | env: 41 | # Add the rules that Semgrep uses by setting the SEMGREP_RULES environment variable. 42 | SEMGREP_RULES: p/default # more at semgrep.dev/explore 43 | 44 | - name: Upload SARIF file for GitHub Advanced Security Dashboard 45 | uses: github/codeql-action/upload-sarif@6c089f53dd51dc3fc7e599c3cb5356453a52ca9e # v2.20.0 46 | with: 47 | sarif_file: semgrep.sarif 48 | if: always() -------------------------------------------------------------------------------- /.github/workflows/gem-push.yml: -------------------------------------------------------------------------------- 1 | name: Ruby Gem 2 | 3 | on: workflow_dispatch 4 | 5 | jobs: 6 | build: 7 | name: Build + Publish 8 | runs-on: ubuntu-latest 9 | permissions: 10 | contents: read 11 | packages: write 12 | 13 | steps: 14 | - uses: actions/checkout@v3 15 | - name: Set up Ruby 2.6 16 | uses: ruby/setup-ruby@v1 17 | with: 18 | ruby-version: 2.6.10 19 | 20 | - name: Publish to RubyGems 21 | run: | 22 | mkdir -p $HOME/.gem 23 | touch $HOME/.gem/credentials 24 | chmod 0600 $HOME/.gem/credentials 25 | printf -- "---\n:rubygems_api_key: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials 26 | gem build *.gemspec 27 | gem push *.gem 28 | env: 29 | GEM_HOST_API_KEY: "${{secrets.RUBYGEMS_AUTH_TOKEN}}" 30 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | dist/* 2 | *.log 3 | browserstack.err 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: ruby 2 | 3 | matrix: 4 | include: 5 | - os: linux 6 | rvm: 2.2.2 7 | - os: linux 8 | rvm: 2.2.1 9 | - os: linux 10 | rvm: 1.9.3 11 | - os: linux 12 | rvm: 1.8.7 13 | - os: osx 14 | rvm: 2.2.2 15 | - os: osx 16 | rvm: 2.2.1 17 | 18 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](http://keepachangelog.com/) 5 | and this project adheres to [Semantic Versioning](http://semver.org/). 6 | 7 | ## [Unreleased] - yyyy-mm-dd 8 | 9 | ## [ 10 | 1.4.3] - 2023-08-24 11 | 12 | ### Changed 13 | Ruby 3 exists? deprecation fix 14 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @browserstack/local-dev 2 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source "http://rubygems.org" 2 | gem "minitest" 3 | gem "rake" 4 | gem "json" 5 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: http://rubygems.org/ 3 | specs: 4 | json (1.8.3) 5 | minitest (5.8.4) 6 | rake (12.3.3) 7 | 8 | PLATFORMS 9 | ruby 10 | 11 | DEPENDENCIES 12 | json 13 | minitest 14 | rake 15 | 16 | BUNDLED WITH 17 | 1.11.2 18 | -------------------------------------------------------------------------------- /MIT-LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 BrowserStack 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # browserstack-local-ruby 2 | 3 | [![Build Status](https://travis-ci.org/browserstack/browserstack-local-ruby.svg?branch=master)](https://travis-ci.org/browserstack/browserstack-local-ruby) [![Gem Version](https://badge.fury.io/rb/browserstack-local.svg)](https://badge.fury.io/rb/browserstack-local) 4 | 5 | Ruby bindings for BrowserStack Local. 6 | 7 | ## Installation 8 | 9 | ``` 10 | gem install browserstack-local 11 | ``` 12 | 13 | ## Example 14 | 15 | ``` 16 | require 'browserstack/local' 17 | 18 | #creates an instance of Local 19 | bs_local = BrowserStack::Local.new 20 | 21 | #replace with your key. You can also set an environment variable - "BROWSERSTACK_ACCESS_KEY". 22 | bs_local_args = { "key" => "" } 23 | 24 | #starts the Local instance with the required arguments 25 | bs_local.start(bs_local_args) 26 | 27 | #check if BrowserStack local instance is running 28 | puts bs_local.isRunning 29 | 30 | #stop the Local instance 31 | bs_local.stop 32 | 33 | ``` 34 | 35 | ## Arguments 36 | 37 | Apart from the key, all other BrowserStack Local modifiers are optional. For the full list of modifiers, refer [BrowserStack Local modifiers](https://www.browserstack.com/local-testing#modifiers). For examples, refer below - 38 | 39 | #### Verbose Logging 40 | To enable verbose logging - 41 | ``` 42 | bs_local_args = { "key" => "" , "v" => "true"} 43 | ``` 44 | 45 | #### Folder Testing 46 | To test local folder rather internal server, provide path to folder as value of this option - 47 | ``` 48 | bs_local_args = { "key" => "" , "f" => "/my/awesome/folder"} 49 | ``` 50 | 51 | #### Force Start 52 | To kill other running Browserstack Local instances - 53 | ``` 54 | bs_local_args = { "key" => "" , "force" => "true"} 55 | ``` 56 | 57 | #### Only Automate 58 | To disable local testing for Live and Screenshots, and enable only Automate - 59 | ``` 60 | bs_local_args = { "key" => "" , "onlyAutomate" => "true"} 61 | ``` 62 | 63 | #### Force Local 64 | To route all traffic via local(your) machine - 65 | ``` 66 | bs_local_args = { "key" => "" , "forcelocal" => "true"} 67 | ``` 68 | 69 | #### Proxy 70 | To use a proxy for local testing - 71 | 72 | * proxyHost: Hostname/IP of proxy, remaining proxy options are ignored if this option is absent 73 | * proxyPort: Port for the proxy, defaults to 3128 when -proxyHost is used 74 | * proxyUser: Username for connecting to proxy (Basic Auth Only) 75 | * proxyPass: Password for USERNAME, will be ignored if USERNAME is empty or not specified 76 | 77 | ``` 78 | bs_local_args = { "key" => "", "proxyHost" => "127.0.0.1", "proxyPort" => "8000", "proxyUser" => "user", "proxyPass" => "password"} 79 | ``` 80 | 81 | #### Local Proxy 82 | To use local proxy in local testing - 83 | 84 | * localProxyHost: Hostname/IP of proxy, remaining proxy options are ignored if this option is absent 85 | * localProxyPort: Port for the proxy, defaults to 8081 when -localProxyHost is used 86 | * localProxyUser: Username for connecting to proxy (Basic Auth Only) 87 | * localProxyPass: Password for USERNAME, will be ignored if USERNAME is empty or not specified 88 | 89 | ``` 90 | bs_local_args = { "key" => "", "localProxyHost" => "127.0.0.1", "localProxyPort" => "8000", "-localProxyUser" => "user", "-localProxyPass" => "password"} 91 | ``` 92 | 93 | #### PAC (Proxy Auto-Configuration) 94 | To use PAC (Proxy Auto-Configuration) in local testing - 95 | 96 | * pac-file: PAC (Proxy Auto-Configuration) file’s absolute path 97 | 98 | ``` 99 | bs_local_args = { "key" => "" , "-pac-file" => ""} 100 | ``` 101 | 102 | #### Local Identifier 103 | If doing simultaneous multiple local testing connections, set this uniquely for different processes - 104 | ``` 105 | bs_local_args = { "key" => "" , "localIdentifier" => "randomstring"} 106 | ``` 107 | 108 | ## Additional Arguments 109 | 110 | #### Binary Path 111 | 112 | By default, BrowserStack local wrappers try downloading and executing the latest version of BrowserStack binary in ~/.browserstack or the present working directory or the tmp folder by order. But you can override these by passing the -binarypath argument. 113 | Path to specify local Binary path - 114 | ``` 115 | bs_local_args = { "key" => "" , "binarypath" => "/browserstack/BrowserStackLocal"} 116 | ``` 117 | 118 | #### Logfile 119 | To save the logs to the file while running with the '-v' argument, you can specify the path of the file. By default the logs are saved in the local.log file in the present woring directory. 120 | To specify the path to file where the logs will be saved - 121 | ``` 122 | bs_local_args = { "key" => "" , "v" => "true", "logfile" => "/browserstack/logs.txt"} 123 | ``` 124 | 125 | ## Contribute 126 | 127 | ### Build Instructions 128 | 129 | To build gem, `rake build`. 130 | 131 | To run the test suite run, `rake test`. 132 | 133 | ### Reporting bugs 134 | 135 | You can submit bug reports either in the Github issue tracker. 136 | 137 | Before submitting an issue please check if there is already an existing issue. If there is, please add any additional information give it a "+1" in the comments. 138 | 139 | When submitting an issue please describe the issue clearly, including how to reproduce the bug, which situations it appears in, what you expect to happen, what actually happens, and what platform (operating system and version) you are using. 140 | 141 | ### Pull Requests 142 | 143 | We love pull requests! We are very happy to work with you to get your changes merged in, however, please keep the following in mind. 144 | 145 | * Adhere to the coding conventions you see in the surrounding code. 146 | * Include tests, and make sure all tests pass. 147 | * Before submitting a pull-request, clean up the git history by going over your commits and squashing together minor changes and fixes into the corresponding commits. You can do this using the interactive rebase command. 148 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require "rake/testtask" 2 | 3 | task :default => :test 4 | Rake::TestTask.new do |t| 5 | t.pattern = "test/*test.rb" 6 | t.verbose = false 7 | end 8 | 9 | task :build do 10 | system "mkdir dist" 11 | system "gem build browserstack-local.gemspec" 12 | move_command = RbConfig::CONFIG['host_os'].match(/mswin|msys|mingw|cygwin|bccwin|wince|emc|win32/) ? "move" : "mv"; 13 | system "#{move_command} browserstack-local-*.gem dist" 14 | system "gem install ./dist/browserstack-local-*.gem" 15 | system "rm -rf dist" 16 | end 17 | -------------------------------------------------------------------------------- /browserstack-local.gemspec: -------------------------------------------------------------------------------- 1 | Gem::Specification.new do |s| 2 | s.name = 'browserstack-local' 3 | s.version = '1.4.3' 4 | s.date = '2023-08-24' 5 | s.summary = "BrowserStack Local" 6 | s.description = "Ruby bindings for BrowserStack Local" 7 | s.authors = ["BrowserStack"] 8 | s.email = 'support@browserstack.com' 9 | s.files = ["lib/browserstack/local.rb", "lib/browserstack/localbinary.rb", "lib/browserstack/localexception.rb"] 10 | s.homepage = 11 | 'http://rubygems.org/gems/browserstack-local' 12 | s.license = 'MIT' 13 | end 14 | 15 | -------------------------------------------------------------------------------- /lib/browserstack/local.rb: -------------------------------------------------------------------------------- 1 | require 'browserstack/localbinary' 2 | require 'browserstack/localexception' 3 | require 'json' 4 | 5 | module BrowserStack 6 | 7 | class Local 8 | attr_reader :pid 9 | 10 | def initialize(key = ENV["BROWSERSTACK_ACCESS_KEY"]) 11 | @key = key 12 | @user_arguments = [] 13 | @logfile = File.join(Dir.pwd, "local.log") 14 | @is_windows = RbConfig::CONFIG['host_os'].match(/mswin|msys|mingw|cygwin|bccwin|wince|emc|win32/) 15 | @exec = @is_windows ? "call" : "exec"; 16 | end 17 | 18 | def add_args(key, value=nil) 19 | if key == "key" 20 | @key = value 21 | elsif key == "v" && value.to_s != "false" 22 | @verbose_flag = "-vvv" 23 | elsif key == "force" && value.to_s != "false" 24 | @force_flag = "-force" 25 | elsif key == "only" && value.to_s != "false" 26 | @only_flag = "-only" 27 | elsif key == "onlyAutomate" && value.to_s != "false" 28 | @only_automate_flag = "-onlyAutomate" 29 | elsif key == "forcelocal" && value.to_s != "false" 30 | @force_local_flag = "-forcelocal" 31 | elsif key == "localIdentifier" 32 | @local_identifier_flag = value 33 | elsif key == "f" 34 | @folder_flag = "-f" 35 | @folder_path = value 36 | elsif key == "proxyHost" 37 | @proxy_host = value 38 | elsif key == "proxyPort" 39 | @proxy_port = value 40 | elsif key == "proxyUser" 41 | @proxy_user = value 42 | elsif key == "proxyPass" 43 | @proxy_pass = value 44 | elsif key == "hosts" 45 | @hosts = value 46 | elsif key == "logfile" 47 | @logfile = value 48 | elsif key == "binarypath" 49 | @binary_path = value 50 | elsif key == "forceproxy" && value.to_s != "false" 51 | @force_proxy_flag = "-forceproxy" 52 | else 53 | if value.to_s.downcase.eql?("true") 54 | @user_arguments << "-#{key}" 55 | else 56 | @user_arguments += ["-#{key}", value] 57 | end 58 | end 59 | end 60 | 61 | def start(options = {}) 62 | options.each_pair do |key, value| 63 | self.add_args(key, value) 64 | end 65 | 66 | @binary_path = if @binary_path.nil? 67 | BrowserStack::LocalBinary.new.binary_path 68 | else 69 | @binary_path 70 | end 71 | 72 | if @is_windows 73 | system("echo > #{@logfile}") 74 | else 75 | system("echo '' > '#{@logfile}'") 76 | end 77 | 78 | if defined? spawn 79 | @process = IO.popen(start_command_args) 80 | else 81 | @process = IO.popen(start_command) 82 | end 83 | 84 | while true 85 | begin 86 | line = @process.readline 87 | rescue EOFError => e 88 | sleep 1 89 | next 90 | end 91 | 92 | data = JSON.parse(line) rescue {"message" => "Unable to parse daemon mode JSON output"} 93 | if data['state'].to_s != "connected" 94 | @process.close 95 | raise BrowserStack::LocalException.new(data["message"]["message"]) 96 | return 97 | else 98 | @pid = data["pid"] 99 | break 100 | end 101 | end 102 | end 103 | 104 | def isRunning 105 | return true if (!@pid.nil? && Process.kill(0, @pid)) rescue false 106 | end 107 | 108 | def stop 109 | return if @pid.nil? 110 | @process.close 111 | if defined? spawn 112 | @process = IO.popen(stop_command_args) 113 | else 114 | @process = IO.popen(stop_command) 115 | end 116 | @process.close 117 | @pid = nil 118 | end 119 | 120 | def command 121 | start_command 122 | end 123 | 124 | def start_command 125 | cmd = "#{@binary_path} -d start -logFile '#{@logfile}' #{@folder_flag} #{@key} #{@folder_path} #{@force_local_flag}" 126 | cmd += " -localIdentifier #{@local_identifier_flag}" if @local_identifier_flag 127 | cmd += " #{@only_flag} #{@only_automate_flag}" 128 | cmd += " -proxyHost #{@proxy_host}" if @proxy_host 129 | cmd += " -proxyPort #{@proxy_port}" if @proxy_port 130 | cmd += " -proxyUser #{@proxy_user}" if @proxy_user 131 | cmd += " -proxyPass #{@proxy_pass}" if @proxy_pass 132 | cmd += " #{@force_proxy_flag} #{@force_flag} #{@verbose_flag} #{@hosts} #{@user_arguments.join(" ")} 2>&1" 133 | cmd.strip 134 | end 135 | 136 | def start_command_args 137 | args = [@binary_path, "-d", "start", "-logFile", @logfile, @key, @folder_flag, @folder_path, @force_local_flag] 138 | args += ["-localIdentifier", @local_identifier_flag] if @local_identifier_flag 139 | args += [@only_flag, @only_automate_flag] 140 | args += ["-proxyHost", @proxy_host] if @proxy_host 141 | args += ["-proxyPort", @proxy_port] if @proxy_port 142 | args += ["-proxyUser", @proxy_user] if @proxy_user 143 | args += ["-proxyPass", @proxy_pass] if @proxy_pass 144 | args += [@force_proxy_flag, @force_flag, @verbose_flag, @hosts] 145 | args += @user_arguments 146 | 147 | args = args.select {|a| a.to_s != "" } 148 | args.push(:err => [:child, :out]) 149 | args 150 | end 151 | 152 | def stop_command 153 | if @local_identifier_flag 154 | return "#{@binary_path} -d stop -localIdentifier #{@local_identifier_flag}".strip 155 | else 156 | return "#{@binary_path} -d stop".strip 157 | end 158 | end 159 | 160 | def stop_command_args 161 | args = ["#{@binary_path}", "-d", "stop"] 162 | args += ["-localIdentifier", "#{@local_identifier_flag}"] if @local_identifier_flag 163 | args = args.select {|a| a.to_s != "" } 164 | args.push(:err => [:child, :out]) 165 | args 166 | end 167 | end 168 | 169 | end 170 | -------------------------------------------------------------------------------- /lib/browserstack/localbinary.rb: -------------------------------------------------------------------------------- 1 | require 'net/http' 2 | require 'net/https' 3 | require 'rbconfig' 4 | require 'openssl' 5 | require 'tmpdir' 6 | require 'browserstack/localexception' 7 | 8 | module BrowserStack 9 | 10 | class LocalBinary 11 | def initialize 12 | host_os = RbConfig::CONFIG['host_os'] 13 | @http_path = case host_os 14 | when /mswin|msys|mingw|cygwin|bccwin|wince|emc/ 15 | @windows = true 16 | "https://www.browserstack.com/local-testing/downloads/binaries/BrowserStackLocal.exe" 17 | when /darwin|mac os/ 18 | "https://www.browserstack.com/local-testing/downloads/binaries/BrowserStackLocal-darwin-x64" 19 | when /linux-musl/ 20 | "https://www.browserstack.com/local-testing/downloads/binaries/BrowserStackLocal-alpine" 21 | when /linux/ 22 | if 1.size == 8 23 | "https://www.browserstack.com/local-testing/downloads/binaries/BrowserStackLocal-linux-x64" 24 | else 25 | "https://www.browserstack.com/local-testing/downloads/binaries/BrowserStackLocal-linux-ia32" 26 | end 27 | end 28 | 29 | @ordered_paths = [ 30 | File.join(File.expand_path('~'), '.browserstack'), 31 | Dir.pwd, 32 | Dir.tmpdir 33 | ] 34 | end 35 | 36 | def download(dest_parent_dir) 37 | unless File.exist? dest_parent_dir 38 | Dir.mkdir dest_parent_dir 39 | end 40 | uri = URI.parse(@http_path) 41 | binary_path = File.join(dest_parent_dir, "BrowserStackLocal#{".exe" if @windows}") 42 | http = Net::HTTP.new(uri.host, uri.port) 43 | http.use_ssl = true 44 | http.verify_mode = OpenSSL::SSL::VERIFY_NONE 45 | 46 | res = http.get(uri.path) 47 | file = open(binary_path, 'wb') 48 | file.write(res.body) 49 | file.close 50 | FileUtils.chmod 0755, binary_path 51 | 52 | binary_path 53 | end 54 | 55 | def verify_binary(binary_path) 56 | binary_response = IO.popen(binary_path + " --version").readline 57 | binary_response =~ /BrowserStack Local version \d+\.\d+/ 58 | rescue Exception => e 59 | false 60 | end 61 | 62 | def binary_path 63 | dest_parent_dir = get_available_dirs 64 | binary_path = File.join(dest_parent_dir, "BrowserStackLocal#{".exe" if @windows}") 65 | 66 | if File.exist? binary_path 67 | binary_path 68 | else 69 | binary_path = download(dest_parent_dir) 70 | end 71 | 72 | valid_binary = verify_binary(binary_path) 73 | 74 | if valid_binary 75 | binary_path 76 | else 77 | binary_path = download(dest_parent_dir) 78 | valid_binary = verify_binary(binary_path) 79 | if valid_binary 80 | binary_path 81 | else 82 | raise BrowserStack::LocalException.new('BrowserStack Local binary is corrupt') 83 | end 84 | end 85 | end 86 | 87 | private 88 | 89 | def get_available_dirs 90 | i = 0 91 | while i < @ordered_paths.size 92 | path = @ordered_paths[i] 93 | if make_path(path) 94 | return path 95 | else 96 | i += 1 97 | end 98 | end 99 | raise BrowserStack::LocalException.new('Error trying to download BrowserStack Local binary') 100 | end 101 | 102 | def make_path(path) 103 | begin 104 | FileUtils.mkdir_p path if !File.directory?(path) 105 | return true 106 | rescue Exception 107 | return false 108 | end 109 | end 110 | end 111 | 112 | end 113 | -------------------------------------------------------------------------------- /lib/browserstack/localexception.rb: -------------------------------------------------------------------------------- 1 | module BrowserStack 2 | 3 | class LocalException < Exception 4 | end 5 | 6 | end -------------------------------------------------------------------------------- /test/browserstack-local-test.rb: -------------------------------------------------------------------------------- 1 | require 'rubygems' 2 | require 'minitest' 3 | require 'minitest/autorun' 4 | require 'browserstack/local' 5 | 6 | class BrowserStackLocalTest < Minitest::Test 7 | def setup 8 | @bs_local = BrowserStack::Local.new 9 | end 10 | 11 | def test_check_pid 12 | @bs_local.start 13 | refute_nil @bs_local.pid, 0 14 | end 15 | 16 | def test_is_running 17 | @bs_local.start 18 | assert_equal true, @bs_local.isRunning 19 | end 20 | 21 | def test_multiple_binary 22 | @bs_local.start 23 | bs_local_2 = BrowserStack::Local.new 24 | second_log_file = File.join(Dir.pwd, 'local2.log') 25 | assert_raises BrowserStack::LocalException do 26 | bs_local_2.start({'logfile' => second_log_file}) 27 | end 28 | File.delete(second_log_file) 29 | end 30 | 31 | def test_enable_verbose 32 | @bs_local.add_args('v') 33 | assert_match /\-v/, @bs_local.command 34 | end 35 | 36 | def test_set_folder 37 | @bs_local.add_args 'f', "/" 38 | assert_match /\-f/, @bs_local.command 39 | assert_match /\//, @bs_local.command 40 | end 41 | 42 | def test_enable_force 43 | @bs_local.add_args "force" 44 | assert_match /\-force/, @bs_local.command 45 | end 46 | 47 | def test_enable_only 48 | @bs_local.add_args "only" 49 | assert_match /\-only/, @bs_local.command 50 | end 51 | 52 | def test_enable_only_automate 53 | @bs_local.add_args "onlyAutomate" 54 | assert_match /\-onlyAutomate/, @bs_local.command 55 | end 56 | 57 | def test_enable_force_local 58 | @bs_local.add_args "forcelocal" 59 | assert_match /\-forcelocal/, @bs_local.command 60 | end 61 | 62 | def test_set_local_identifier 63 | @bs_local.add_args "localIdentifier", "randomString" 64 | assert_match /\-localIdentifier randomString/, @bs_local.command 65 | end 66 | 67 | def test_custom_boolean_argument 68 | @bs_local.add_args "boolArg1" 69 | @bs_local.add_args "boolArg2" 70 | assert_match /\-boolArg1/, @bs_local.command 71 | assert_match /\-boolArg2/, @bs_local.command 72 | end 73 | 74 | def test_custom_keyval 75 | @bs_local.add_args "customKey1", "'custom value1'" 76 | @bs_local.add_args "customKey2", "'custom value2'" 77 | assert_match /\-customKey1 \'custom value1\'/, @bs_local.command 78 | assert_match /\-customKey2 \'custom value2\'/, @bs_local.command 79 | end 80 | 81 | def test_set_proxy 82 | @bs_local.add_args "proxyHost", "localhost" 83 | @bs_local.add_args "proxyPort", 8080 84 | @bs_local.add_args "proxyUser", "user" 85 | @bs_local.add_args "proxyPass", "pass" 86 | assert_match /\-proxyHost localhost \-proxyPort 8080 \-proxyUser user \-proxyPass pass/, @bs_local.command 87 | end 88 | 89 | def test_force_proxy 90 | @bs_local.add_args "forceproxy" 91 | assert_match /\-forceproxy/, @bs_local.command 92 | end 93 | 94 | def test_hosts 95 | @bs_local.add_args "hosts", "localhost,8080,0" 96 | assert_match /localhost\,8080\,0/, @bs_local.command 97 | end 98 | 99 | def teardown 100 | @bs_local.stop 101 | end 102 | end 103 | --------------------------------------------------------------------------------