diff --git a/backend/lib/edgehog_web/resolvers/devices.ex b/backend/lib/edgehog_web/resolvers/devices.ex index 943dbcb2f..c870790c1 100644 --- a/backend/lib/edgehog_web/resolvers/devices.ex +++ b/backend/lib/edgehog_web/resolvers/devices.ex @@ -19,6 +19,7 @@ # defmodule EdgehogWeb.Resolvers.Devices do + alias Edgehog.Astarte alias Edgehog.Devices alias Edgehog.Devices.HardwareType alias Edgehog.Devices.SystemModel @@ -168,4 +169,9 @@ defmodule EdgehogWeb.Resolvers.Devices do _ -> {:ok, nil} end end + + def extract_device_tags(%Astarte.Device{tags: tags}, _args, _context) do + tag_names = for t <- tags, do: t.name + {:ok, tag_names} + end end diff --git a/backend/lib/edgehog_web/schema/astarte_types.ex b/backend/lib/edgehog_web/schema/astarte_types.ex index 9d381144e..61ad2a42b 100644 --- a/backend/lib/edgehog_web/schema/astarte_types.ex +++ b/backend/lib/edgehog_web/schema/astarte_types.ex @@ -82,6 +82,13 @@ defmodule EdgehogWeb.Schema.AstarteTypes do the name of the device's hardware type. """ field :hardware_type_name, :string + + @desc """ + A string to match against the tags of the device. + The match is case-insensitive and tests whether the string is included in \ + one of the tags of the device. + """ + field :tag, :string end @desc """ @@ -406,6 +413,11 @@ defmodule EdgehogWeb.Schema.AstarteTypes do @desc "The system model of the device." field :system_model, :system_model + @desc "The tags of the device" + field :tags, non_null(list_of(non_null(:string))) do + resolve &Resolvers.Devices.extract_device_tags/3 + end + @desc "List of capabilities supported by the device." field :capabilities, non_null(list_of(non_null(:device_capability))) do resolve &Resolvers.Astarte.list_device_capabilities/3 @@ -535,6 +547,9 @@ defmodule EdgehogWeb.Schema.AstarteTypes do @desc "The display name of the device." field :name, :string + + @desc "The tags of the device. These replace all the current tags." + field :tags, list_of(non_null(:string)) end output do diff --git a/backend/test/edgehog_web/schema/mutation/update_device_test.exs b/backend/test/edgehog_web/schema/mutation/update_device_test.exs index 2ef9c937a..8af7a76b1 100644 --- a/backend/test/edgehog_web/schema/mutation/update_device_test.exs +++ b/backend/test/edgehog_web/schema/mutation/update_device_test.exs @@ -23,6 +23,7 @@ defmodule EdgehogWeb.Schema.Mutation.UpdateDeviceTest do use Edgehog.AstarteMockCase import Edgehog.AstarteFixtures + alias Edgehog.Astarte describe "updateDevice field" do setup do @@ -40,6 +41,7 @@ defmodule EdgehogWeb.Schema.Mutation.UpdateDeviceTest do device { id name + tags } } } @@ -52,7 +54,8 @@ defmodule EdgehogWeb.Schema.Mutation.UpdateDeviceTest do variables = %{ input: %{ device_id: Absinthe.Relay.Node.to_global_id(:device, device.id, EdgehogWeb.Schema), - name: "Some new name" + name: "Some new name", + tags: ["foo", "bar", "baz"] } } @@ -62,7 +65,8 @@ defmodule EdgehogWeb.Schema.Mutation.UpdateDeviceTest do "data" => %{ "updateDevice" => %{ "device" => %{ - "name" => "Some new name" + "name" => "Some new name", + "tags" => ["foo", "bar", "baz"] } } } @@ -82,5 +86,33 @@ defmodule EdgehogWeb.Schema.Mutation.UpdateDeviceTest do assert %{"errors" => _} = assert(json_response(conn, 200)) end + + test "handles partial updates", %{ + conn: conn, + api_path: api_path, + device: device + } do + {:ok, _} = Astarte.update_device(device, %{tags: ["not", "touched"]}) + + variables = %{ + input: %{ + device_id: Absinthe.Relay.Node.to_global_id(:device, device.id, EdgehogWeb.Schema), + name: "Some new name" + } + } + + conn = post(conn, api_path, query: @query, variables: variables) + + assert %{ + "data" => %{ + "updateDevice" => %{ + "device" => %{ + "name" => "Some new name", + "tags" => ["not", "touched"] + } + } + } + } = json_response(conn, 200) + end end end diff --git a/backend/test/edgehog_web/schema/query/device_test.exs b/backend/test/edgehog_web/schema/query/device_test.exs index 38701ce06..b19c7030b 100644 --- a/backend/test/edgehog_web/schema/query/device_test.exs +++ b/backend/test/edgehog_web/schema/query/device_test.exs @@ -26,6 +26,7 @@ defmodule EdgehogWeb.Schema.Query.DeviceTest do import Edgehog.AstarteFixtures import Edgehog.OSManagementFixtures + alias Edgehog.Astarte alias Edgehog.Astarte.Device describe "device query" do @@ -144,5 +145,31 @@ defmodule EdgehogWeb.Schema.Query.DeviceTest do assert decoded_id == ota_operation.id assert operation["status"] == "PENDING" end + + @query """ + query ($id: ID!) { + device(id: $id) { + tags + } + } + """ + + test "returns the tags", %{conn: conn, api_path: api_path, realm: realm} do + {:ok, %Device{id: id}} = + device_fixture(realm) + |> Astarte.update_device(%{tags: ["foo", "bar"]}) + + variables = %{id: Absinthe.Relay.Node.to_global_id(:device, id, EdgehogWeb.Schema)} + + conn = get(conn, api_path, query: @query, variables: variables) + + assert %{ + "data" => %{ + "device" => device + } + } = json_response(conn, 200) + + assert device["tags"] == ["foo", "bar"] + end end end diff --git a/backend/test/edgehog_web/schema/query/devices_test.exs b/backend/test/edgehog_web/schema/query/devices_test.exs index 610d9047c..4dd786c8e 100644 --- a/backend/test/edgehog_web/schema/query/devices_test.exs +++ b/backend/test/edgehog_web/schema/query/devices_test.exs @@ -25,6 +25,7 @@ defmodule EdgehogWeb.Schema.Query.DevicesTest do import Edgehog.DevicesFixtures import Edgehog.AstarteFixtures + alias Edgehog.Astarte alias Edgehog.Astarte.Device describe "systemModels field" do @@ -108,6 +109,37 @@ defmodule EdgehogWeb.Schema.Query.DevicesTest do assert device["online"] == online end + test "filters devices with tag", %{ + conn: conn, + api_path: api_path, + realm: realm + } do + {:ok, + %Device{ + name: name, + device_id: device_id, + online: online + }} = + device_fixture(realm, device_id: "INyxlnmUT3CEJHPAwWMi0A") + |> Astarte.update_device(%{tags: ["foobar"]}) + + _device_2 = device_fixture(realm, device_id: "1YmkqsFfSuWDZcYV3ceoBQ") + + variables = %{filter: %{tag: "foo"}} + + conn = post(conn, api_path, query: @query, variables: variables) + + assert %{ + "data" => %{ + "devices" => [device] + } + } = json_response(conn, 200) + + assert device["name"] == name + assert device["deviceId"] == device_id + assert device["online"] == online + end + test "returns system model description with default locale", %{ conn: conn, api_path: api_path,