|
| 1 | +# SPDX-FileCopyrightText: 2019 ash_json_api contributors <https://github.com/ash-project/ash_json_api/graphs/contributors> |
| 2 | +# |
| 3 | +# SPDX-License-Identifier: MIT |
| 4 | + |
| 5 | +defmodule Test.Acceptance.UnionTest do |
| 6 | + use ExUnit.Case, async: true |
| 7 | + |
| 8 | + defmodule HeartRate do |
| 9 | + use Ash.Resource, |
| 10 | + domain: nil, |
| 11 | + data_layer: :embedded |
| 12 | + |
| 13 | + attributes do |
| 14 | + attribute(:bpm, :integer, public?: true, allow_nil?: false) |
| 15 | + end |
| 16 | + |
| 17 | + actions do |
| 18 | + defaults([:read, :destroy, create: :*, update: :*]) |
| 19 | + end |
| 20 | + end |
| 21 | + |
| 22 | + defmodule BloodPressure do |
| 23 | + use Ash.Resource, |
| 24 | + domain: nil, |
| 25 | + data_layer: :embedded |
| 26 | + |
| 27 | + attributes do |
| 28 | + attribute(:systolic, :integer, public?: true, allow_nil?: false) |
| 29 | + attribute(:diastolic, :integer, public?: true, allow_nil?: false) |
| 30 | + end |
| 31 | + |
| 32 | + actions do |
| 33 | + defaults([:read, :destroy, create: :*, update: :*]) |
| 34 | + end |
| 35 | + end |
| 36 | + |
| 37 | + defmodule MeasurementValue do |
| 38 | + use Ash.Type.NewType, |
| 39 | + subtype_of: :union, |
| 40 | + constraints: [ |
| 41 | + types: [ |
| 42 | + heart_rate: [ |
| 43 | + type: HeartRate, |
| 44 | + tag: :type, |
| 45 | + tag_value: "heart_rate" |
| 46 | + ], |
| 47 | + blood_pressure: [ |
| 48 | + type: BloodPressure, |
| 49 | + tag: :type, |
| 50 | + tag_value: "blood_pressure" |
| 51 | + ], |
| 52 | + note: [ |
| 53 | + type: :string |
| 54 | + ] |
| 55 | + ] |
| 56 | + ] |
| 57 | + end |
| 58 | + |
| 59 | + defmodule Measurement do |
| 60 | + use Ash.Resource, |
| 61 | + domain: Test.Acceptance.UnionTest.Domain, |
| 62 | + data_layer: Ash.DataLayer.Ets, |
| 63 | + extensions: [AshJsonApi.Resource] |
| 64 | + |
| 65 | + ets do |
| 66 | + private?(true) |
| 67 | + end |
| 68 | + |
| 69 | + json_api do |
| 70 | + type "measurement" |
| 71 | + |
| 72 | + routes do |
| 73 | + base "/measurements" |
| 74 | + get :read |
| 75 | + index :read |
| 76 | + end |
| 77 | + end |
| 78 | + |
| 79 | + attributes do |
| 80 | + uuid_primary_key(:id) |
| 81 | + attribute(:value, MeasurementValue, public?: true, allow_nil?: false) |
| 82 | + attribute(:values, {:array, MeasurementValue}, public?: true, default: []) |
| 83 | + end |
| 84 | + |
| 85 | + actions do |
| 86 | + default_accept([:value, :values]) |
| 87 | + defaults([:read, :destroy, create: :*, update: :*]) |
| 88 | + end |
| 89 | + end |
| 90 | + |
| 91 | + defmodule Domain do |
| 92 | + use Ash.Domain, |
| 93 | + otp_app: :ash_json_api, |
| 94 | + extensions: [AshJsonApi.Domain] |
| 95 | + |
| 96 | + json_api do |
| 97 | + authorize? false |
| 98 | + log_errors? false |
| 99 | + end |
| 100 | + |
| 101 | + resources do |
| 102 | + resource Measurement |
| 103 | + end |
| 104 | + end |
| 105 | + |
| 106 | + defmodule Router do |
| 107 | + use AshJsonApi.Router, domain: Domain |
| 108 | + end |
| 109 | + |
| 110 | + import AshJsonApi.Test |
| 111 | + |
| 112 | + setup do |
| 113 | + Application.put_env(:ash_json_api, Domain, json_api: [test_router: Router]) |
| 114 | + :ok |
| 115 | + end |
| 116 | + |
| 117 | + test "renders an embedded resource inside a union without needing Jason.Encoder" do |
| 118 | + m = |
| 119 | + Measurement |
| 120 | + |> Ash.Changeset.for_create(:create, %{ |
| 121 | + value: %{type: "heart_rate", bpm: 72} |
| 122 | + }) |
| 123 | + |> Ash.create!() |
| 124 | + |
| 125 | + response = Domain |> get("/measurements/#{m.id}", status: 200) |
| 126 | + attrs = response.resp_body["data"]["attributes"] |
| 127 | + |
| 128 | + assert attrs["value"] == %{"bpm" => 72} |
| 129 | + end |
| 130 | + |
| 131 | + test "renders a primitive value inside a union" do |
| 132 | + m = |
| 133 | + Measurement |
| 134 | + |> Ash.Changeset.for_create(:create, %{ |
| 135 | + value: "feeling fine" |
| 136 | + }) |
| 137 | + |> Ash.create!() |
| 138 | + |
| 139 | + response = Domain |> get("/measurements/#{m.id}", status: 200) |
| 140 | + attrs = response.resp_body["data"]["attributes"] |
| 141 | + |
| 142 | + assert attrs["value"] == "feeling fine" |
| 143 | + end |
| 144 | + |
| 145 | + test "renders an array of unions" do |
| 146 | + m = |
| 147 | + Measurement |
| 148 | + |> Ash.Changeset.for_create(:create, %{ |
| 149 | + value: %{type: "heart_rate", bpm: 60}, |
| 150 | + values: [ |
| 151 | + %{type: "heart_rate", bpm: 80}, |
| 152 | + %{type: "blood_pressure", systolic: 120, diastolic: 80} |
| 153 | + ] |
| 154 | + }) |
| 155 | + |> Ash.create!() |
| 156 | + |
| 157 | + response = Domain |> get("/measurements/#{m.id}", status: 200) |
| 158 | + attrs = response.resp_body["data"]["attributes"] |
| 159 | + |
| 160 | + assert attrs["values"] == [ |
| 161 | + %{"bpm" => 80}, |
| 162 | + %{"systolic" => 120, "diastolic" => 80} |
| 163 | + ] |
| 164 | + end |
| 165 | +end |
0 commit comments