Database-BI
view release on metacpan or search on metacpan
t/transaction.t view on Meta::CPAN
subtest 'Transaction 6: Filter state machine' => sub {
# ------------------------------------------------------------------
# State S0: no filter.
# ------------------------------------------------------------------
$t->get_ok('/export?l=table:sales&format=csv')
->status_is(200)
->content_type_like(qr{text/csv});
is count_csv_rows($t->tx->res->body), $SALES_ROWS,
'S0 (no filter): all sales rows present';
# ------------------------------------------------------------------
# State S1: region = North.
# ------------------------------------------------------------------
$t->get_ok('/export?l=table:sales&format=csv&f=region:eq:North')
->status_is(200);
is count_csv_rows($t->tx->res->body), $NORTH_ROWS,
'S1 (region=North): correct North row count';
# ------------------------------------------------------------------
# State S2: region = North AND amount > 1000.
# ------------------------------------------------------------------
$t->get_ok('/export?l=table:sales&format=csv&f=region:eq:North&f=amount:gt:1500')
->status_is(200);
is count_csv_rows($t->tx->res->body), $NORTH_GT1500,
'S2 (North AND amount>1000): exactly one row';
# ------------------------------------------------------------------
# Back to S1: remove the amount filter (region=North only).
# ------------------------------------------------------------------
$t->get_ok('/export?l=table:sales&format=csv&f=region:eq:North')
->status_is(200);
is count_csv_rows($t->tx->res->body), $NORTH_ROWS,
'S1 (return): removing amount filter restores North count';
# ------------------------------------------------------------------
# Back to S0: remove all filters.
# ------------------------------------------------------------------
$t->get_ok('/export?l=table:sales&format=csv')
->status_is(200);
is count_csv_rows($t->tx->res->body), $SALES_ROWS,
'S0 (return): removing all filters restores full row count';
# ------------------------------------------------------------------
# Commutativity: S2 with reversed filter order must give the same count.
# ------------------------------------------------------------------
$t->get_ok('/export?l=table:sales&format=csv&f=amount:gt:1500&f=region:eq:North')
->status_is(200);
is count_csv_rows($t->tx->res->body), $NORTH_GT1500,
'Commutativity: reversed filter order produces same S2 count';
};
# ======================================================================
# TRANSACTION 7: Columns API -> Join coordination
#
# The columns_api endpoint feeds the join panel UI with column names.
# This transaction verifies that:
# Phase 1 GET /api/columns?table=sales -> columns list
# Phase 2 The "region" column from the API can serve as a join key
# Phase 3 GET /join using that key -> merged result
# Phase 4 Column count in result is correct
# ======================================================================
subtest 'Transaction 7: Columns API -> join coordination' => sub {
# ------------------------------------------------------------------
# Phase 1: fetch columns for the sales table.
# ------------------------------------------------------------------
$t->get_ok('/api/columns?table=sales')
->status_is(200)
->content_type_like(qr{application/json});
my $cols_json = decode_json($t->tx->res->body);
ok defined $cols_json->{columns}, 'Phase 1: response has "columns" key';
my @cols = @{ $cols_json->{columns} };
ok scalar @cols == $SALES_COLS, 'Phase 1: correct number of columns returned';
# ------------------------------------------------------------------
# Phase 2: verify a key column is present in the API response.
# We will use "region" to join with a hand-crafted right table.
# ------------------------------------------------------------------
ok scalar(grep { $_ eq 'region' } @cols), 'Phase 2: "region" column reported by API';
# ------------------------------------------------------------------
# Phase 3: create a right table keyed on "region" and perform the join.
# ------------------------------------------------------------------
my $tmpdir = tempdir(CLEANUP => 1);
my $right_file = Mojo::File->new($tmpdir)->child('regionmap.csv');
$right_file->spurt("region,zone_code\nNorth,N\nSouth,S\nEast,E\nWest,W\n");
my $lspec = 'table:sales';
my $rspec = 'path:' . $right_file->to_string;
my $jspec = $rspec . '|region|region';
$t->get_ok('/join?l=' . url_escape($lspec) . '&j=' . url_escape($jspec))
->status_is(200);
# ------------------------------------------------------------------
# Phase 4: merged result has left columns + right non-key columns.
# left = 6 (id,product,region,sales_rep,amount,sale_date)
# right non-key = 1 (zone_code) -> merged total = 7
# ------------------------------------------------------------------
my $right_extra_cols = 1; # zone_code only (region is the join key, dropped)
my $expected_merged = $SALES_COLS + $right_extra_cols;
$t->get_ok(
'/export?format=csv' .
'&l=' . url_escape($lspec) .
'&j=' . url_escape($jspec)
)->status_is(200);
is count_csv_cols($t->tx->res->body), $expected_merged,
'Phase 4: merged CSV has left + right non-key columns';
};
# ======================================================================
# TRANSACTION 8: Export write idempotency + stat before/after
( run in 2.316 seconds using v1.01-cache-2.11-cpan-9789f410c06 )