mirror of
https://github.com/plausible/analytics.git
synced 2025-01-09 03:26:52 +03:00
Evaluate ephemeral funnels before saving (#3097)
* PoC: evaluate funnel on step selection * Adjust test to actually _select_ steps * Throttle and test ephemeral funnel evaluation * Format compact percentages server-side At this point it's pointless to duplicate this; all the primitives exist in the API in case the client wants a different representation.
This commit is contained in:
parent
e98a16141e
commit
ade437c085
@ -56,7 +56,7 @@ export default function FunnelTooltip(palette, funnel) {
|
||||
</td>
|
||||
<td class="text-right text-sm">
|
||||
<span>
|
||||
${dataIndex == 0 ? formatPercentage(funnel.entering_visitors_percentage) : formatPercentage(currentStep.conversion_rate_step)}%
|
||||
${dataIndex == 0 ? funnel.entering_visitors_percentage : currentStep.conversion_rate_step}%
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
@ -73,7 +73,7 @@ export default function FunnelTooltip(palette, funnel) {
|
||||
<span>${dataIndex == 0 ? funnel.never_entering_visitors.toLocaleString() : currentStep.dropoff.toLocaleString()}</span>
|
||||
</td >
|
||||
<td class="text-right text-sm">
|
||||
<span>${dataIndex == 0 ? formatPercentage(funnel.never_entering_visitors_percentage) : formatPercentage(currentStep.dropoff_percentage)}%</span>
|
||||
<span>${dataIndex == 0 ? funnel.never_entering_visitors_percentage : currentStep.dropoff_percentage}%</span>
|
||||
</td>
|
||||
</tr >
|
||||
</table >
|
||||
@ -83,8 +83,3 @@ export default function FunnelTooltip(palette, funnel) {
|
||||
tooltipEl.style.display = null
|
||||
}
|
||||
}
|
||||
|
||||
const formatPercentage = (value) => {
|
||||
const decimalNumber = parseFloat(value);
|
||||
return decimalNumber % 1 === 0 ? decimalNumber.toFixed(0) : value;
|
||||
}
|
||||
|
@ -97,7 +97,7 @@ export default function Funnel(props) {
|
||||
const formatDataLabel = (visitors, ctx) => {
|
||||
if (ctx.dataset.label === 'Visitors') {
|
||||
const conversionRate = funnel.steps[ctx.dataIndex].conversion_rate
|
||||
return `${formatPercentage(conversionRate)}% \n(${numberFormatter(visitors)} Visitors)`
|
||||
return `${conversionRate}% \n(${numberFormatter(visitors)} Visitors)`
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
@ -339,11 +339,6 @@ export default function Funnel(props) {
|
||||
)
|
||||
}
|
||||
|
||||
const formatPercentage = (value) => {
|
||||
const decimalNumber = parseFloat(value);
|
||||
return decimalNumber % 1 === 0 ? decimalNumber.toFixed(0) : value;
|
||||
}
|
||||
|
||||
return (
|
||||
<div style={{ minHeight: '400px' }}>
|
||||
<LazyLoader onVisible={() => setVisible(true)}>
|
||||
|
@ -169,14 +169,22 @@ defmodule Plausible.Stats.Funnel do
|
||||
end
|
||||
|
||||
defp percentage(x, y) when x in [0, nil] or y in [0, nil] do
|
||||
"0.00"
|
||||
"0"
|
||||
end
|
||||
|
||||
defp percentage(x, y) do
|
||||
x
|
||||
|> Decimal.div(y)
|
||||
|> Decimal.mult(100)
|
||||
|> Decimal.round(2)
|
||||
|> Decimal.to_string()
|
||||
result =
|
||||
x
|
||||
|> Decimal.div(y)
|
||||
|> Decimal.mult(100)
|
||||
|> Decimal.round(2)
|
||||
|> Decimal.to_string()
|
||||
|
||||
case result do
|
||||
<<compact::binary-size(1), ".00">> -> compact
|
||||
<<compact::binary-size(2), ".00">> -> compact
|
||||
<<compact::binary-size(3), ".00">> -> compact
|
||||
decimal -> decimal
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -36,14 +36,16 @@ defmodule PlausibleWeb.Live.FunnelSettings.Form do
|
||||
form: to_form(Plausible.Funnels.create_changeset(site, "", [])),
|
||||
goals: goals,
|
||||
site: site,
|
||||
selections_made: Map.new()
|
||||
selections_made: Map.new(),
|
||||
evaluation_result: nil,
|
||||
evaluation_at: System.monotonic_time()
|
||||
)}
|
||||
end
|
||||
|
||||
def render(assigns) do
|
||||
~H"""
|
||||
<div id="funnel-form" class="grid grid-cols-4 gap-6 mt-6">
|
||||
<div class="col-span-4 sm:col-span-2">
|
||||
<div id="funnel-form" class="grid grid-cols-2 gap-6 mt-6">
|
||||
<div class="col-span-2 sm:col-span-2">
|
||||
<.form
|
||||
:let={f}
|
||||
for={@form}
|
||||
@ -63,7 +65,7 @@ defmodule PlausibleWeb.Live.FunnelSettings.Form do
|
||||
) %>
|
||||
|
||||
<div :for={step_idx <- @step_ids} class="flex">
|
||||
<div class="w-full flex-1">
|
||||
<div class="w-2/5 flex-1">
|
||||
<.live_component
|
||||
submit_name="funnel[steps][][goal_id]"
|
||||
module={PlausibleWeb.Live.FunnelSettings.ComboBox}
|
||||
@ -72,7 +74,17 @@ defmodule PlausibleWeb.Live.FunnelSettings.Form do
|
||||
/>
|
||||
</div>
|
||||
|
||||
<.remove_step_button :if={length(@step_ids) > Funnel.min_steps()} step_idx={step_idx} />
|
||||
<div class="w-min inline-flex items-center align-middle">
|
||||
<.remove_step_button :if={length(@step_ids) > Funnel.min_steps()} step_idx={step_idx} />
|
||||
</div>
|
||||
|
||||
<div class="w-2/5 inline-flex items-center ml-2 mb-3 text-gray-500 dark:text-gray-400">
|
||||
<.evaluation
|
||||
:if={@evaluation_result}
|
||||
result={@evaluation_result}
|
||||
at={Enum.find_index(@step_ids, &(&1 == step_idx))}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<.add_step_button :if={
|
||||
@ -81,7 +93,19 @@ defmodule PlausibleWeb.Live.FunnelSettings.Form do
|
||||
} />
|
||||
|
||||
<div class="mt-6">
|
||||
<%= if has_steps_errors?(f) do %>
|
||||
<p id="funnel-eval" class="text-gray-500 dark:text-gray-400 text-sm mt-2 mb-2">
|
||||
<%= if @evaluation_result do %>
|
||||
Last month conversion rate: <strong><%= List.last(@evaluation_result.steps).conversion_rate %></strong>%
|
||||
<% else %>
|
||||
<span class="text-red-600 text-sm">
|
||||
Choose minimum <%= Funnel.min_steps() %> steps to evaluate funnel.
|
||||
</span>
|
||||
<% end %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="mt-6">
|
||||
<%= if has_steps_errors?(f) or map_size(@selections_made) < Funnel.min_steps() or length(@step_ids) > map_size(@selections_made) do %>
|
||||
<.submit_button_inactive />
|
||||
<% else %>
|
||||
<.submit_button />
|
||||
@ -108,7 +132,7 @@ defmodule PlausibleWeb.Live.FunnelSettings.Form do
|
||||
name={@field.name}
|
||||
value={@field.value}
|
||||
phx-debounce="300"
|
||||
class="focus:ring-indigo-500 focus:border-indigo-500 dark:bg-gray-900 dark:text-gray-300 block w-full rounded-md sm:text-sm border-gray-300 dark:border-gray-500"
|
||||
class="focus:ring-indigo-500 focus:border-indigo-500 dark:bg-gray-900 dark:text-gray-300 block w-7/12 rounded-md sm:text-sm border-gray-300 dark:border-gray-500"
|
||||
/>
|
||||
|
||||
<.error :for={{msg, _} <- @field.errors}>Funnel name <%= msg %></.error>
|
||||
@ -128,7 +152,7 @@ defmodule PlausibleWeb.Live.FunnelSettings.Form do
|
||||
|
||||
def remove_step_button(assigns) do
|
||||
~H"""
|
||||
<div class="inline-flex items-center ml-2 mb-2 text-red-600">
|
||||
<div class="inline-flex items-center ml-2 mb-4 text-red-600">
|
||||
<svg
|
||||
id={"remove-step-#{@step_idx}"}
|
||||
class="feather feather-sm cursor-pointer"
|
||||
@ -192,6 +216,28 @@ defmodule PlausibleWeb.Live.FunnelSettings.Form do
|
||||
"""
|
||||
end
|
||||
|
||||
attr(:at, :integer, required: true)
|
||||
attr(:result, :map, required: true)
|
||||
|
||||
def evaluation(assigns) do
|
||||
~H"""
|
||||
<span class="text-xs" id={"step-eval-#{@at}"}>
|
||||
<% step = Enum.at(@result.steps, @at) %>
|
||||
<span :if={step && @at == 0}>
|
||||
<span
|
||||
class="border-dotted border-b border-gray-400 "
|
||||
tooltip="Sample calculation for last month"
|
||||
>
|
||||
Entering Visitors: <strong><%= @result.entering_visitors %></strong>
|
||||
</span>
|
||||
</span>
|
||||
<span :if={step && @at > 0}>
|
||||
Dropoff: <strong><%= Map.get(step, :dropoff_percentage) %>%</strong>
|
||||
</span>
|
||||
</span>
|
||||
"""
|
||||
end
|
||||
|
||||
def handle_event("add-step", _value, socket) do
|
||||
step_ids = socket.assigns.step_ids
|
||||
|
||||
@ -208,6 +254,7 @@ defmodule PlausibleWeb.Live.FunnelSettings.Form do
|
||||
idx = String.to_integer(idx)
|
||||
step_ids = List.delete(socket.assigns.step_ids, idx)
|
||||
selections_made = drop_selection(socket.assigns.selections_made, idx)
|
||||
send(self(), :evaluate_funnel)
|
||||
|
||||
{:noreply, assign(socket, step_ids: step_ids, selections_made: selections_made)}
|
||||
end
|
||||
@ -245,12 +292,72 @@ defmodule PlausibleWeb.Live.FunnelSettings.Form do
|
||||
def handle_info({:selection_made, %{submit_value: goal_id, by: combo_box}}, socket) do
|
||||
selections_made = store_selection(socket.assigns, combo_box, goal_id)
|
||||
|
||||
send(self(), :evaluate_funnel)
|
||||
|
||||
{:noreply,
|
||||
assign(socket,
|
||||
selections_made: selections_made
|
||||
)}
|
||||
end
|
||||
|
||||
def handle_info(:evaluate_funnel, socket) do
|
||||
{:noreply, evaluate_funnel(socket)}
|
||||
end
|
||||
|
||||
defp evaluate_funnel(%{assigns: %{selections_made: selections_made}} = socket)
|
||||
when map_size(selections_made) < Funnel.min_steps() do
|
||||
socket
|
||||
end
|
||||
|
||||
defp evaluate_funnel(
|
||||
%{
|
||||
assigns: %{
|
||||
site: site,
|
||||
selections_made: selections_made,
|
||||
evaluation_at: evaluation_at
|
||||
}
|
||||
} = socket
|
||||
) do
|
||||
with true <- seconds_since_evaluation(evaluation_at) >= 1,
|
||||
{:ok, {definition, query}} <- build_ephemeral_funnel(site, selections_made),
|
||||
{:ok, funnel} <- Plausible.Stats.funnel(site, query, definition) do
|
||||
assign(socket, evaluation_result: funnel, evaluation_at: System.monotonic_time())
|
||||
else
|
||||
_ ->
|
||||
socket
|
||||
end
|
||||
end
|
||||
|
||||
defp seconds_since_evaluation(evaluation_at) do
|
||||
System.convert_time_unit(System.monotonic_time() - evaluation_at, :native, :second)
|
||||
end
|
||||
|
||||
defp build_ephemeral_funnel(site, selections_made) do
|
||||
steps =
|
||||
selections_made
|
||||
|> Enum.sort_by(&elem(&1, 0))
|
||||
|> Enum.map(fn {_, goal} ->
|
||||
%{
|
||||
"goal_id" => goal.id,
|
||||
"goal" => %{
|
||||
"id" => goal.id,
|
||||
"event_name" => goal.event_name,
|
||||
"page_path" => goal.page_path
|
||||
}
|
||||
}
|
||||
end)
|
||||
|
||||
definition =
|
||||
Plausible.Funnels.ephemeral_definition(
|
||||
site,
|
||||
"Test funnel",
|
||||
steps
|
||||
)
|
||||
|
||||
query = Plausible.Stats.Query.from(site, %{"period" => "all"})
|
||||
{:ok, {definition, query}}
|
||||
end
|
||||
|
||||
defp find_sequence_break(input) do
|
||||
input
|
||||
|> Enum.sort()
|
||||
|
@ -178,26 +178,26 @@ defmodule Plausible.FunnelsTest do
|
||||
%{
|
||||
label: "Visit /go/to/blog/**",
|
||||
visitors: 2,
|
||||
conversion_rate: "100.00",
|
||||
conversion_rate_step: "0.00",
|
||||
conversion_rate: "100",
|
||||
conversion_rate_step: "0",
|
||||
dropoff: 0,
|
||||
dropoff_percentage: "0.00"
|
||||
dropoff_percentage: "0"
|
||||
},
|
||||
%{
|
||||
label: "Signup",
|
||||
visitors: 2,
|
||||
conversion_rate: "100.00",
|
||||
conversion_rate_step: "100.00",
|
||||
conversion_rate: "100",
|
||||
conversion_rate_step: "100",
|
||||
dropoff: 0,
|
||||
dropoff_percentage: "0.00"
|
||||
dropoff_percentage: "0"
|
||||
},
|
||||
%{
|
||||
label: "Visit /checkout",
|
||||
visitors: 1,
|
||||
conversion_rate: "50.00",
|
||||
conversion_rate_step: "50.00",
|
||||
conversion_rate: "50",
|
||||
conversion_rate_step: "50",
|
||||
dropoff: 1,
|
||||
dropoff_percentage: "50.00"
|
||||
dropoff_percentage: "50"
|
||||
}
|
||||
]
|
||||
}} = funnel_data
|
||||
@ -230,32 +230,32 @@ defmodule Plausible.FunnelsTest do
|
||||
%{
|
||||
all_visitors: 2,
|
||||
entering_visitors: 2,
|
||||
entering_visitors_percentage: "100.00",
|
||||
entering_visitors_percentage: "100",
|
||||
never_entering_visitors: 0,
|
||||
never_entering_visitors_percentage: "0.00",
|
||||
never_entering_visitors_percentage: "0",
|
||||
steps: [
|
||||
%{
|
||||
label: "Visit /go/to/blog/**",
|
||||
visitors: 2,
|
||||
conversion_rate: "100.00",
|
||||
conversion_rate_step: "0.00",
|
||||
conversion_rate: "100",
|
||||
conversion_rate_step: "0",
|
||||
dropoff: 0
|
||||
},
|
||||
%{
|
||||
label: "Signup",
|
||||
visitors: 2,
|
||||
conversion_rate: "100.00",
|
||||
conversion_rate_step: "100.00",
|
||||
conversion_rate: "100",
|
||||
conversion_rate_step: "100",
|
||||
dropoff: 0,
|
||||
dropoff_percentage: "0.00"
|
||||
dropoff_percentage: "0"
|
||||
},
|
||||
%{
|
||||
label: "Visit /checkout",
|
||||
visitors: 1,
|
||||
conversion_rate: "50.00",
|
||||
conversion_rate_step: "50.00",
|
||||
conversion_rate: "50",
|
||||
conversion_rate_step: "50",
|
||||
dropoff: 1,
|
||||
dropoff_percentage: "50.00"
|
||||
dropoff_percentage: "50"
|
||||
}
|
||||
]
|
||||
}} = funnel_data
|
||||
@ -280,33 +280,33 @@ defmodule Plausible.FunnelsTest do
|
||||
%{
|
||||
all_visitors: 0,
|
||||
entering_visitors: 0,
|
||||
entering_visitors_percentage: "0.00",
|
||||
entering_visitors_percentage: "0",
|
||||
never_entering_visitors: 0,
|
||||
never_entering_visitors_percentage: "0.00",
|
||||
never_entering_visitors_percentage: "0",
|
||||
steps: [
|
||||
%{
|
||||
label: "Visit /go/to/blog/**",
|
||||
visitors: 0,
|
||||
conversion_rate: "0.00",
|
||||
conversion_rate_step: "0.00",
|
||||
conversion_rate: "0",
|
||||
conversion_rate_step: "0",
|
||||
dropoff: 0,
|
||||
dropoff_percentage: "0.00"
|
||||
dropoff_percentage: "0"
|
||||
},
|
||||
%{
|
||||
label: "Signup",
|
||||
visitors: 0,
|
||||
conversion_rate: "0.00",
|
||||
conversion_rate_step: "0.00",
|
||||
conversion_rate: "0",
|
||||
conversion_rate_step: "0",
|
||||
dropoff: 0,
|
||||
dropoff_percentage: "0.00"
|
||||
dropoff_percentage: "0"
|
||||
},
|
||||
%{
|
||||
label: "Visit /checkout",
|
||||
visitors: 0,
|
||||
conversion_rate: "0.00",
|
||||
conversion_rate_step: "0.00",
|
||||
conversion_rate: "0",
|
||||
conversion_rate_step: "0",
|
||||
dropoff: 0,
|
||||
dropoff_percentage: "0.00"
|
||||
dropoff_percentage: "0"
|
||||
}
|
||||
]
|
||||
}} = funnel_data
|
||||
|
@ -41,34 +41,34 @@ defmodule PlausibleWeb.Api.StatsController.FunnelsTest do
|
||||
"never_entering_visitors_percentage" => "33.33",
|
||||
"steps" => [
|
||||
%{
|
||||
"conversion_rate" => "100.00",
|
||||
"conversion_rate_step" => "0.00",
|
||||
"conversion_rate" => "100",
|
||||
"conversion_rate_step" => "0",
|
||||
"dropoff" => 0,
|
||||
"dropoff_percentage" => "0.00",
|
||||
"dropoff_percentage" => "0",
|
||||
"label" => "Visit /blog/announcement",
|
||||
"visitors" => 2
|
||||
},
|
||||
%{
|
||||
"conversion_rate" => "100.00",
|
||||
"conversion_rate_step" => "100.00",
|
||||
"conversion_rate" => "100",
|
||||
"conversion_rate_step" => "100",
|
||||
"dropoff" => 0,
|
||||
"dropoff_percentage" => "0.00",
|
||||
"dropoff_percentage" => "0",
|
||||
"label" => "Signup",
|
||||
"visitors" => 2
|
||||
},
|
||||
%{
|
||||
"conversion_rate" => "50.00",
|
||||
"conversion_rate_step" => "50.00",
|
||||
"conversion_rate" => "50",
|
||||
"conversion_rate_step" => "50",
|
||||
"dropoff" => 1,
|
||||
"dropoff_percentage" => "50.00",
|
||||
"dropoff_percentage" => "50",
|
||||
"label" => "Visit /cart/add/product",
|
||||
"visitors" => 1
|
||||
},
|
||||
%{
|
||||
"conversion_rate" => "50.00",
|
||||
"conversion_rate_step" => "100.00",
|
||||
"conversion_rate" => "50",
|
||||
"conversion_rate_step" => "100",
|
||||
"dropoff" => 0,
|
||||
"dropoff_percentage" => "0.00",
|
||||
"dropoff_percentage" => "0",
|
||||
"label" => "Purchase",
|
||||
"visitors" => 1
|
||||
}
|
||||
@ -128,39 +128,39 @@ defmodule PlausibleWeb.Api.StatsController.FunnelsTest do
|
||||
"name" => "Test funnel",
|
||||
"all_visitors" => 1,
|
||||
"entering_visitors" => 1,
|
||||
"entering_visitors_percentage" => "100.00",
|
||||
"entering_visitors_percentage" => "100",
|
||||
"never_entering_visitors" => 0,
|
||||
"never_entering_visitors_percentage" => "0.00",
|
||||
"never_entering_visitors_percentage" => "0",
|
||||
"steps" => [
|
||||
%{
|
||||
"conversion_rate" => "100.00",
|
||||
"conversion_rate_step" => "0.00",
|
||||
"conversion_rate" => "100",
|
||||
"conversion_rate_step" => "0",
|
||||
"dropoff" => 0,
|
||||
"dropoff_percentage" => "0.00",
|
||||
"dropoff_percentage" => "0",
|
||||
"label" => "Visit /blog/announcement",
|
||||
"visitors" => 1
|
||||
},
|
||||
%{
|
||||
"conversion_rate" => "100.00",
|
||||
"conversion_rate_step" => "100.00",
|
||||
"conversion_rate" => "100",
|
||||
"conversion_rate_step" => "100",
|
||||
"dropoff" => 0,
|
||||
"dropoff_percentage" => "0.00",
|
||||
"dropoff_percentage" => "0",
|
||||
"label" => "Signup",
|
||||
"visitors" => 1
|
||||
},
|
||||
%{
|
||||
"conversion_rate" => "0.00",
|
||||
"conversion_rate_step" => "0.00",
|
||||
"conversion_rate" => "0",
|
||||
"conversion_rate_step" => "0",
|
||||
"dropoff" => 1,
|
||||
"dropoff_percentage" => "100.00",
|
||||
"dropoff_percentage" => "100",
|
||||
"label" => "Visit /cart/add/product",
|
||||
"visitors" => 0
|
||||
},
|
||||
%{
|
||||
"conversion_rate" => "0.00",
|
||||
"conversion_rate_step" => "0.00",
|
||||
"conversion_rate" => "0",
|
||||
"conversion_rate_step" => "0",
|
||||
"dropoff" => 0,
|
||||
"dropoff_percentage" => "0.00",
|
||||
"dropoff_percentage" => "0",
|
||||
"label" => "Purchase",
|
||||
"visitors" => 0
|
||||
}
|
||||
@ -180,39 +180,39 @@ defmodule PlausibleWeb.Api.StatsController.FunnelsTest do
|
||||
"name" => "Test funnel",
|
||||
"all_visitors" => 0,
|
||||
"entering_visitors" => 0,
|
||||
"entering_visitors_percentage" => "0.00",
|
||||
"entering_visitors_percentage" => "0",
|
||||
"never_entering_visitors" => 0,
|
||||
"never_entering_visitors_percentage" => "0.00",
|
||||
"never_entering_visitors_percentage" => "0",
|
||||
"steps" => [
|
||||
%{
|
||||
"conversion_rate" => "0.00",
|
||||
"conversion_rate_step" => "0.00",
|
||||
"conversion_rate" => "0",
|
||||
"conversion_rate_step" => "0",
|
||||
"dropoff" => 0,
|
||||
"dropoff_percentage" => "0.00",
|
||||
"dropoff_percentage" => "0",
|
||||
"label" => "Visit /blog/announcement",
|
||||
"visitors" => 0
|
||||
},
|
||||
%{
|
||||
"conversion_rate" => "0.00",
|
||||
"conversion_rate_step" => "0.00",
|
||||
"conversion_rate" => "0",
|
||||
"conversion_rate_step" => "0",
|
||||
"dropoff" => 0,
|
||||
"dropoff_percentage" => "0.00",
|
||||
"dropoff_percentage" => "0",
|
||||
"label" => "Signup",
|
||||
"visitors" => 0
|
||||
},
|
||||
%{
|
||||
"conversion_rate" => "0.00",
|
||||
"conversion_rate_step" => "0.00",
|
||||
"conversion_rate" => "0",
|
||||
"conversion_rate_step" => "0",
|
||||
"dropoff" => 0,
|
||||
"dropoff_percentage" => "0.00",
|
||||
"dropoff_percentage" => "0",
|
||||
"label" => "Visit /cart/add/product",
|
||||
"visitors" => 0
|
||||
},
|
||||
%{
|
||||
"conversion_rate" => "0.00",
|
||||
"conversion_rate_step" => "0.00",
|
||||
"conversion_rate" => "0",
|
||||
"conversion_rate_step" => "0",
|
||||
"dropoff" => 0,
|
||||
"dropoff_percentage" => "0.00",
|
||||
"dropoff_percentage" => "0",
|
||||
"label" => "Purchase",
|
||||
"visitors" => 0
|
||||
}
|
||||
|
@ -164,10 +164,14 @@ defmodule PlausibleWeb.Live.FunnelSettingsTest do
|
||||
|
||||
assert lv = find_live_child(lv, "funnels-form")
|
||||
|
||||
lv
|
||||
|> element("li#dropdown-step-1-option-0 a")
|
||||
|> render_click()
|
||||
|
||||
doc =
|
||||
lv
|
||||
|> element("form")
|
||||
|> render_change(%{funnel: %{name: "My test funnel"}})
|
||||
|> element("li#dropdown-step-2-option-0 a")
|
||||
|> render_click()
|
||||
|
||||
save_inactive = ~s/form button#save.cursor-not-allowed/
|
||||
save_active = ~s/form button#save[type="submit"]/
|
||||
@ -192,6 +196,33 @@ defmodule PlausibleWeb.Live.FunnelSettingsTest do
|
||||
refute element_exists?(doc, save_inactive)
|
||||
end
|
||||
|
||||
test "funnel gets evaluated on every select, assuming a second has passed between selections",
|
||||
%{
|
||||
conn: conn,
|
||||
site: site
|
||||
} do
|
||||
setup_goals(site)
|
||||
lv = get_liveview(conn, site)
|
||||
lv |> element(~s/button[phx-click="add-funnel"]/) |> render_click()
|
||||
|
||||
assert lv = find_live_child(lv, "funnels-form")
|
||||
|
||||
lv |> element("li#dropdown-step-1-option-0 a") |> render_click()
|
||||
|
||||
:timer.sleep(1001)
|
||||
|
||||
lv |> element("li#dropdown-step-2-option-0 a") |> render_click()
|
||||
|
||||
doc = lv |> element("#step-eval-0") |> render()
|
||||
assert text_of_element(doc, ~s/#step-eval-0/) =~ "Entering Visitors: 0"
|
||||
|
||||
doc = lv |> element("#step-eval-1") |> render()
|
||||
assert text_of_element(doc, ~s/#step-eval-1/) =~ "Dropoff: 0%"
|
||||
|
||||
doc = lv |> element("#funnel-eval") |> render()
|
||||
assert text_of_element(doc, ~s/#funnel-eval/) =~ "Last month conversion rate: 0%"
|
||||
end
|
||||
|
||||
test "cancel buttons renders the funnel list", %{
|
||||
conn: conn,
|
||||
site: site
|
||||
|
Loading…
Reference in New Issue
Block a user