From cd4a9fbbb4acf1b5361fa98f15e31f556774384d Mon Sep 17 00:00:00 2001 From: Adrian Kumpf Date: Sat, 6 Apr 2019 17:54:57 +0200 Subject: [PATCH] Test Log --- lib/tesla_mate/log.ex | 54 ++- lib/tesla_mate/log/state.ex | 1 + lib/tesla_mate/vehicles/vehicle.ex | 10 +- test/support/conn_case.ex | 3 +- test/tesla_mate/log/log_car_test.exs | 57 ++++ test/tesla_mate/log/log_charging_test.exs | 174 ++++++++++ test/tesla_mate/log/log_state_test.exs | 62 ++++ test/tesla_mate/log/log_test.exs | 393 ---------------------- test/tesla_mate/log/log_trip_test.exs | 187 ++++++++++ test/tesla_mate/vehicles/vehicle_test.exs | 14 - 10 files changed, 516 insertions(+), 439 deletions(-) create mode 100644 test/tesla_mate/log/log_car_test.exs create mode 100644 test/tesla_mate/log/log_charging_test.exs create mode 100644 test/tesla_mate/log/log_state_test.exs delete mode 100644 test/tesla_mate/log/log_test.exs create mode 100644 test/tesla_mate/log/log_trip_test.exs diff --git a/lib/tesla_mate/log.ex b/lib/tesla_mate/log.ex index 89317e08..72ae1683 100644 --- a/lib/tesla_mate/log.ex +++ b/lib/tesla_mate/log.ex @@ -40,7 +40,7 @@ defmodule TeslaMate.Log do alias TeslaMate.Log.State - def start_state(car_id, state) do + def start_state(car_id, state) when not is_nil(car_id) and not is_nil(state) do case get_current_state(car_id) do %State{state: ^state} -> :ok @@ -75,12 +75,9 @@ defmodule TeslaMate.Log do alias TeslaMate.Log.Position def insert_position(car_id, attrs) do - with {:ok, _} <- - %Position{car_id: car_id, trip_id: Map.get(attrs, :trip_id)} - |> Position.changeset(attrs) - |> Repo.insert() do - :ok - end + %Position{car_id: car_id, trip_id: Map.get(attrs, :trip_id)} + |> Position.changeset(attrs) + |> Repo.insert() end ## Trip @@ -125,23 +122,25 @@ defmodule TeslaMate.Log do }) |> Repo.one() - ideal_distance = stats.end_range_km - stats.start_range_km - efficiency = if ideal_distance > 0, do: stats.distance / ideal_distance, else: nil - consumption = ideal_distance * trip.car.efficiency - consumption_100km = if stats.distance > 0, do: consumption / stats.distance * 100, else: nil - - stats = - stats - |> Map.put(:efficiency, efficiency) - |> Map.put(:consumption_kWh, consumption) - |> Map.put(:consumption_kWh_100km, consumption_100km) - - trip = Trip.changeset(trip, stats) - - if stats.distance == 0 do - Repo.delete(trip) + if stats.distance in [nil, 0, 0.0] do + trip + |> Trip.changeset(stats) + |> Repo.delete() else - Repo.update(trip) + ideal_distance = stats.end_range_km - stats.start_range_km + efficiency = if ideal_distance > 0, do: stats.distance / ideal_distance, else: nil + consumption = ideal_distance * trip.car.efficiency + consumption_100km = if stats.distance > 0, do: consumption / stats.distance * 100, else: nil + + stats = + stats + |> Map.put(:efficiency, efficiency) + |> Map.put(:consumption_kWh, consumption) + |> Map.put(:consumption_kWh_100km, consumption_100km) + + trip + |> Trip.changeset(stats) + |> Repo.update() end end @@ -159,12 +158,9 @@ defmodule TeslaMate.Log do end def insert_charge(process_id, attrs) do - with {:ok, _} <- - %Charge{charging_process_id: process_id} - |> Charge.changeset(attrs) - |> Repo.insert() do - :ok - end + %Charge{charging_process_id: process_id} + |> Charge.changeset(attrs) + |> Repo.insert() end def close_charging_process(process_id) do diff --git a/lib/tesla_mate/log/state.ex b/lib/tesla_mate/log/state.ex index 38d85bf1..c3db3019 100644 --- a/lib/tesla_mate/log/state.ex +++ b/lib/tesla_mate/log/state.ex @@ -19,5 +19,6 @@ defmodule TeslaMate.Log.State do state |> cast(attrs, [:state, :start_date, :end_date]) |> validate_required([:car_id, :state, :start_date]) + |> foreign_key_constraint(:car_id) end end diff --git a/lib/tesla_mate/vehicles/vehicle.ex b/lib/tesla_mate/vehicles/vehicle.ex index e6b90a15..4e27ae36 100644 --- a/lib/tesla_mate/vehicles/vehicle.ex +++ b/lib/tesla_mate/vehicles/vehicle.ex @@ -78,6 +78,7 @@ defmodule TeslaMate.Vehicles.Vehicle do end # TODO + # - seperate suspend mode w/ previous state tuple to restore that state if suspending failed # - /wake_up & /sleep routes # - sleep time # - reverse adress lookup @@ -318,7 +319,10 @@ defmodule TeslaMate.Vehicles.Vehicle do defp insert_position(vehicle_state, data, opts) do position = create_position(vehicle_state, opts) - call(data.deps.log, :insert_position, [data.car_id, position]) + + with {:ok, _pos} <- call(data.deps.log, :insert_position, [data.car_id, position]) do + :ok + end end defp create_position(%Vehicle{drive_state: %State.Drive{}} = state, opts \\ []) do @@ -363,7 +367,9 @@ defmodule TeslaMate.Vehicles.Vehicle do outside_temp: state.climate_state.outside_temp } - :ok = call(data.deps.log, :insert_charge, [process_id, attrs]) + with {:ok, _} <- call(data.deps.log, :insert_charge, [process_id, attrs]) do + :ok + end end defp parse_timestamp(ts) do diff --git a/test/support/conn_case.ex b/test/support/conn_case.ex index effe3e7c..66455e71 100644 --- a/test/support/conn_case.ex +++ b/test/support/conn_case.ex @@ -33,7 +33,8 @@ defmodule TeslaMateWeb.ConnCase do Ecto.Adapters.SQL.Sandbox.mode(TeslaMate.Repo, {:shared, self()}) end - {:ok, _} = TeslaMateWeb.Endpoint.start_link() + # TODO remove and fix + TeslaMateWeb.Endpoint.start_link() {:ok, conn: Phoenix.ConnTest.build_conn()} end diff --git a/test/tesla_mate/log/log_car_test.exs b/test/tesla_mate/log/log_car_test.exs new file mode 100644 index 00000000..80845ddb --- /dev/null +++ b/test/tesla_mate/log/log_car_test.exs @@ -0,0 +1,57 @@ +defmodule TeslaMate.LogCarTest do + use TeslaMate.DataCase, async: true + + alias TeslaMate.Log.Car + alias TeslaMate.Log + + @valid_attrs %{efficiency: 0.153, eid: 42, model: "M3", vid: 42} + @update_attrs %{efficiency: 0.190, model: "MS", eid: 43, vid: 43} + @invalid_attrs %{efficiency: nil, eid: nil, model: nil, vid: nil} + + def car_fixture(attrs \\ %{}) do + {:ok, car} = + attrs + |> Enum.into(@valid_attrs) + |> Log.create_car() + + car + end + + test "list_cars/0 returns all car" do + car = car_fixture() + assert Log.list_cars() == [car] + end + + test "get_car!/1 returns the car with given id" do + car = car_fixture() + assert Log.get_car!(car.id) == car + end + + test "create_car/1 with valid data creates a car" do + assert {:ok, %Car{} = car} = Log.create_car(@valid_attrs) + assert car.efficiency == 0.153 + assert car.eid == 42 + assert car.model == "M3" + assert car.vid == 42 + end + + test "create_car/1 with invalid data returns error changeset" do + assert {:error, %Ecto.Changeset{}} = Log.create_car(@invalid_attrs) + end + + test "update_car/2 with valid data updates the car" do + car = car_fixture() + assert {:ok, %Car{} = car} = Log.update_car(car, @update_attrs) + + assert car.efficiency == 0.190 + assert car.model == "MS" + assert car.eid == 42 + assert car.vid == 42 + end + + test "update_car/2 with invalid data returns error changeset" do + car = car_fixture() + assert {:error, %Ecto.Changeset{}} = Log.update_car(car, @invalid_attrs) + assert car == Log.get_car!(car.id) + end +end diff --git a/test/tesla_mate/log/log_charging_test.exs b/test/tesla_mate/log/log_charging_test.exs new file mode 100644 index 00000000..aaa83aff --- /dev/null +++ b/test/tesla_mate/log/log_charging_test.exs @@ -0,0 +1,174 @@ +defmodule TeslaMate.LogTripChargingTest do + use TeslaMate.DataCase, async: true + + alias TeslaMate.Log.{Car, ChargingProcess, Charge} + alias TeslaMate.Log + + def car_fixture(attrs \\ %{}) do + {:ok, car} = + attrs + |> Enum.into(%{efficiency: 0.153, eid: 42, model: "M3", vid: 42}) + |> Log.create_car() + + car + end + + @valid_attrs %{ + date: DateTime.utc_now(), + charger_power: 50, + charger_phases: 3, + charge_energy_added: 0.160, + ideal_battery_range_km: 250 + } + + describe "start_charging_process/2" do + @valid_pos_attrs %{date: DateTime.utc_now(), latitude: 0.0, longitude: 0.0} + + test "with valid data creates a position" do + assert %Car{id: car_id} = car_fixture() + + assert {:ok, charging_process_id} = Log.start_charging_process(car_id, @valid_pos_attrs) + + assert cproc = + %ChargingProcess{} = + ChargingProcess + |> preload([:position]) + |> Repo.get(charging_process_id) + + assert cproc.car_id == car_id + assert cproc.position.latitude == @valid_pos_attrs.latitude + assert cproc.position.longitude == @valid_pos_attrs.longitude + assert cproc.position.date == DateTime.truncate(@valid_pos_attrs.date, :second) + assert %DateTime{} = cproc.start_date + end + + test "with invalid data returns error changeset" do + assert {:error, %Ecto.Changeset{} = changeset} = Log.start_charging_process(nil, %{}) + + assert errors_on(changeset) == %{ + car_id: ["can't be blank"], + position: %{ + car_id: ["can't be blank"], + date: ["can't be blank"], + latitude: ["can't be blank"], + longitude: ["can't be blank"] + } + } + end + end + + describe "insert_charge/2" do + test "with valid data creates a position" do + assert %Car{id: car_id} = car_fixture() + assert {:ok, charging_process_id} = Log.start_charging_process(car_id, @valid_pos_attrs) + assert {:ok, %Charge{} = charge} = Log.insert_charge(charging_process_id, @valid_attrs) + + assert charge.charging_process_id == charging_process_id + assert charge.date == DateTime.truncate(@valid_attrs.date, :second) + assert charge.charger_phases == @valid_attrs.charger_phases + assert charge.charger_power == @valid_attrs.charger_power + assert charge.charge_energy_added == @valid_attrs.charge_energy_added + assert charge.ideal_battery_range_km == @valid_attrs.ideal_battery_range_km + end + + test "with invalid data returns error changeset" do + assert %Car{id: car_id} = car_fixture() + assert {:ok, charging_process_id} = Log.start_charging_process(car_id, @valid_pos_attrs) + + assert {:error, %Ecto.Changeset{} = changeset} = + Log.insert_charge(charging_process_id, %{charger_phases: 0}) + + assert errors_on(changeset) == %{ + charger_phases: ["must be greater than 0"], + charge_energy_added: ["can't be blank"], + charger_power: ["can't be blank"], + date: ["can't be blank"], + ideal_battery_range_km: ["can't be blank"] + } + end + end + + describe "close_charging_process/1" do + test "aggregates charging data" do + assert %Car{id: car_id} = car_fixture() + assert {:ok, charging_process_id} = Log.start_charging_process(car_id, @valid_pos_attrs) + + charges = [ + %{ + date: "2019-04-05 16:01:27", + battery_level: 50, + charge_energy_added: 0.41, + charger_actual_current: 5, + charger_phases: 3, + charger_pilot_current: 16, + charger_power: 4, + charger_voltage: 234, + ideal_battery_range_km: 266.6, + outside_temp: 16 + }, + %{ + date: "2019-04-05 16:02:28", + battery_level: 51, + charge_energy_added: 0.51, + charger_actual_current: 5, + charger_phases: 3, + charger_pilot_current: 16, + charger_power: 4, + charger_voltage: 234, + ideal_battery_range_km: 267.3, + outside_temp: 15.5 + }, + %{ + date: "2019-04-05 16:04:34", + battery_level: 52, + charge_energy_added: 0.72, + charger_actual_current: 5, + charger_phases: 3, + charger_pilot_current: 16, + charger_power: 4, + charger_voltage: 234, + ideal_battery_range_km: 268.6, + outside_temp: 15 + }, + %{ + date: "2019-04-05 16:05:40", + battery_level: 54, + charge_energy_added: 0.72, + charger_actual_current: 5, + charger_phases: 3, + charger_pilot_current: 16, + charger_power: 4, + charger_voltage: 234, + ideal_battery_range_km: 268.6, + outside_temp: 14.5 + } + ] + + for c <- charges do + assert {:ok, %Charge{} = charge} = Log.insert_charge(charging_process_id, c) + end + + assert {:ok, %ChargingProcess{} = cproc} = Log.close_charging_process(charging_process_id) + + assert %DateTime{} = cproc.start_date + assert %DateTime{} = cproc.end_date + assert cproc.calculated_max_range == 497 + assert cproc.charge_energy_added == 0.72 + assert cproc.duration_min == 4 + assert cproc.end_battery_level == 54 + assert cproc.start_battery_level == 50 + assert cproc.start_soc == 266.6 + assert cproc.end_soc == 268.6 + assert cproc.outside_temp_avg == 15.25 + end + + test "closes charging process with zero charges " do + assert %Car{id: car_id} = car_fixture() + assert {:ok, charging_process_id} = Log.start_charging_process(car_id, @valid_pos_attrs) + assert {:ok, %ChargingProcess{} = cproc} = Log.close_charging_process(charging_process_id) + + assert %DateTime{} = cproc.start_date + assert %DateTime{} = cproc.end_date + end + end +end diff --git a/test/tesla_mate/log/log_state_test.exs b/test/tesla_mate/log/log_state_test.exs new file mode 100644 index 00000000..a4214f52 --- /dev/null +++ b/test/tesla_mate/log/log_state_test.exs @@ -0,0 +1,62 @@ +defmodule TeslaMate.LogStateTest do + use TeslaMate.DataCase, async: true + + alias TeslaMate.Log.{State, Car} + alias TeslaMate.Log + + def car_fixture(attrs \\ %{}) do + {:ok, car} = + attrs + |> Enum.into(%{efficiency: 0.153, eid: 42, model: "M3", vid: 42}) + |> Log.create_car() + + car + end + + describe "create_state/1 " do + test "with valid data creates a state" do + assert %Car{id: car_id} = car_fixture() + assert :ok = Log.start_state(car_id, :online) + + assert [%State{} = state] = Repo.all(State) + assert state.car_id == car_id + assert %DateTime{} = state.start_date + assert state.end_date == nil + assert state.state == :online + end + + test "does not create a new state if the state is already open" do + assert %Car{id: car_id} = car_fixture() + + assert :ok = Log.start_state(car_id, :online) + assert [%State{state: :online, start_date: start_date, end_date: nil}] = Repo.all(State) + + assert :ok = Log.start_state(car_id, :online) + assert [%State{state: :online, start_date: start_date, end_date: nil}] = Repo.all(State) + end + + test "closes the previous state if the state changed" do + assert %Car{id: car_id} = car_fixture() + + assert :ok = Log.start_state(car_id, :online) + assert [%State{state: :online, start_date: start_date, end_date: nil}] = Repo.all(State) + + :timer.sleep(10) + + assert :ok = Log.start_state(car_id, :offline) + + assert [ + %State{state: :online, start_date: ^start_date, end_date: end_date}, + %State{state: :offline, start_date: end_date, end_date: nil} + ] = Repo.all(State) + end + + test "with invalid data returns error changeset" do + assert {:error, %Ecto.Changeset{} = changeset} = Log.start_state(404, :foo) + assert errors_on(changeset) == %{state: ["is invalid"]} + + assert {:error, %Ecto.Changeset{} = changeset} = Log.start_state(404, :asleep) + assert errors_on(changeset) == %{car_id: ["does not exist"]} + end + end +end diff --git a/test/tesla_mate/log/log_test.exs b/test/tesla_mate/log/log_test.exs deleted file mode 100644 index 7029fbfe..00000000 --- a/test/tesla_mate/log/log_test.exs +++ /dev/null @@ -1,393 +0,0 @@ -defmodule TeslaMate.LogTest do - use TeslaMate.DataCase - - alias TeslaMate.Log - - # describe "positions" do - # alias TeslaMate.Log.Position - - # @valid_attrs %{name: "some name"} - # @update_attrs %{name: "some updated name"} - # @invalid_attrs %{name: nil} - - # def position_fixture(attrs \\ %{}) do - # {:ok, position} = - # attrs - # |> Enum.into(@valid_attrs) - # |> Log.create_position() - - # position - # end - - # test "list_positions/0 returns all positions" do - # position = position_fixture() - # assert Log.list_positions() == [position] - # end - - # test "get_position!/1 returns the position with given id" do - # position = position_fixture() - # assert Log.get_position!(position.id) == position - # end - - # test "create_position/1 with valid data creates a position" do - # assert {:ok, %Position{} = position} = Log.create_position(@valid_attrs) - # assert position.name == "some name" - # end - - # test "create_position/1 with invalid data returns error changeset" do - # assert {:error, %Ecto.Changeset{}} = Log.create_position(@invalid_attrs) - # end - - # test "update_position/2 with valid data updates the position" do - # position = position_fixture() - # assert {:ok, %Position{} = position} = Log.update_position(position, @update_attrs) - # assert position.name == "some updated name" - # end - - # test "update_position/2 with invalid data returns error changeset" do - # position = position_fixture() - # assert {:error, %Ecto.Changeset{}} = Log.update_position(position, @invalid_attrs) - # assert position == Log.get_position!(position.id) - # end - - # test "delete_position/1 deletes the position" do - # position = position_fixture() - # assert {:ok, %Position{}} = Log.delete_position(position) - # assert_raise Ecto.NoResultsError, fn -> Log.get_position!(position.id) end - # end - - # test "change_position/1 returns a position changeset" do - # position = position_fixture() - # assert %Ecto.Changeset{} = Log.change_position(position) - # end - # end - - # describe "states" do - # alias TeslaMate.Log.State - - # @valid_attrs %{end_date: "2010-04-17T14:00:00Z", end_position_id: 42, start_data: "2010-04-17T14:00:00Z", start_position_id: 42, state: "some state"} - # @update_attrs %{end_date: "2011-05-18T15:01:01Z", end_position_id: 43, start_data: "2011-05-18T15:01:01Z", start_position_id: 43, state: "some updated state"} - # @invalid_attrs %{end_date: nil, end_position_id: nil, start_data: nil, start_position_id: nil, state: nil} - - # def state_fixture(attrs \\ %{}) do - # {:ok, state} = - # attrs - # |> Enum.into(@valid_attrs) - # |> Log.create_state() - - # state - # end - - # test "list_states/0 returns all states" do - # state = state_fixture() - # assert Log.list_states() == [state] - # end - - # test "get_state!/1 returns the state with given id" do - # state = state_fixture() - # assert Log.get_state!(state.id) == state - # end - - # test "create_state/1 with valid data creates a state" do - # assert {:ok, %State{} = state} = Log.create_state(@valid_attrs) - # assert state.end_date == DateTime.from_naive!(~N[2010-04-17T14:00:00Z], "Etc/UTC") - # assert state.end_position_id == 42 - # assert state.start_data == DateTime.from_naive!(~N[2010-04-17T14:00:00Z], "Etc/UTC") - # assert state.start_position_id == 42 - # assert state.state == "some state" - # end - - # test "create_state/1 with invalid data returns error changeset" do - # assert {:error, %Ecto.Changeset{}} = Log.create_state(@invalid_attrs) - # end - - # test "update_state/2 with valid data updates the state" do - # state = state_fixture() - # assert {:ok, %State{} = state} = Log.update_state(state, @update_attrs) - # assert state.end_date == DateTime.from_naive!(~N[2011-05-18T15:01:01Z], "Etc/UTC") - # assert state.end_position_id == 43 - # assert state.start_data == DateTime.from_naive!(~N[2011-05-18T15:01:01Z], "Etc/UTC") - # assert state.start_position_id == 43 - # assert state.state == "some updated state" - # end - - # test "update_state/2 with invalid data returns error changeset" do - # state = state_fixture() - # assert {:error, %Ecto.Changeset{}} = Log.update_state(state, @invalid_attrs) - # assert state == Log.get_state!(state.id) - # end - - # test "delete_state/1 deletes the state" do - # state = state_fixture() - # assert {:ok, %State{}} = Log.delete_state(state) - # assert_raise Ecto.NoResultsError, fn -> Log.get_state!(state.id) end - # end - - # test "change_state/1 returns a state changeset" do - # state = state_fixture() - # assert %Ecto.Changeset{} = Log.change_state(state) - # end - # end - - # describe "trips" do - # alias TeslaMate.Log.Trip - - # @valid_attrs %{end_date: "2010-04-17T14:00:00Z", end_position_id: 42, start_date: "2010-04-17T14:00:00Z", start_position_id: 42} - # @update_attrs %{end_date: "2011-05-18T15:01:01Z", end_position_id: 43, start_date: "2011-05-18T15:01:01Z", start_position_id: 43} - # @invalid_attrs %{end_date: nil, end_position_id: nil, start_date: nil, start_position_id: nil} - - # def trip_fixture(attrs \\ %{}) do - # {:ok, trip} = - # attrs - # |> Enum.into(@valid_attrs) - # |> Log.create_trip() - - # trip - # end - - # test "list_trips/0 returns all trips" do - # trip = trip_fixture() - # assert Log.list_trips() == [trip] - # end - - # test "get_trip!/1 returns the trip with given id" do - # trip = trip_fixture() - # assert Log.get_trip!(trip.id) == trip - # end - - # test "create_trip/1 with valid data creates a trip" do - # assert {:ok, %Trip{} = trip} = Log.create_trip(@valid_attrs) - # assert trip.end_date == DateTime.from_naive!(~N[2010-04-17T14:00:00Z], "Etc/UTC") - # assert trip.end_position_id == 42 - # assert trip.start_date == DateTime.from_naive!(~N[2010-04-17T14:00:00Z], "Etc/UTC") - # assert trip.start_position_id == 42 - # end - - # test "create_trip/1 with invalid data returns error changeset" do - # assert {:error, %Ecto.Changeset{}} = Log.create_trip(@invalid_attrs) - # end - - # test "update_trip/2 with valid data updates the trip" do - # trip = trip_fixture() - # assert {:ok, %Trip{} = trip} = Log.update_trip(trip, @update_attrs) - # assert trip.end_date == DateTime.from_naive!(~N[2011-05-18T15:01:01Z], "Etc/UTC") - # assert trip.end_position_id == 43 - # assert trip.start_date == DateTime.from_naive!(~N[2011-05-18T15:01:01Z], "Etc/UTC") - # assert trip.start_position_id == 43 - # end - - # test "update_trip/2 with invalid data returns error changeset" do - # trip = trip_fixture() - # assert {:error, %Ecto.Changeset{}} = Log.update_trip(trip, @invalid_attrs) - # assert trip == Log.get_trip!(trip.id) - # end - - # test "delete_trip/1 deletes the trip" do - # trip = trip_fixture() - # assert {:ok, %Trip{}} = Log.delete_trip(trip) - # assert_raise Ecto.NoResultsError, fn -> Log.get_trip!(trip.id) end - # end - - # test "change_trip/1 returns a trip changeset" do - # trip = trip_fixture() - # assert %Ecto.Changeset{} = Log.change_trip(trip) - # end - # end - - # describe "charging_states" do - # alias TeslaMate.Log.ChargingProcess - - # @valid_attrs %{end_date: "2010-04-17T14:00:00Z", start_date: "2010-04-17T14:00:00Z"} - # @update_attrs %{end_date: "2011-05-18T15:01:01Z", start_date: "2011-05-18T15:01:01Z"} - # @invalid_attrs %{end_date: nil, start_date: nil} - - # def charging_state_fixture(attrs \\ %{}) do - # {:ok, charging_state} = - # attrs - # |> Enum.into(@valid_attrs) - # |> Log.create_charging_state() - - # charging_state - # end - - # test "list_charging_states/0 returns all charging_states" do - # charging_state = charging_state_fixture() - # assert Log.list_charging_states() == [charging_state] - # end - - # test "get_charging_state!/1 returns the charging_state with given id" do - # charging_state = charging_state_fixture() - # assert Log.get_charging_state!(charging_state.id) == charging_state - # end - - # test "create_charging_state/1 with valid data creates a charging_state" do - # assert {:ok, %ChargingProcess{} = charging_state} = Log.create_charging_state(@valid_attrs) - # assert charging_state.end_date == DateTime.from_naive!(~N[2010-04-17T14:00:00Z], "Etc/UTC") - # assert charging_state.start_date == DateTime.from_naive!(~N[2010-04-17T14:00:00Z], "Etc/UTC") - # end - - # test "create_charging_state/1 with invalid data returns error changeset" do - # assert {:error, %Ecto.Changeset{}} = Log.create_charging_state(@invalid_attrs) - # end - - # test "update_charging_state/2 with valid data updates the charging_state" do - # charging_state = charging_state_fixture() - # assert {:ok, %ChargingProcess{} = charging_state} = Log.update_charging_state(charging_state, @update_attrs) - # assert charging_state.end_date == DateTime.from_naive!(~N[2011-05-18T15:01:01Z], "Etc/UTC") - # assert charging_state.start_date == DateTime.from_naive!(~N[2011-05-18T15:01:01Z], "Etc/UTC") - # end - - # test "update_charging_state/2 with invalid data returns error changeset" do - # charging_state = charging_state_fixture() - # assert {:error, %Ecto.Changeset{}} = Log.update_charging_state(charging_state, @invalid_attrs) - # assert charging_state == Log.get_charging_state!(charging_state.id) - # end - - # test "delete_charging_state/1 deletes the charging_state" do - # charging_state = charging_state_fixture() - # assert {:ok, %ChargingProcess{}} = Log.delete_charging_state(charging_state) - # assert_raise Ecto.NoResultsError, fn -> Log.get_charging_state!(charging_state.id) end - # end - - # test "change_charging_state/1 returns a charging_state changeset" do - # charging_state = charging_state_fixture() - # assert %Ecto.Changeset{} = Log.change_charging_state(charging_state) - # end - # end - - # describe "charges" do - # alias TeslaMate.Log.Charge - - # @valid_attrs %{battery_level: 120.5, charge_energy_added: 120.5, charger_actual_current: 42, charger_phases: 42, charger_power: 120.5, charger_voltage: 42, date: "2010-04-17T14:00:00Z", ideal_battery_range_km: 120.5, outside_temp: 120.5} - # @update_attrs %{battery_level: 456.7, charge_energy_added: 456.7, charger_actual_current: 43, charger_phases: 43, charger_power: 456.7, charger_voltage: 43, date: "2011-05-18T15:01:01Z", ideal_battery_range_km: 456.7, outside_temp: 456.7} - # @invalid_attrs %{battery_level: nil, charge_energy_added: nil, charger_actual_current: nil, charger_phases: nil, charger_power: nil, charger_voltage: nil, date: nil, ideal_battery_range_km: nil, outside_temp: nil} - - # def charge_fixture(attrs \\ %{}) do - # {:ok, charge} = - # attrs - # |> Enum.into(@valid_attrs) - # |> Log.create_charge() - - # charge - # end - - # test "list_charges/0 returns all charges" do - # charge = charge_fixture() - # assert Log.list_charges() == [charge] - # end - - # test "get_charge!/1 returns the charge with given id" do - # charge = charge_fixture() - # assert Log.get_charge!(charge.id) == charge - # end - - # test "create_charge/1 with valid data creates a charge" do - # assert {:ok, %Charge{} = charge} = Log.create_charge(@valid_attrs) - # assert charge.battery_level == 120.5 - # assert charge.charge_energy_added == 120.5 - # assert charge.charger_actual_current == 42 - # assert charge.charger_phases == 42 - # assert charge.charger_power == 120.5 - # assert charge.charger_voltage == 42 - # assert charge.date == DateTime.from_naive!(~N[2010-04-17T14:00:00Z], "Etc/UTC") - # assert charge.ideal_battery_range_km == 120.5 - # assert charge.outside_temp == 120.5 - # end - - # test "create_charge/1 with invalid data returns error changeset" do - # assert {:error, %Ecto.Changeset{}} = Log.create_charge(@invalid_attrs) - # end - - # test "update_charge/2 with valid data updates the charge" do - # charge = charge_fixture() - # assert {:ok, %Charge{} = charge} = Log.update_charge(charge, @update_attrs) - # assert charge.battery_level == 456.7 - # assert charge.charge_energy_added == 456.7 - # assert charge.charger_actual_current == 43 - # assert charge.charger_phases == 43 - # assert charge.charger_power == 456.7 - # assert charge.charger_voltage == 43 - # assert charge.date == DateTime.from_naive!(~N[2011-05-18T15:01:01Z], "Etc/UTC") - # assert charge.ideal_battery_range_km == 456.7 - # assert charge.outside_temp == 456.7 - # end - - # test "update_charge/2 with invalid data returns error changeset" do - # charge = charge_fixture() - # assert {:error, %Ecto.Changeset{}} = Log.update_charge(charge, @invalid_attrs) - # assert charge == Log.get_charge!(charge.id) - # end - - # test "delete_charge/1 deletes the charge" do - # charge = charge_fixture() - # assert {:ok, %Charge{}} = Log.delete_charge(charge) - # assert_raise Ecto.NoResultsError, fn -> Log.get_charge!(charge.id) end - # end - - # test "change_charge/1 returns a charge changeset" do - # charge = charge_fixture() - # assert %Ecto.Changeset{} = Log.change_charge(charge) - # end - # end - - describe "car" do - alias TeslaMate.Log.Car - - @valid_attrs %{efficiency: 120.5, eid: 42, model: "some model", vid: 42} - @update_attrs %{ - efficiency: 456.7, - model: "some updated model", - eid: 43, - vid: 43 - } - @invalid_attrs %{efficiency: nil, eid: nil, model: nil, vid: nil} - - def car_fixture(attrs \\ %{}) do - {:ok, car} = - attrs - |> Enum.into(@valid_attrs) - |> Log.create_car() - - car - end - - test "list_cars/0 returns all car" do - car = car_fixture() - assert Log.list_cars() == [car] - end - - test "get_car!/1 returns the car with given id" do - car = car_fixture() - assert Log.get_car!(car.id) == car - end - - test "create_car/1 with valid data creates a car" do - assert {:ok, %Car{} = car} = Log.create_car(@valid_attrs) - assert car.efficiency == 120.5 - assert car.eid == 42 - assert car.model == "some model" - assert car.vid == 42 - end - - test "create_car/1 with invalid data returns error changeset" do - assert {:error, %Ecto.Changeset{}} = Log.create_car(@invalid_attrs) - end - - test "update_car/2 with valid data updates the car" do - car = car_fixture() - assert {:ok, %Car{} = car} = Log.update_car(car, @update_attrs) - - assert car.efficiency == 456.7 - assert car.model == "some updated model" - - assert car.eid == 42 - assert car.vid == 42 - end - - test "update_car/2 with invalid data returns error changeset" do - car = car_fixture() - assert {:error, %Ecto.Changeset{}} = Log.update_car(car, @invalid_attrs) - assert car == Log.get_car!(car.id) - end - end -end diff --git a/test/tesla_mate/log/log_trip_test.exs b/test/tesla_mate/log/log_trip_test.exs new file mode 100644 index 00000000..672de23f --- /dev/null +++ b/test/tesla_mate/log/log_trip_test.exs @@ -0,0 +1,187 @@ +defmodule TeslaMate.LogTripTest do + use TeslaMate.DataCase, async: true + + alias TeslaMate.Log.{Car, Position, Trip} + alias TeslaMate.Log + + @valid_attrs %{date: DateTime.utc_now(), latitude: 0.0, longitude: 0.0} + + def car_fixture(attrs \\ %{}) do + {:ok, car} = + attrs + |> Enum.into(%{efficiency: 0.153, eid: 42, model: "M3", vid: 42}) + |> Log.create_car() + + car + end + + test "start_trip/1 returns the trip_id" do + assert %car{id: car_id} = car_fixture() + assert {:ok, trip_id} = Log.start_trip(car_id) + assert is_number(trip_id) + end + + describe "insert_position/1" do + test "with valid data creates a position" do + assert %Car{id: car_id} = car_fixture() + + assert {:ok, %Position{} = position} = Log.insert_position(car_id, @valid_attrs) + assert %DateTime{} = position.date + assert position.car_id == car_id + assert position.longitude == 0.0 + assert position.latitude == 0.0 + end + + test "cannot insert positions for trips which don't exist" do + assert %Car{id: car_id} = car_fixture() + + attrs = Map.put(@valid_attrs, :trip_id, 404) + assert {:error, %Ecto.Changeset{} = changeset} = Log.insert_position(car_id, attrs) + assert errors_on(changeset) == %{trip_id: ["does not exist"]} + end + + test "with invalid data returns error changeset" do + assert {:error, %Ecto.Changeset{} = changeset} = Log.insert_position(nil, %{}) + + assert errors_on(changeset) == %{ + car_id: ["can't be blank"], + date: ["can't be blank"], + latitude: ["can't be blank"], + longitude: ["can't be blank"] + } + end + end + + describe "close_trip/2" do + test "aggregates trip data" do + assert %car{id: car_id} = car_fixture() + + positions = [ + %{ + date: "2019-04-06 10:19:02", + latitude: 50.112198, + longitude: 11.597669, + speed: 23, + power: 15, + odometer: 284.85156, + ideal_battery_range_km: 338.8, + battery_level: 68, + outside_temp: 19.2 + }, + %{ + date: "2019-04-06 10:20:08", + latitude: 50.112214, + longitude: 11.598471, + speed: 42, + power: -4, + odometer: 285.90556, + ideal_battery_range_km: 337.8, + battery_level: 68, + outside_temp: 19.0 + }, + %{ + date: "2019-04-06 10:21:14", + latitude: 50.112167, + longitude: 11.599395, + speed: 34, + power: -7, + odometer: 286.969561, + ideal_battery_range_km: 336.8, + battery_level: 68, + outside_temp: 21.0 + }, + %{ + date: "2019-04-06 10:22:20", + latitude: 50.112118, + longitude: 11.599919, + speed: 21, + power: 1, + odometer: 287.00556, + ideal_battery_range_km: 335.8, + battery_level: 68, + outside_temp: 18 + }, + %{ + date: "2019-04-06 10:23:25", + latitude: 50.11196, + longitude: 11.600445, + speed: 39, + power: 36, + odometer: 288.045561, + ideal_battery_range_km: 334.8, + battery_level: 68, + outside_temp: 18.0 + } + ] + + assert {:ok, trip_id} = Log.start_trip(car_id) + + for p <- positions do + assert {:ok, _} = Log.insert_position(car_id, Map.put(p, :trip_id, trip_id)) + end + + assert {:ok, trip} = Log.close_trip(trip_id) + + assert {:ok, trip.end_date, 0} == DateTime.from_iso8601("2019-04-06 10:23:25Z") + assert trip.outside_temp_avg == 19.04 + assert trip.speed_max == 42 + assert trip.power_max == 36.0 + assert trip.power_min == -7.0 + assert trip.power_avg == 8.2 + assert trip.start_km == 284.85156 + assert trip.end_km == 288.045561 + assert trip.distance == 3.1940010000000143 + assert trip.start_range_km == 334.8 + assert trip.end_range_km == 338.8 + assert trip.duration_min == 4 + assert trip.consumption_kWh == 0.612 + assert trip.consumption_kWh_100km == 19.160920738597053 + end + + test "deletes a trip and if it has no positions" do + assert %car{id: car_id} = car_fixture() + + assert {:ok, trip_id} = Log.start_trip(car_id) + assert %Trip{} = Repo.get(Trip, trip_id) + + assert {:ok, _trip} = Log.close_trip(trip_id) + assert nil == Repo.get(Trip, trip_id) + end + + test "deletes a trip and its position if the distance driven is 0" do + assert %car{id: car_id} = car_fixture() + + positions = [ + %{date: "2019-04-06 10:00:00", latitude: 0.0, longitude: 0.0, odometer: 100}, + %{date: "2019-04-06 10:00:00", latitude: 0.0, longitude: 0.0, odometer: 100} + ] + + assert {:ok, trip_id} = Log.start_trip(car_id) + + for p <- positions do + assert {:ok, _} = Log.insert_position(car_id, Map.put(p, :trip_id, trip_id)) + end + + assert {:ok, %Trip{distance: 0.0}} = Log.close_trip(trip_id) + assert nil == Repo.get(Trip, trip_id) + end + end + + test "deletes a trip and its position if the distance attributes are nil" do + assert %car{id: car_id} = car_fixture() + + positions = [ + %{date: "2019-04-06 10:00:00", latitude: 0.0, longitude: 0.0}, + %{date: "2019-04-06 10:00:00", latitude: 0.0, longitude: 0.0} + ] + + assert {:ok, trip_id} = Log.start_trip(car_id) + + for p <- positions do + assert {:ok, _} = Log.insert_position(car_id, Map.put(p, :trip_id, trip_id)) + end + + assert {:ok, %Trip{distance: nil}} = Log.close_trip(trip_id) + assert nil == Repo.get(Trip, trip_id) + end +end diff --git a/test/tesla_mate/vehicles/vehicle_test.exs b/test/tesla_mate/vehicles/vehicle_test.exs index bb215462..bf0bff7a 100644 --- a/test/tesla_mate/vehicles/vehicle_test.exs +++ b/test/tesla_mate/vehicles/vehicle_test.exs @@ -27,20 +27,6 @@ defmodule TeslaMate.Vehicles.VehicleTest do assert_receive {:start_state, 999, :online} - # assert_receive {:insert_position, - # %{ - # altitude: nil, - # battery_level: nil, - # date: ^now, - # ideal_battery_range_km: nil, - # latitude: 0.0, - # longitude: 0.0, - # odometer: nil, - # outside_temp: nil, - # power: nil, - # speed: nil - # }} - refute_receive _ end