Skip to content

Commit a771f31

Browse files
committed
refactor(typed-channel): use real aggregate expressions in test calc transforms
1 parent 1fbc362 commit a771f31

File tree

4 files changed

+41
-39
lines changed

4 files changed

+41
-39
lines changed

test/ash_typescript/typed_channel/codegen_test.exs

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -313,40 +313,39 @@ defmodule AshTypescript.TypedChannel.CodegenTest do
313313
"export type TrackerSnapshotPayload = {id: UUID, name: string | null, status: string | null};"
314314
end
315315

316-
test "map calc transform payload type with different field types", %{
316+
test "map calc transform payload type with relationship traversal", %{
317317
types_content: content
318318
} do
319-
# %{id: id, name: name, description: status}
320-
# id non-null (PK), name/description nullable (attributes)
319+
# %{id: id, name: name, latest_entry_body: first(entries, :body)}
320+
# id non-null, name nullable, first() nullable
321321
assert content =~
322-
"export type TrackerDetailPayload = {id: UUID, name: string | null, description: string | null};"
322+
"export type TrackerDetailPayload = {id: UUID, name: string | null, latestEntryBody: string | null};"
323323
end
324324

325-
test "integer calc payload type from attribute", %{types_content: content} do
325+
test "integer calc payload type (count aggregate)", %{types_content: content} do
326326
assert content =~ "export type TrackerEntryCountPayload = number;"
327327
end
328328

329329
test "boolean expression calc transform payload type", %{types_content: content} do
330330
assert content =~ "export type TrackerIsActivePayload = boolean;"
331331
end
332332

333-
test "integer calc payload type from attribute (alt)", %{types_content: content} do
333+
test "integer aggregate calc payload type (max)", %{types_content: content} do
334334
assert content =~ "export type TrackerTopScorePayload = number;"
335335
end
336336

337-
test "map with various field types", %{types_content: content} do
338-
# id non-null (PK), name/status nullable, currentPriority nullable (integer attr)
337+
test "map with nested relationship fields (first on related FK)", %{types_content: content} do
338+
# id non-null (PK), name nullable, aggregates (first) nullable
339339
assert content =~
340-
"export type TrackerDeepDetailPayload = {id: UUID, name: string | null, status: string | null, currentPriority: number | null};"
340+
"export type TrackerDeepDetailPayload = {id: UUID, name: string | null, latestAuthor: UUID | null, latestBody: string | null, latestScore: number | null};"
341341
end
342342

343-
test "map mixing expressions, booleans, and attributes with correct nullability", %{
343+
test "map mixing aggregates, booleans, and strings with correct nullability", %{
344344
types_content: content
345345
} do
346-
# boolean expr → nullable (operands are nullable), attributes → nullable, string concat → nullable
347-
# Fields are alphabetically ordered in output
346+
# all fields nullable: attributes nullable, aggregates nullable, boolean expr with nullable operands nullable
348347
assert content =~
349-
"export type TrackerReportPayload = {label: string | null, name: string | null, status: string | null, isActive: boolean | null, currentPriority: number | null};"
348+
"export type TrackerReportPayload = {name: string | null, status: string | null, entryCount: number | null, isActive: boolean | null, topScore: number | null, latestBody: string | null};"
350349
end
351350

352351
test "no payload types are unknown", %{types_content: content} do

test/support/resources/channel_tracker.ex

Lines changed: 27 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,19 @@ defmodule AshTypescript.Test.ChannelTracker do
99
All publications use `transform: :calc_name`. Ash auto-populates the
1010
`returns` type from the calculation, which AshTypescript reads directly.
1111
12-
Expression types covered (all :auto unless noted):
12+
Expression types covered:
1313
- String concat (explicit and :auto)
14-
- Map with local attribute fields
15-
- Map with mixed field types (string, integer, boolean)
16-
- Integer from attribute reference
17-
- Boolean expression
18-
19-
Note: Avoids aggregate expressions (first, count, max) because
20-
Ash.DataLayer.Simple doesn't support aggregate type resolution for :auto.
14+
- Map with local fields (:auto)
15+
- Map with relationship traversal via first() (:auto)
16+
- Map with nested relationship traversal via first() with dot access (:auto)
17+
- Map mixing aggregates, booleans, strings, and relationship fields (:auto)
18+
- Count aggregate (:auto)
19+
- Max aggregate (:auto)
20+
- Boolean expression (:auto)
2121
"""
2222
use Ash.Resource,
2323
domain: nil,
24+
data_layer: Ash.DataLayer.Ets,
2425
notifiers: [Ash.Notifier.PubSub]
2526

2627
pub_sub do
@@ -51,13 +52,13 @@ defmodule AshTypescript.Test.ChannelTracker do
5152
public?: true,
5253
transform: :snapshot
5354

54-
# Map calc with different field types (:auto typed)
55+
# Map calc with relationship traversal (:auto typed)
5556
publish :detail_snapshot, [:id],
5657
event: "tracker_detail",
5758
public?: true,
5859
transform: :detail
5960

60-
# Integer from attribute (:auto typed)
61+
# Count aggregate (:auto typed)
6162
publish :count_entries, [:id],
6263
event: "tracker_entry_count",
6364
public?: true,
@@ -69,19 +70,19 @@ defmodule AshTypescript.Test.ChannelTracker do
6970
public?: true,
7071
transform: :is_active
7172

72-
# Integer from attribute (:auto typed)
73+
# Max aggregate (:auto typed)
7374
publish :top_score, [:id],
7475
event: "tracker_top_score",
7576
public?: true,
7677
transform: :top_entry_score
7778

78-
# Map with various field types (:auto typed)
79+
# Map with nested relationship traversal (:auto typed)
7980
publish :deep_snapshot, [:id],
8081
event: "tracker_deep_detail",
8182
public?: true,
8283
transform: :deep_detail
8384

84-
# Map mixing expressions and attributes (:auto typed)
85+
# Map mixing aggregates, booleans, and strings (:auto typed)
8586
publish :full_report, [:id],
8687
event: "tracker_report",
8788
public?: true,
@@ -122,15 +123,15 @@ defmodule AshTypescript.Test.ChannelTracker do
122123
public?(true)
123124
end
124125

125-
# :auto map calc with different field types (no aggregates)
126+
# :auto map calc with relationship traversal (first aggregate)
126127
calculate :detail,
127128
:auto,
128-
expr(%{id: id, name: name, description: status}) do
129+
expr(%{id: id, name: name, latest_entry_body: first(entries, field: :body)}) do
129130
public?(true)
130131
end
131132

132-
# :auto integer — type inferred from integer attribute
133-
calculate :entry_count, :auto, expr(priority) do
133+
# :auto count aggregate — should resolve to integer
134+
calculate :entry_count, :auto, expr(count(entries)) do
134135
public?(true)
135136
end
136137

@@ -139,19 +140,20 @@ defmodule AshTypescript.Test.ChannelTracker do
139140
public?(true)
140141
end
141142

142-
# :auto integer — type inferred from integer attribute
143-
calculate :top_entry_score, :auto, expr(priority) do
143+
# :auto max aggregate on related field — should resolve to integer
144+
calculate :top_entry_score, :auto, expr(max(entries, field: :score)) do
144145
public?(true)
145146
end
146147

147-
# :auto map with various field types
148+
# :auto map with nested relationship traversal — entries -> author -> username
148149
calculate :deep_detail,
149150
:auto,
150151
expr(%{
151152
id: id,
152153
name: name,
153-
status: status,
154-
current_priority: priority
154+
latest_author: first(entries, field: :channel_tracker_author_id),
155+
latest_body: first(entries, field: :body),
156+
latest_score: first(entries, field: :score)
155157
}) do
156158
public?(true)
157159
end
@@ -163,8 +165,9 @@ defmodule AshTypescript.Test.ChannelTracker do
163165
name: name,
164166
status: status,
165167
is_active: status == "active" and priority > 0,
166-
current_priority: priority,
167-
label: name <> " tracker"
168+
entry_count: count(entries),
169+
top_score: max(entries, field: :score),
170+
latest_body: first(entries, field: :body)
168171
}) do
169172
public?(true)
170173
end

test/support/resources/channel_tracker_author.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ defmodule AshTypescript.Test.ChannelTrackerAuthor do
66
@moduledoc """
77
Author resource for nested relationship traversal testing in :auto calculations.
88
"""
9-
use Ash.Resource, domain: nil
9+
use Ash.Resource, domain: nil, data_layer: Ash.DataLayer.Ets
1010

1111
attributes do
1212
uuid_primary_key :id

test/support/resources/channel_tracker_entry.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ defmodule AshTypescript.Test.ChannelTrackerEntry do
99
1010
Has a belongs_to :author for nested relationship traversal tests.
1111
"""
12-
use Ash.Resource, domain: nil
12+
use Ash.Resource, domain: nil, data_layer: Ash.DataLayer.Ets
1313

1414
attributes do
1515
uuid_primary_key :id

0 commit comments

Comments
 (0)