diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 82b681f4..c8a0898f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -32,5 +32,10 @@ jobs: ruby-version: ${{ matrix.ruby-version }} bundler-cache: true + - name: Lint code + uses: andrewmcodes/standardrb-action@v0.0.2 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Run test suite run: bundle exec rake diff --git a/Gemfile b/Gemfile index fa75df15..b4e2a20b 100644 --- a/Gemfile +++ b/Gemfile @@ -1,3 +1,3 @@ -source 'https://rubygems.org' +source "https://rubygems.org" gemspec diff --git a/Rakefile b/Rakefile index 8dfd4b22..c575548e 100644 --- a/Rakefile +++ b/Rakefile @@ -2,32 +2,32 @@ require "bundler/gem_tasks" require "rspec/core/rake_task" RSpec::Core::RakeTask.new(:spec) do |task| - task.rspec_opts = ['--color', '--format', 'documentation', '--require', 'spec_helper'] + task.rspec_opts = ["--color", "--format", "documentation", "--require", "spec_helper"] end desc "Open an irb session preloaded with this library" task :console do # Load all gems - require 'rubygems' - require 'bundler/setup' + require "rubygems" + require "bundler/setup" Bundler.require(:default) # Load the envs - require 'dotenv' + require "dotenv" Dotenv.load! # Set up a global client def client @client ||= begin - client = TeslaApi::Client.new(email: ENV['TESLA_EMAIL']) - client.login!(ENV['TESLA_PASS']) - client + client = TeslaApi::Client.new(email: ENV["TESLA_EMAIL"]) + client.login!(ENV["TESLA_PASS"]) + client end end # Load IRB - require 'irb' - require 'irb/completion' + require "irb" + require "irb/completion" IRB.conf[:PROMPT_MODE] = :SIMPLE IRB.conf[:AUTO_INDENT] = true diff --git a/lib/tesla_api.rb b/lib/tesla_api.rb index 882d7735..3fd77d24 100644 --- a/lib/tesla_api.rb +++ b/lib/tesla_api.rb @@ -1,15 +1,15 @@ -require 'date' -require 'base64' +require "date" +require "base64" -require 'faraday' -require 'faraday_middleware' +require "faraday" +require "faraday_middleware" -require 'async' -require 'async/http/endpoint' -require 'async/websocket/client' +require "async" +require "async/http/endpoint" +require "async/websocket/client" -require 'tesla_api/version' -require 'tesla_api/client' -require 'tesla_api/stream' -require 'tesla_api/autopark' -require 'tesla_api/vehicle' +require "tesla_api/version" +require "tesla_api/client" +require "tesla_api/stream" +require "tesla_api/autopark" +require "tesla_api/vehicle" diff --git a/lib/tesla_api/autopark.rb b/lib/tesla_api/autopark.rb index 03b7fbb6..67578756 100644 --- a/lib/tesla_api/autopark.rb +++ b/lib/tesla_api/autopark.rb @@ -3,13 +3,13 @@ module Autopark def start_autopark(&handler) Async do |task| Async::WebSocket::Client.connect(autopark_endpoint, headers: headers) do |connection| - while message = connection.read + while (message = connection.read) case message[:msg_type] - when 'control:hello' + when "control:hello" interval = message[:autopark][:heartbeat_frequency] / 1000.0 task.async do |subtask| subtask.sleep interval - connection.write({ msg_type: 'autopark:heartbeat_app', timestamp: Time.now.to_i }.to_json) + connection.write({msg_type: "autopark:heartbeat_app", timestamp: Time.now.to_i}.to_json) end end @@ -26,17 +26,17 @@ def autopark_endpoint end def autopark_endpoint_url - "wss://streaming.vn.teslamotors.com/connect/#{self['vehicle_id']}" + "wss://streaming.vn.teslamotors.com/connect/#{self["vehicle_id"]}" end def autopark_headers { - 'Authorization' => "Basic #{socket_auth}" + "Authorization" => "Basic #{socket_auth}" } end def autopark_socket_auth - Base64.strict_encode64("#{email}:#{self['tokens'].first}") + Base64.strict_encode64("#{email}:#{self["tokens"].first}") end end end diff --git a/lib/tesla_api/client.rb b/lib/tesla_api/client.rb index ab38b17b..79b9b20a 100644 --- a/lib/tesla_api/client.rb +++ b/lib/tesla_api/client.rb @@ -2,20 +2,20 @@ module TeslaApi class Client attr_reader :api, :email, :access_token, :access_token_expires_at, :refresh_token, :client_id, :client_secret - BASE_URI = 'https://owner-api.teslamotors.com' - SSO_URI = 'https://auth.tesla.com' + BASE_URI = "https://owner-api.teslamotors.com" + SSO_URI = "https://auth.tesla.com" def initialize( - email: nil, - access_token: nil, - access_token_expires_at: nil, - refresh_token: nil, - client_id: ENV['TESLA_CLIENT_ID'], - client_secret: ENV['TESLA_CLIENT_SECRET'], - retry_options: nil, - base_uri: nil, - sso_uri: nil, - client_options: {} + email: nil, + access_token: nil, + access_token_expires_at: nil, + refresh_token: nil, + client_id: ENV["TESLA_CLIENT_ID"], + client_secret: ENV["TESLA_CLIENT_SECRET"], + retry_options: nil, + base_uri: nil, + sso_uri: nil, + client_options: {} ) @email = email @base_uri = base_uri || BASE_URI @@ -29,45 +29,45 @@ def initialize( @refresh_token = refresh_token @api = Faraday.new( - @base_uri + '/api/1', + @base_uri + "/api/1", { - headers: { 'User-Agent' => "github.com/timdorr/tesla-api v:#{VERSION}" } + headers: {"User-Agent" => "github.com/timdorr/tesla-api v:#{VERSION}"} }.merge(client_options) - ) do |conn| + ) { |conn| conn.request :json conn.response :json conn.response :raise_error conn.request :retry, retry_options if retry_options # Must be registered after :raise_error conn.adapter Faraday.default_adapter - end + } end def refresh_access_token response = @api.post( - @sso_uri + '/oauth2/v3/token', + @sso_uri + "/oauth2/v3/token", { - grant_type: 'refresh_token', - client_id: 'ownerapi', + grant_type: "refresh_token", + client_id: "ownerapi", client_secret: client_secret, refresh_token: refresh_token, - scope: 'openid email offline_access' + scope: "openid email offline_access" } ).body - @refresh_token = response['refresh_token'] + @refresh_token = response["refresh_token"] response = api.post( - @base_uri + '/oauth/token', + @base_uri + "/oauth/token", { - grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer', + grant_type: "urn:ietf:params:oauth:grant-type:jwt-bearer", client_id: client_id, client_secret: client_secret }, - 'Authorization' => "Bearer #{response['access_token']}" + "Authorization" => "Bearer #{response["access_token"]}" ).body - @access_token = response['access_token'] - @access_token_expires_at = Time.at(response['created_at'].to_f + response['expires_in'].to_f).to_datetime + @access_token = response["access_token"] + @access_token_expires_at = Time.at(response["created_at"].to_f + response["expires_in"].to_f).to_datetime response end @@ -78,65 +78,65 @@ def login!(password) state = rand(36**20).to_s(36) response = Faraday.get( - @sso_uri + '/oauth2/v3/authorize', + @sso_uri + "/oauth2/v3/authorize", { - client_id: 'ownerapi', + client_id: "ownerapi", code_challenge: code_challenge, - code_challenge_method: 'S256', - redirect_uri: 'https://auth.tesla.com/void/callback', - response_type: 'code', - scope: 'openid email offline_access', - state: state, + code_challenge_method: "S256", + redirect_uri: "https://auth.tesla.com/void/callback", + response_type: "code", + scope: "openid email offline_access", + state: state } ) - cookie = response.headers['set-cookie'].split(' ').first + cookie = response.headers["set-cookie"].split(" ").first parameters = Hash[response.body.scan(/type="hidden" name="(.*?)" value="(.*?)"/)] response = Faraday.post( - @sso_uri + '/oauth2/v3/authorize?' + URI.encode_www_form({ - client_id: 'ownerapi', + @sso_uri + "/oauth2/v3/authorize?" + URI.encode_www_form({ + client_id: "ownerapi", code_challenge: code_challenge, - code_challenge_method: 'S256', - redirect_uri: 'https://auth.tesla.com/void/callback', - response_type: 'code', - scope: 'openid email offline_access', - state: state, + code_challenge_method: "S256", + redirect_uri: "https://auth.tesla.com/void/callback", + response_type: "code", + scope: "openid email offline_access", + state: state }), URI.encode_www_form(parameters.merge( - 'identity' => email, - 'credential' => password + "identity" => email, + "credential" => password )), - 'Cookie' => cookie + "Cookie" => cookie ) - code = CGI.parse(URI(response.headers['location']).query)['code'].first + code = CGI.parse(URI(response.headers["location"]).query)["code"].first response = @api.post( - @sso_uri + '/oauth2/v3/token', + @sso_uri + "/oauth2/v3/token", { - grant_type: 'authorization_code', - client_id: 'ownerapi', + grant_type: "authorization_code", + client_id: "ownerapi", code: code, code_verifier: code_verifier, - redirect_uri: 'https://auth.tesla.com/void/callback' + redirect_uri: "https://auth.tesla.com/void/callback" } ).body - @refresh_token = response['refresh_token'] + @refresh_token = response["refresh_token"] response = api.post( - @base_uri + '/oauth/token', + @base_uri + "/oauth/token", { - grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer', + grant_type: "urn:ietf:params:oauth:grant-type:jwt-bearer", client_id: client_id, client_secret: client_secret }, - 'Authorization' => "Bearer #{response['access_token']}" + "Authorization" => "Bearer #{response["access_token"]}" ).body - @access_token = response['access_token'] - @access_token_expires_at = Time.at(response['created_at'].to_f + response['expires_in'].to_f).to_datetime + @access_token = response["access_token"] + @access_token_expires_at = Time.at(response["created_at"].to_f + response["expires_in"].to_f).to_datetime response end @@ -147,19 +147,19 @@ def expired? end def get(url) - api.get(url.sub(/^\//, ''), nil, { 'Authorization' => "Bearer #{access_token}" }).body + api.get(url.sub(/^\//, ""), nil, {"Authorization" => "Bearer #{access_token}"}).body end def post(url, body: nil) - api.post(url.sub(/^\//, ''), body, { 'Authorization' => "Bearer #{access_token}" }).body + api.post(url.sub(/^\//, ""), body, {"Authorization" => "Bearer #{access_token}"}).body end def vehicles - get('/vehicles')['response'].map { |v| Vehicle.new(self, email, v['id'], v) } + get("/vehicles")["response"].map { |v| Vehicle.new(self, email, v["id"], v) } end def vehicle(id) - Vehicle.new(self, email, id, self.get("/vehicles/#{id}")['response']) + Vehicle.new(self, email, id, get("/vehicles/#{id}")["response"]) end end end diff --git a/lib/tesla_api/stream.rb b/lib/tesla_api/stream.rb index 85701703..8d9a675b 100644 --- a/lib/tesla_api/stream.rb +++ b/lib/tesla_api/stream.rb @@ -1,7 +1,7 @@ module TeslaApi module Stream def self.streaming_endpoint_url - 'wss://streaming.vn.teslamotors.com/streaming/' + "wss://streaming.vn.teslamotors.com/streaming/" end def self.streaming_endpoint @@ -19,16 +19,16 @@ def stream(endpoint: Stream.streaming_endpoint, &receiver) connection.write(streaming_connect_message) timeout = task.async(&on_timeout) - while message = connection.read + while (message = connection.read) timeout.stop timeout = task.async(&on_timeout) case message[:msg_type] - when 'data:update' - attributes = message[:value].split(',') + when "data:update" + attributes = message[:value].split(",") receiver.call({ - time: DateTime.strptime((attributes[0].to_i/1000).to_s, '%s'), + time: DateTime.strptime((attributes[0].to_i / 1000).to_s, "%s"), speed: attributes[1].to_f, odometer: attributes[2].to_f, soc: attributes[3].to_f, @@ -42,7 +42,7 @@ def stream(endpoint: Stream.streaming_endpoint, &receiver) est_range: attributes[11].to_f, heading: attributes[12].to_f }) - when 'data:error' + when "data:error" task.stop end end @@ -56,10 +56,10 @@ def stream(endpoint: Stream.streaming_endpoint, &receiver) def streaming_connect_message { - msg_type: 'data:subscribe_oauth', + msg_type: "data:subscribe_oauth", token: client.access_token, - value: 'speed,odometer,soc,elevation,est_heading,est_lat,est_lng,power,shift_state,range,est_range,heading', - tag: self['vehicle_id'].to_s, + value: "speed,odometer,soc,elevation,est_heading,est_lat,est_lng,power,shift_state,range,est_range,heading", + tag: self["vehicle_id"].to_s } end end diff --git a/lib/tesla_api/vehicle.rb b/lib/tesla_api/vehicle.rb index 8cc21a90..df6f1f96 100644 --- a/lib/tesla_api/vehicle.rb +++ b/lib/tesla_api/vehicle.rb @@ -18,176 +18,180 @@ def [](key) end def method_missing(name) - if vehicle.keys.include?(name.to_s) + if vehicle.key?(name.to_s) vehicle[name.to_s] else raise NoMethodError.new("Vehicle does not have property `#{name}`", name) end end + def respond_to_missing?(name, include_private = false) + vehicle.key?(name.to_s) || super + end + # State def vehicle_data - client.get("/vehicles/#{id}/vehicle_data")['response'] + client.get("/vehicles/#{id}/vehicle_data")["response"] end def data - client.get("/vehicles/#{id}/data")['response'] + client.get("/vehicles/#{id}/data")["response"] end def mobile_enabled - client.get("/vehicles/#{id}/mobile_enabled")['response'] + client.get("/vehicles/#{id}/mobile_enabled")["response"] end def nearby_charging_sites - client.get("/vehicles/#{id}/nearby_charging_sites")['response'] + client.get("/vehicles/#{id}/nearby_charging_sites")["response"] end def gui_settings - data_request('gui_settings')['response'] + data_request("gui_settings")["response"] end def charge_state - data_request('charge_state')['response'] + data_request("charge_state")["response"] end def climate_state - data_request('climate_state')['response'] + data_request("climate_state")["response"] end def drive_state - data_request('drive_state')['response'] + data_request("drive_state")["response"] end def vehicle_state - data_request('vehicle_state')['response'] + data_request("vehicle_state")["response"] end def vehicle_config - data_request('vehicle_config')['response'] + data_request("vehicle_config")["response"] end # Commands def wake_up - @vehicle = client.post("/vehicles/#{id}/wake_up")['response'] + @vehicle = client.post("/vehicles/#{id}/wake_up")["response"] end - def set_valet_mode(on, password=nil) - command('set_valet_mode', body: {on: on, password: password})['response'] + def set_valet_mode(on, password = nil) + command("set_valet_mode", body: {on: on, password: password})["response"] end def reset_valet_pin - command('reset_valet_pin')['response'] + command("reset_valet_pin")["response"] end def charge_port_door_open - command('charge_port_door_open')['response'] + command("charge_port_door_open")["response"] end def charge_port_door_close - command('charge_port_door_close')['response'] + command("charge_port_door_close")["response"] end def charge_standard - command('charge_standard')['response'] + command("charge_standard")["response"] end def charge_max_range - command('charge_max_range')['response'] + command("charge_max_range")["response"] end def set_charge_limit(percent) - command('set_charge_limit', body: {percent: percent.to_i})['response'] + command("set_charge_limit", body: {percent: percent.to_i})["response"] end def charge_start - command('charge_start')['response'] + command("charge_start")["response"] end def charge_stop - command('charge_stop')['response'] + command("charge_stop")["response"] end def flash_lights - command('flash_lights')['response'] + command("flash_lights")["response"] end def honk_horn - command('honk_horn')['response'] + command("honk_horn")["response"] end def door_unlock - command('door_unlock')['response'] + command("door_unlock")["response"] end def door_lock - command('door_lock')['response'] + command("door_lock")["response"] end def set_temps(driver_temp, passenger_temp) - command('set_temps', body: {driver_temp: driver_temp, passenger_temp: passenger_temp})['response'] + command("set_temps", body: {driver_temp: driver_temp, passenger_temp: passenger_temp})["response"] end def set_preconditioning_max(on) - command('set_preconditioning_max', body: {on: on})['response'] + command("set_preconditioning_max", body: {on: on})["response"] end def auto_conditioning_start - command('auto_conditioning_start')['response'] + command("auto_conditioning_start")["response"] end def auto_conditioning_stop - command('auto_conditioning_stop')['response'] + command("auto_conditioning_stop")["response"] end def sun_roof_control(state) - command('sun_roof_control', body: {state: state})['response'] + command("sun_roof_control", body: {state: state})["response"] end def sun_roof_move(percent) - command('sun_roof_control', body: {state: 'move', percent: percent})['response'] + command("sun_roof_control", body: {state: "move", percent: percent})["response"] end def window_control(command) - command('window_control', body: {command: command, lat: 0, lon: 0})['response'] + command("window_control", body: {command: command, lat: 0, lon: 0})["response"] end def remote_start_drive(password) - command('remote_start_drive', body: {password: password})['response'] + command("remote_start_drive", body: {password: password})["response"] end def open_trunk - command('actuate_trunk', body: {which_trunk: 'rear'})['response'] + command("actuate_trunk", body: {which_trunk: "rear"})["response"] end def open_frunk - command('actuate_trunk', body: {which_trunk: 'front'})['response'] + command("actuate_trunk", body: {which_trunk: "front"})["response"] end def activate_speed_limit(pin) - command('speed_limit_activate', body: {pin: pin})['response'] + command("speed_limit_activate", body: {pin: pin})["response"] end def deactivate_speed_limit(pin) - command('speed_limit_deactivate', body: {pin: pin})['response'] + command("speed_limit_deactivate", body: {pin: pin})["response"] end def set_speed_limit(limit_mph) - command('speed_limit_set_limit', body: {limit_mph: limit_mph})['response'] + command("speed_limit_set_limit", body: {limit_mph: limit_mph})["response"] end def clear_speed_limit_pin(pin) - command('speed_limit_clear_pin', body: {pin: pin})['response'] + command("speed_limit_clear_pin", body: {pin: pin})["response"] end def navigation_request(address) - command('navigation_request', body: { - type: 'share_ext_content_raw', - locale: 'en-US', - timestamp_ms: Time.now.to_i, - value: {'android.intent.extra.TEXT' => address} - })['response'] + command("navigation_request", body: { + type: "share_ext_content_raw", + locale: "en-US", + timestamp_ms: Time.now.to_i, + value: {"android.intent.extra.TEXT" => address} + })["response"] end def share(text) @@ -195,55 +199,55 @@ def share(text) end def schedule_software_update(offset_sec = 0) - command('schedule_software_update', body: {offset_sec: offset_sec})['response'] + command("schedule_software_update", body: {offset_sec: offset_sec})["response"] end def cancel_software_update - command('cancel_software_update')['response'] + command("cancel_software_update")["response"] end def set_seat_heater(heater, level) - command('remote_seat_heater_request', body: {heater: heater, level: level})['response'] + command("remote_seat_heater_request", body: {heater: heater, level: level})["response"] end def set_steering_wheel_heater(on) - command('remote_steering_wheel_heater_request', body: {on: on})['response'] + command("remote_steering_wheel_heater_request", body: {on: on})["response"] end def set_sentry_mode(on) - command('set_sentry_mode', body: {on: on})['response'] + command("set_sentry_mode", body: {on: on})["response"] end def trigger_homelink(lat, lon) - command('trigger_homelink', body: {lat: lat, lon: lon})['response'] + command("trigger_homelink", body: {lat: lat, lon: lon})["response"] end def media_toggle_playback - command('media_toggle_playback')['response'] + command("media_toggle_playback")["response"] end def media_next_track - command('media_next_track')['response'] + command("media_next_track")["response"] end def media_prev_track - command('media_prev_track')['response'] + command("media_prev_track")["response"] end def media_next_fav - command('media_next_fav')['response'] + command("media_next_fav")["response"] end def media_prev_fav - command('media_prev_fav')['response'] + command("media_prev_fav")["response"] end def media_volume_up - command('media_volume_up')['response'] + command("media_volume_up")["response"] end def media_volume_down - command('media_volume_down')['response'] + command("media_volume_down")["response"] end private diff --git a/lib/tesla_api/version.rb b/lib/tesla_api/version.rb index 9b44a4e7..ee3825b2 100644 --- a/lib/tesla_api/version.rb +++ b/lib/tesla_api/version.rb @@ -1,3 +1,3 @@ module TeslaApi - VERSION = '3.1.0' + VERSION = "3.1.0" end diff --git a/spec/lib/tesla_api/client_spec.rb b/spec/lib/tesla_api/client_spec.rb index 24f14994..1fd7cbdb 100644 --- a/spec/lib/tesla_api/client_spec.rb +++ b/spec/lib/tesla_api/client_spec.rb @@ -1,87 +1,89 @@ -require 'spec_helper' +require "spec_helper" RSpec.describe TeslaApi::Client do - subject(:tesla_api) { TeslaApi::Client.new(email: ENV['TESLA_EMAIL']) } + subject(:tesla_api) { TeslaApi::Client.new(email: ENV["TESLA_EMAIL"]) } it { is_expected.to be_a(TeslaApi::Client) } - context 'password grant auth' do - describe '#new' do - it 'has no expiry date' do + context "password grant auth" do + describe "#new" do + it "has no expiry date" do expect(tesla_api.access_token_expires_at).to eq(nil) end - it 'has a expiry status set to true' do + it "has a expiry status set to true" do expect(tesla_api.expired?).to eq(true) end end - describe '#login!', vcr: { - cassette_name: 'client-login', + describe "#login!", vcr: { + cassette_name: "client-login", match_requests_on: [ - :method, + :method, VCR.request_matchers.uri_without_params(:code_challenge, :state) - ] + ] } do - it 'logs into the API' do - tesla_api.login!(ENV['TESLA_PASS']) + it "logs into the API" do + tesla_api.login!(ENV["TESLA_PASS"]) expect(a_request(:post, "https://#{URI.parse(TeslaApi::Client::BASE_URI).host}/oauth/token")).to have_been_made.once end - it 'obtains a Bearer token' do - tesla_api.login!(ENV['TESLA_PASS']) - expect(tesla_api.access_token).to start_with('qts-') + it "obtains a Bearer token" do + tesla_api.login!(ENV["TESLA_PASS"]) + expect(tesla_api.access_token).to start_with("qts-") end - it 'set a expiry date' do - tesla_api.login!(ENV['TESLA_PASS']) + it "set a expiry date" do + tesla_api.login!(ENV["TESLA_PASS"]) expect(tesla_api.access_token_expires_at).to eq(Time.at(1612019326 + 3888000).to_datetime) end - it 'obtains a refresh token' do - tesla_api.login!(ENV['TESLA_PASS']) - expect(tesla_api.refresh_token).to start_with('eyJ') + it "obtains a refresh token" do + tesla_api.login!(ENV["TESLA_PASS"]) + expect(tesla_api.refresh_token).to start_with("eyJ") end - it 'expose expiry status' do - tesla_api.login!(ENV['TESLA_PASS']) + it "expose expiry status" do + tesla_api.login!(ENV["TESLA_PASS"]) expect(tesla_api.expired?).to eq(false) end end end - context 'token grant auth' do - subject(:tesla_api) { TeslaApi::Client.new( + context "token grant auth" do + subject(:tesla_api) { + TeslaApi::Client.new( access_token: access_token, access_token_expires_at: DateTime.now + 1, refresh_token: refresh_token - ) } + ) + } - let(:access_token) { ENV['TESLA_ACCESS_TOKEN'] } - let(:refresh_token) { ENV['TESLA_REFRESH_TOKEN'] } + let(:access_token) { ENV["TESLA_ACCESS_TOKEN"] } + let(:refresh_token) { ENV["TESLA_REFRESH_TOKEN"] } - describe '#new' do - it 'is not expired' do + describe "#new" do + it "is not expired" do expect(tesla_api.expired?).to eq(false) end end - describe '#refresh_access_token', vcr: { - cassette_name: 'client-refresh', + describe "#refresh_access_token", vcr: { + cassette_name: "client-refresh", match_requests_on: [ - :method, + :method, VCR.request_matchers.uri_without_params(:code_challenge, :state) - ] + ] } do - it 'refreshes the access token' do + it "refreshes the access token" do tesla_api.refresh_access_token expect(tesla_api.access_token).not_to eq(access_token) end end end - describe '#vehicles', vcr: {cassette_name: 'client-vehicles'} do - it 'lists the vehicles on the account' do + describe "#vehicles", vcr: {cassette_name: "client-vehicles"} do + it "lists the vehicles on the account" do expect(tesla_api.vehicles).to include(TeslaApi::Vehicle) end end diff --git a/spec/lib/tesla_api/vehicle_spec.rb b/spec/lib/tesla_api/vehicle_spec.rb index 2b8b0141..fc777b91 100644 --- a/spec/lib/tesla_api/vehicle_spec.rb +++ b/spec/lib/tesla_api/vehicle_spec.rb @@ -1,402 +1,402 @@ -require 'spec_helper' +require "spec_helper" RSpec.describe TeslaApi::Vehicle do - let(:tesla_api) { TeslaApi::Client.new(access_token: ENV['TESLA_ACCESS_TOKEN']) } + let(:tesla_api) { TeslaApi::Client.new(access_token: ENV["TESLA_ACCESS_TOKEN"]) } subject(:vehicle) { tesla_api.vehicles.first } - describe '#[]', vcr: { cassette_name: 'vehicle' } do - it 'contains the vehicle name' do - expect(vehicle['display_name']).to eq('Nikola') + describe "#[]", vcr: {cassette_name: "vehicle"} do + it "contains the vehicle name" do + expect(vehicle["display_name"]).to eq("Nikola") end end - describe '#method_missing', vcr: {cassette_name: 'vehicle'} do - it 'doesn\'t provide dynamic methods for nonexistent properties' do - expect{vehicle.gas_level}.to raise_exception(NoMethodError) + describe "#method_missing", vcr: {cassette_name: "vehicle"} do + it "doesn't provide dynamic methods for nonexistent properties" do + expect { vehicle.gas_level }.to raise_exception(NoMethodError) end - it 'provides a dynamic method for the display_name' do - expect(vehicle.display_name).to eq('Nikola') + it "provides a dynamic method for the display_name" do + expect(vehicle.display_name).to eq("Nikola") end end - describe '#vehicle_data', vcr: {cassette_name: 'vehicle-vehicle_data'} do - context 'data about the vehicle\'s overall state' do + describe "#vehicle_data", vcr: {cassette_name: "vehicle-vehicle_data"} do + context "data about the vehicle's overall state" do subject { vehicle.data } - it { should include('display_name') } - it { should include('drive_state') } - it { should include('vehicle_state') } - it { should include('vehicle_config') } - it { should include('charge_state') } + it { should include("display_name") } + it { should include("drive_state") } + it { should include("vehicle_state") } + it { should include("vehicle_config") } + it { should include("charge_state") } end end - describe '#data', vcr: {cassette_name: 'vehicle-data'} do - context 'data about the vehicle\'s overall state' do + describe "#data", vcr: {cassette_name: "vehicle-data"} do + context "data about the vehicle's overall state" do subject { vehicle.data } - it { should include('display_name') } - it { should include('drive_state') } - it { should include('vehicle_state') } - it { should include('vehicle_config') } - it { should include('charge_state') } + it { should include("display_name") } + it { should include("drive_state") } + it { should include("vehicle_state") } + it { should include("vehicle_config") } + it { should include("charge_state") } end end - describe '#mobile_enabled', vcr: {cassette_name: 'vehicle-mobile_enabled'} do - it 'indicates if mobile app access is enabled' do + describe "#mobile_enabled", vcr: {cassette_name: "vehicle-mobile_enabled"} do + it "indicates if mobile app access is enabled" do expect(vehicle.mobile_enabled).to eq(true) end end - describe '#nearby_charging_sites', vcr: {cassette_name: 'vehicle-nearby_charging_sites'} do - pending 'returns a list of nearby charging sites' do + describe "#nearby_charging_sites", vcr: {cassette_name: "vehicle-nearby_charging_sites"} do + pending "returns a list of nearby charging sites" do expect(vehicle.nearby_charging_sites).to eq([]) end end - describe '#gui_settings', vcr: {cassette_name: 'vehicle-gui_settings'} do - context 'details for a GUI built on the API' do + describe "#gui_settings", vcr: {cassette_name: "vehicle-gui_settings"} do + context "details for a GUI built on the API" do subject { vehicle.gui_settings } - it { should include('gui_charge_rate_units') } - it { should include('gui_distance_units') } - it { should include('gui_temperature_units') } - it { should include('gui_range_display') } - it { should include('gui_24_hour_time') } + it { should include("gui_charge_rate_units") } + it { should include("gui_distance_units") } + it { should include("gui_temperature_units") } + it { should include("gui_range_display") } + it { should include("gui_24_hour_time") } end end - describe '#charge_state', vcr: {cassette_name: 'vehicle-charge_state'} do - context 'data about the vehicle\'s charging state' do + describe "#charge_state", vcr: {cassette_name: "vehicle-charge_state"} do + context "data about the vehicle's charging state" do subject { vehicle.charge_state } - it { should include('battery_level') } - it { should include('charge_rate') } - it { should include('charging_state') } - it { should include('est_battery_range') } - it { should include('fast_charger_present') } + it { should include("battery_level") } + it { should include("charge_rate") } + it { should include("charging_state") } + it { should include("est_battery_range") } + it { should include("fast_charger_present") } end end - describe '#climate_state', vcr: {cassette_name: 'vehicle-climate_state'} do - context 'data about the vehicle\'s climate controls and internal climate' do + describe "#climate_state", vcr: {cassette_name: "vehicle-climate_state"} do + context "data about the vehicle's climate controls and internal climate" do subject { vehicle.climate_state } - it { should include('inside_temp') } - it { should include('outside_temp') } - it { should include('driver_temp_setting') } - it { should include('passenger_temp_setting') } - it { should include('is_auto_conditioning_on') } + it { should include("inside_temp") } + it { should include("outside_temp") } + it { should include("driver_temp_setting") } + it { should include("passenger_temp_setting") } + it { should include("is_auto_conditioning_on") } end end - describe '#drive_state', vcr: {cassette_name: 'vehicle-drive_state'} do - context 'data about the vehicle\'s driving state' do + describe "#drive_state", vcr: {cassette_name: "vehicle-drive_state"} do + context "data about the vehicle's driving state" do subject { vehicle.drive_state } - it { should include('heading') } - it { should include('latitude') } - it { should include('longitude') } - it { should include('speed') } + it { should include("heading") } + it { should include("latitude") } + it { should include("longitude") } + it { should include("speed") } end end - describe '#vehicle_state', vcr: {cassette_name: 'vehicle-vehicle_state'} do - context 'data about the vehicle\'s overall state' do + describe "#vehicle_state", vcr: {cassette_name: "vehicle-vehicle_state"} do + context "data about the vehicle's overall state" do subject { vehicle.vehicle_state } - it { should include('vehicle_name') } - it { should include('exterior_color') } - it { should include('wheel_type') } - it { should include('has_spoiler') } - it { should include('calendar_supported') } - it { should include('locked') } + it { should include("vehicle_name") } + it { should include("exterior_color") } + it { should include("wheel_type") } + it { should include("has_spoiler") } + it { should include("calendar_supported") } + it { should include("locked") } end end - describe '#vehicle_config', vcr: {cassette_name: 'vehicle-vehicle_config'} do - context 'data about the vehicle\'s overall state' do + describe "#vehicle_config", vcr: {cassette_name: "vehicle-vehicle_config"} do + context "data about the vehicle's overall state" do subject { vehicle.vehicle_config } - it { should include('exterior_color') } - it { should include('wheel_type') } - it { should include('has_air_suspension') } - it { should include('car_type') } - it { should include('timestamp') } + it { should include("exterior_color") } + it { should include("wheel_type") } + it { should include("has_air_suspension") } + it { should include("car_type") } + it { should include("timestamp") } end end - describe '#wake_up', vcr: {cassette_name: 'vehicle-wake_up'} do - it 'wakes up the car from sleep mode' do + describe "#wake_up", vcr: {cassette_name: "vehicle-wake_up"} do + it "wakes up the car from sleep mode" do vehicle.wake_up - expect(vehicle.state).to eq('online') + expect(vehicle.state).to eq("online") end end - describe '#set_valet_mode', vcr: {cassette_name: 'vehicle-set_valet_mode'} do - it 'enables valet mode on the car' do - expect(vehicle.set_valet_mode(true, 1234)['result']).to eq(true) + describe "#set_valet_mode", vcr: {cassette_name: "vehicle-set_valet_mode"} do + it "enables valet mode on the car" do + expect(vehicle.set_valet_mode(true, 1234)["result"]).to eq(true) end - it 'enables valet mode with a previous PIN' do - expect(vehicle.set_valet_mode(true)['result']).to eq(true) + it "enables valet mode with a previous PIN" do + expect(vehicle.set_valet_mode(true)["result"]).to eq(true) end end - describe '#reset_valet_pin', vcr: {cassette_name: 'vehicle-reset_valet_pin'} do - it 'resets the valet mode PIN' do - expect(vehicle.reset_valet_pin['result']).to eq(true) + describe "#reset_valet_pin", vcr: {cassette_name: "vehicle-reset_valet_pin"} do + it "resets the valet mode PIN" do + expect(vehicle.reset_valet_pin["result"]).to eq(true) end end - describe '#charge_port_door_open', vcr: {cassette_name: 'vehicle-charge_port_door_open'} do - it 'opens the charge port door' do - expect(vehicle.charge_port_door_open['result']).to eq(true) + describe "#charge_port_door_open", vcr: {cassette_name: "vehicle-charge_port_door_open"} do + it "opens the charge port door" do + expect(vehicle.charge_port_door_open["result"]).to eq(true) end end - describe '#charge_standard' do - it 'sets the charge limit to standard (90%)', vcr: {cassette_name: 'vehicle-charge_standard'} do - expect(vehicle.charge_standard['result']).to eq(true) + describe "#charge_standard" do + it "sets the charge limit to standard (90%)", vcr: {cassette_name: "vehicle-charge_standard"} do + expect(vehicle.charge_standard["result"]).to eq(true) end - it 'doesn\'t set the charge rate to standard twice', vcr: {cassette_name: 'vehicle-charge_standard-twice'} do - expect(vehicle.charge_standard['result']).to eq(true) - expect(vehicle.charge_standard).to eq({'result' => false, 'reason' => 'already_standard'}) + it "doesn't set the charge rate to standard twice", vcr: {cassette_name: "vehicle-charge_standard-twice"} do + expect(vehicle.charge_standard["result"]).to eq(true) + expect(vehicle.charge_standard).to eq({"result" => false, "reason" => "already_standard"}) end end - describe '#charge_max_range' do - it 'sets the charge limit to max range (100%)', vcr: {cassette_name: 'vehicle-charge_max_range'} do - expect(vehicle.charge_max_range['result']).to eq(true) + describe "#charge_max_range" do + it "sets the charge limit to max range (100%)", vcr: {cassette_name: "vehicle-charge_max_range"} do + expect(vehicle.charge_max_range["result"]).to eq(true) end - it 'doesn\'t set the charge rate to max range twice', vcr: {cassette_name: 'vehicle-charge_max_range-twice'} do - expect(vehicle.charge_max_range['result']).to eq(true) - expect(vehicle.charge_max_range).to eq({'result' => false, 'reason' => 'already_max_range'}) + it "doesn't set the charge rate to max range twice", vcr: {cassette_name: "vehicle-charge_max_range-twice"} do + expect(vehicle.charge_max_range["result"]).to eq(true) + expect(vehicle.charge_max_range).to eq({"result" => false, "reason" => "already_max_range"}) end end - describe '#set_charge_limit' do - it 'sets the charge limit to 100%', vcr: {cassette_name: 'vehicle-set_charge_limit-100'} do - expect(vehicle.set_charge_limit(100)['result']).to eq(true) + describe "#set_charge_limit" do + it "sets the charge limit to 100%", vcr: {cassette_name: "vehicle-set_charge_limit-100"} do + expect(vehicle.set_charge_limit(100)["result"]).to eq(true) end - it 'sets the charge limit to 90%', vcr: {cassette_name: 'vehicle-set_charge_limit-90'} do - expect(vehicle.set_charge_limit(90)['result']).to eq(true) + it "sets the charge limit to 90%", vcr: {cassette_name: "vehicle-set_charge_limit-90"} do + expect(vehicle.set_charge_limit(90)["result"]).to eq(true) end - it 'sets the charge limit to 50%', vcr: {cassette_name: 'vehicle-set_charge_limit-50'} do - expect(vehicle.set_charge_limit(50)['result']).to eq(true) + it "sets the charge limit to 50%", vcr: {cassette_name: "vehicle-set_charge_limit-50"} do + expect(vehicle.set_charge_limit(50)["result"]).to eq(true) end - it 'doesn\'t actually set the charge limit to 1%', vcr: {cassette_name: 'vehicle-set_charge_limit-1'} do - expect(vehicle.set_charge_limit(1)['result']).to eq(true) - expect(vehicle.charge_state['charge_limit_soc']).to eq(50) + it "doesn't actually set the charge limit to 1%", vcr: {cassette_name: "vehicle-set_charge_limit-1"} do + expect(vehicle.set_charge_limit(1)["result"]).to eq(true) + expect(vehicle.charge_state["charge_limit_soc"]).to eq(50) end end - describe '#charge_port_door_open', vcr: {cassette_name: 'vehicle-charge_port_door_open'} do - it 'opens the charge port door' do - expect(vehicle.charge_port_door_open['result']).to eq(true) + describe "#charge_port_door_open", vcr: {cassette_name: "vehicle-charge_port_door_open"} do + it "opens the charge port door" do + expect(vehicle.charge_port_door_open["result"]).to eq(true) end end - describe '#charge_port_door_close', vcr: {cassette_name: 'vehicle-charge_port_door_close'} do - it 'closes the charge port door' do - expect(vehicle.charge_port_door_close['result']).to eq(true) + describe "#charge_port_door_close", vcr: {cassette_name: "vehicle-charge_port_door_close"} do + it "closes the charge port door" do + expect(vehicle.charge_port_door_close["result"]).to eq(true) end end - describe '#charge_start', vcr: {cassette_name: 'vehicle-charge_start'} do - it 'starts charging' do - expect(vehicle.charge_start['result']).to eq(true) + describe "#charge_start", vcr: {cassette_name: "vehicle-charge_start"} do + it "starts charging" do + expect(vehicle.charge_start["result"]).to eq(true) end end - describe '#charge_stop', vcr: {cassette_name: 'vehicle-charge_stop'} do - it 'stops charging' do - expect(vehicle.charge_stop['result']).to eq(true) + describe "#charge_stop", vcr: {cassette_name: "vehicle-charge_stop"} do + it "stops charging" do + expect(vehicle.charge_stop["result"]).to eq(true) end end - describe '#flash_lights', vcr: {cassette_name: 'vehicle-flash_lights'} do - it 'flashes the vehicle\'s lights' do - expect(vehicle.flash_lights['result']).to eq(true) + describe "#flash_lights", vcr: {cassette_name: "vehicle-flash_lights"} do + it "flashes the vehicle's lights" do + expect(vehicle.flash_lights["result"]).to eq(true) end end - describe '#honk_horn', vcr: {cassette_name: 'vehicle-honk_horn'} do - it 'honks the vehicle\'s horn' do - expect(vehicle.honk_horn['result']).to eq(true) + describe "#honk_horn", vcr: {cassette_name: "vehicle-honk_horn"} do + it "honks the vehicle's horn" do + expect(vehicle.honk_horn["result"]).to eq(true) end end - describe '#door_unlock', vcr: {cassette_name: 'vehicle-door_unlock'} do - it 'unlocks the vehicle\'s doors' do - expect(vehicle.door_unlock['result']).to eq(true) + describe "#door_unlock", vcr: {cassette_name: "vehicle-door_unlock"} do + it "unlocks the vehicle's doors" do + expect(vehicle.door_unlock["result"]).to eq(true) end end - describe '#door_lock', vcr: {cassette_name: 'vehicle-door_lock'} do - it 'locks the vehicle\'s doors' do - expect(vehicle.door_lock['result']).to eq(true) + describe "#door_lock", vcr: {cassette_name: "vehicle-door_lock"} do + it "locks the vehicle's doors" do + expect(vehicle.door_lock["result"]).to eq(true) end end - describe '#set_temps' do - it 'sets the desired temperature in the car to 70', vcr: {cassette_name: 'vehicle-set_temps-70-70'} do - expect(vehicle.set_temps(20.9, 20.9)['result']).to eq(true) + describe "#set_temps" do + it "sets the desired temperature in the car to 70", vcr: {cassette_name: "vehicle-set_temps-70-70"} do + expect(vehicle.set_temps(20.9, 20.9)["result"]).to eq(true) end - it 'sets the desired temperature in the car to 75 and 65', vcr: {cassette_name: 'vehicle-set_temps-75-65'} do - expect(vehicle.set_temps(23.7, 23.7)['result']).to eq(true) + it "sets the desired temperature in the car to 75 and 65", vcr: {cassette_name: "vehicle-set_temps-75-65"} do + expect(vehicle.set_temps(23.7, 23.7)["result"]).to eq(true) end end - describe '#auto_conditioning_start', vcr: {cassette_name: 'vehicle-auto_conditioning_start'} do - it 'starts the HVAC system' do - expect(vehicle.auto_conditioning_start['result']).to eq(true) + describe "#auto_conditioning_start", vcr: {cassette_name: "vehicle-auto_conditioning_start"} do + it "starts the HVAC system" do + expect(vehicle.auto_conditioning_start["result"]).to eq(true) end end - describe '#auto_conditioning_stop', vcr: {cassette_name: 'vehicle-auto_conditioning_stop'} do - it 'stops the HVAC system' do - expect(vehicle.auto_conditioning_stop['result']).to eq(true) + describe "#auto_conditioning_stop", vcr: {cassette_name: "vehicle-auto_conditioning_stop"} do + it "stops the HVAC system" do + expect(vehicle.auto_conditioning_stop["result"]).to eq(true) end end - describe '#sun_roof_control' do - it 'closes the sun roof', vcr: {cassette_name: 'vehicle-sun_roof_control-close'} do - expect(vehicle.sun_roof_control('close')['result']).to eq(true) + describe "#sun_roof_control" do + it "closes the sun roof", vcr: {cassette_name: "vehicle-sun_roof_control-close"} do + expect(vehicle.sun_roof_control("close")["result"]).to eq(true) end - it 'vents the sun roof', vcr: {cassette_name: 'vehicle-sun_roof_control-vent'} do - expect(vehicle.sun_roof_control('vent')['result']).to eq(true) + it "vents the sun roof", vcr: {cassette_name: "vehicle-sun_roof_control-vent"} do + expect(vehicle.sun_roof_control("vent")["result"]).to eq(true) end end - describe '#remote_start_drive', vcr: {cassette_name: 'vehicle-remote_start_drive'} do - it 'starts the vehicle\'s keyless driving mode' do - expect(vehicle.remote_start_drive('elon4eva')['result']).to eq(true) + describe "#remote_start_drive", vcr: {cassette_name: "vehicle-remote_start_drive"} do + it "starts the vehicle's keyless driving mode" do + expect(vehicle.remote_start_drive("elon4eva")["result"]).to eq(true) end end - describe '#open_trunk', vcr: {cassette_name: 'vehicle-open_trunk'} do - it 'opens the trunk' do - expect(vehicle.open_frunk['result']).to eq(true) + describe "#open_trunk", vcr: {cassette_name: "vehicle-open_trunk"} do + it "opens the trunk" do + expect(vehicle.open_frunk["result"]).to eq(true) end end - describe '#open_frunk', vcr: {cassette_name: 'vehicle-open_frunk'} do - it 'opens the frunk' do - expect(vehicle.open_frunk['result']).to eq(true) + describe "#open_frunk", vcr: {cassette_name: "vehicle-open_frunk"} do + it "opens the frunk" do + expect(vehicle.open_frunk["result"]).to eq(true) end end - describe '#activate_speed_limit', vcr: {cassette_name: 'vehicle-activate_speed_limit'} do - it 'activates the speed limit' do - expect(vehicle.activate_speed_limit('1234')['result']).to eq(true) + describe "#activate_speed_limit", vcr: {cassette_name: "vehicle-activate_speed_limit"} do + it "activates the speed limit" do + expect(vehicle.activate_speed_limit("1234")["result"]).to eq(true) end end - describe '#deactivate_speed_limit', vcr: {cassette_name: 'vehicle-deactivate_speed_limit'} do - it 'deactivates the speed limit' do - expect(vehicle.deactivate_speed_limit('1234')['result']).to eq(true) + describe "#deactivate_speed_limit", vcr: {cassette_name: "vehicle-deactivate_speed_limit"} do + it "deactivates the speed limit" do + expect(vehicle.deactivate_speed_limit("1234")["result"]).to eq(true) end end - describe '#set_speed_limit', vcr: {cassette_name: 'vehicle-set_speed_limit'} do - it 'sets the speed limit' do - expect(vehicle.set_speed_limit(65)['result']).to eq(true) + describe "#set_speed_limit", vcr: {cassette_name: "vehicle-set_speed_limit"} do + it "sets the speed limit" do + expect(vehicle.set_speed_limit(65)["result"]).to eq(true) end end - describe '#clear_speed_limit_pin', vcr: {cassette_name: 'vehicle-clear_speed_limit_pin'} do - it 'clears the speed limit pin' do - expect(vehicle.clear_speed_limit_pin('1234')['result']).to eq(true) + describe "#clear_speed_limit_pin", vcr: {cassette_name: "vehicle-clear_speed_limit_pin"} do + it "clears the speed limit pin" do + expect(vehicle.clear_speed_limit_pin("1234")["result"]).to eq(true) end end - describe '#navigation_request', vcr: {cassette_name: 'vehicle-navigation_request'} do - it 'makes a request to navigate to a new address' do - expect(vehicle.navigation_request('1180 W Peachtree St, Atlanta, GA 30309')['result']).to eq(true) + describe "#navigation_request", vcr: {cassette_name: "vehicle-navigation_request"} do + it "makes a request to navigate to a new address" do + expect(vehicle.navigation_request("1180 W Peachtree St, Atlanta, GA 30309")["result"]).to eq(true) end end - describe '#schedule_software_update', vcr: {cassette_name: 'vehicle-schedule_software_update'} do - it 'cancels a pending software update' do - expect(vehicle.schedule_software_update(7200)['result']).to eq(true) + describe "#schedule_software_update", vcr: {cassette_name: "vehicle-schedule_software_update"} do + it "cancels a pending software update" do + expect(vehicle.schedule_software_update(7200)["result"]).to eq(true) end end - describe '#cancel_software_update', vcr: {cassette_name: 'vehicle-cancel_software_update'} do - it 'cancels a pending software update' do - expect(vehicle.cancel_software_update['result']).to eq(true) + describe "#cancel_software_update", vcr: {cassette_name: "vehicle-cancel_software_update"} do + it "cancels a pending software update" do + expect(vehicle.cancel_software_update["result"]).to eq(true) end end - describe '#seat_heater_request', vcr: {cassette_name: 'vehicle-seat_heater_request'} do - it 'turns off the driver seat heater' do - expect(vehicle.set_seat_heater(1, 0)['result']).to eq(true) + describe "#seat_heater_request", vcr: {cassette_name: "vehicle-seat_heater_request"} do + it "turns off the driver seat heater" do + expect(vehicle.set_seat_heater(1, 0)["result"]).to eq(true) end end - describe '#steering_wheel_heater_request', vcr: {cassette_name: 'vehicle-steering_wheel_heater_request'} do - it 'turns off the steering wheel heater' do - expect(vehicle.set_steering_wheel_heater(false)['result']).to eq(true) + describe "#steering_wheel_heater_request", vcr: {cassette_name: "vehicle-steering_wheel_heater_request"} do + it "turns off the steering wheel heater" do + expect(vehicle.set_steering_wheel_heater(false)["result"]).to eq(true) end end - describe '#set_sentry_mode', vcr: {cassette_name: 'vehicle-set_sentry_mode'} do - it 'disables sentry mode' do - expect(vehicle.set_sentry_mode(false)['result']).to eq(true) + describe "#set_sentry_mode", vcr: {cassette_name: "vehicle-set_sentry_mode"} do + it "disables sentry mode" do + expect(vehicle.set_sentry_mode(false)["result"]).to eq(true) end end - context '#media' do - describe '#media_toggle_playback', vcr: {cassette_name: 'vehicle-media_toggle_playback'} do - it 'toggles media from playing and paused' do - expect(vehicle.media_toggle_playback['result']).to eq(true) + context "#media" do + describe "#media_toggle_playback", vcr: {cassette_name: "vehicle-media_toggle_playback"} do + it "toggles media from playing and paused" do + expect(vehicle.media_toggle_playback["result"]).to eq(true) end end - describe '#media_next_track', vcr: {cassette_name: 'vehicle-media_next_track'} do - it 'plays the next track in playlist' do - expect(vehicle.media_next_track['result']).to eq(true) + describe "#media_next_track", vcr: {cassette_name: "vehicle-media_next_track"} do + it "plays the next track in playlist" do + expect(vehicle.media_next_track["result"]).to eq(true) end end - describe '#media_prev_track', vcr: {cassette_name: 'vehicle-media_prev_track'} do - it 'plays the previous track in playlist' do - expect(vehicle.media_prev_track['result']).to eq(true) + describe "#media_prev_track", vcr: {cassette_name: "vehicle-media_prev_track"} do + it "plays the previous track in playlist" do + expect(vehicle.media_prev_track["result"]).to eq(true) end end - describe '#media_next_fav', vcr: {cassette_name: 'vehicle-media_next_fav'} do - it 'plays the next favourite track' do - expect(vehicle.media_next_fav['result']).to eq(true) + describe "#media_next_fav", vcr: {cassette_name: "vehicle-media_next_fav"} do + it "plays the next favourite track" do + expect(vehicle.media_next_fav["result"]).to eq(true) end end - describe '#media_prev_fav', vcr: {cassette_name: 'vehicle-media_prev_fav'} do - it 'plays the previous favourite track' do - expect(vehicle.media_prev_fav['result']).to eq(true) + describe "#media_prev_fav", vcr: {cassette_name: "vehicle-media_prev_fav"} do + it "plays the previous favourite track" do + expect(vehicle.media_prev_fav["result"]).to eq(true) end end - describe '#media_volume_up', vcr: {cassette_name: 'vehicle-media_volume_up'} do - it 'increases volume of media' do - expect(vehicle.media_volume_up['result']).to eq(true) + describe "#media_volume_up", vcr: {cassette_name: "vehicle-media_volume_up"} do + it "increases volume of media" do + expect(vehicle.media_volume_up["result"]).to eq(true) end end - describe '#media_volume_down', vcr: {cassette_name: 'vehicle-media_volume_down'} do - it 'decreases volume of media' do - expect(vehicle.media_volume_down['result']).to eq(true) + describe "#media_volume_down", vcr: {cassette_name: "vehicle-media_volume_down"} do + it "decreases volume of media" do + expect(vehicle.media_volume_down["result"]).to eq(true) end end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index dfcf8e01..ea76867a 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,23 +1,23 @@ -require 'dotenv' -require 'vcr' -require 'webmock/rspec' +require "dotenv" +require "vcr" +require "webmock/rspec" -require 'tesla_api' +require "tesla_api" Dotenv.load VCR.configure do |c| - c.cassette_library_dir = 'spec/cassettes' + c.cassette_library_dir = "spec/cassettes" c.hook_into :webmock - c.default_cassette_options = {:record => :once} + c.default_cassette_options = {record: :once} c.configure_rspec_metadata! - c.define_cassette_placeholder('') { CGI::escape(ENV['TESLA_EMAIL']) } - c.define_cassette_placeholder('') { ENV['TESLA_PASS'] } - c.define_cassette_placeholder('') { ENV['TESLA_CLIENT_ID'] } - c.define_cassette_placeholder('') { ENV['TESLA_CLIENT_SECRET'] } - c.define_cassette_placeholder('') { ENV['TESLA_ACCESS_TOKEN'] } - c.define_cassette_placeholder('') { ENV['TESLA_REFRESH_TOKEN'] } + c.define_cassette_placeholder("") { CGI.escape(ENV["TESLA_EMAIL"]) } + c.define_cassette_placeholder("") { ENV["TESLA_PASS"] } + c.define_cassette_placeholder("") { ENV["TESLA_CLIENT_ID"] } + c.define_cassette_placeholder("") { ENV["TESLA_CLIENT_SECRET"] } + c.define_cassette_placeholder("") { ENV["TESLA_ACCESS_TOKEN"] } + c.define_cassette_placeholder("") { ENV["TESLA_REFRESH_TOKEN"] } end RSpec.configure do |config| diff --git a/tesla_api.gemspec b/tesla_api.gemspec index f9866bb7..696383e0 100644 --- a/tesla_api.gemspec +++ b/tesla_api.gemspec @@ -1,27 +1,28 @@ -require File.expand_path('../lib/tesla_api/version', __FILE__) +require File.expand_path("../lib/tesla_api/version", __FILE__) Gem::Specification.new do |spec| - spec.name = 'tesla_api' - spec.version = TeslaApi::VERSION - spec.authors = ['Tim Dorr'] - spec.email = ['timdorr@timdorr.com'] - spec.summary = 'A wrapper for the Tesla JSON API' - spec.description = "Check the state of your Tesla Model S and issue basic commands. Stream data from the car's telematics system." - spec.homepage = 'https://github.com/timdorr/tesla-api' - spec.license = 'MIT' + spec.name = "tesla_api" + spec.version = TeslaApi::VERSION + spec.authors = ["Tim Dorr"] + spec.email = ["timdorr@timdorr.com"] + spec.summary = "A wrapper for the Tesla JSON API" + spec.description = "Check the state of your Tesla Model S and issue basic commands. Stream data from the car's telematics system." + spec.homepage = "https://github.com/timdorr/tesla-api" + spec.license = "MIT" - spec.files = `git ls-files -z`.split("\0") - spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) - spec.require_paths = ['lib'] + spec.files = `git ls-files -z`.split("\0") + spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) + spec.require_paths = ["lib"] - spec.add_dependency 'async-websocket' - spec.add_dependency 'faraday' - spec.add_dependency 'faraday_middleware' + spec.add_dependency "async-websocket" + spec.add_dependency "faraday" + spec.add_dependency "faraday_middleware" - spec.add_development_dependency 'bundler', '~> 2.0' - spec.add_development_dependency 'rake', '~> 13.0' - spec.add_development_dependency 'rspec', '~> 3.1' - spec.add_development_dependency 'vcr', '~> 6.0' - spec.add_development_dependency 'webmock', '~> 3.0' - spec.add_development_dependency 'dotenv', '~> 2.0' + spec.add_development_dependency "bundler", "~> 2.0" + spec.add_development_dependency "rake", "~> 13.0" + spec.add_development_dependency "rspec", "~> 3.1" + spec.add_development_dependency "standard", "~> 0.12" + spec.add_development_dependency "vcr", "~> 6.0" + spec.add_development_dependency "webmock", "~> 3.0" + spec.add_development_dependency "dotenv", "~> 2.0" end