Upgrade phoenix & liveview (#5766)
* Upgrade phoenix and phoenix_live_view * Use new phoenix controller options * Run mix format * Upgrade lazy_html and bcrypt * Always put root layout * Remove deprecated use Plug.Test * Escpaing updates for LazyHTML * Fix double layouts in site settings * Fix more escaping in tests * More LazyHTML updates * Fix remaining LazyHTML issues * More Floki -> LazyHTML conversions * More Floki -> LazyHTML conversions * Fix another issue with Floki -> LazyHTML * Fix another lazyHTML issue * Remove parsing from tree * Fix HTML escaping in teams_test * More test fixes * More test fixes * Add layout to browser_sso_notice pipeline * Extract elem_count helper
This commit is contained in:
parent
114bf325a8
commit
f3d326b735
|
|
@ -60,8 +60,10 @@ defmodule Plausible.Auth.SSO.Domain.Verification do
|
|||
with %Req.Response{body: body} = response when is_binary(body) <-
|
||||
run_request(url_override || "https://#{sso_domain}"),
|
||||
true <- html?(response),
|
||||
{:ok, html} <- Floki.parse_document(body),
|
||||
[_ | _] <- Floki.find(html, ~s|meta[name="#{@prefix}"][content="#{domain_identifier}"]|) do
|
||||
html <- LazyHTML.from_document(body),
|
||||
[_ | _] <-
|
||||
LazyHTML.query(html, ~s|meta[name="#{@prefix}"][content="#{domain_identifier}"]|)
|
||||
|> Enum.into([]) do
|
||||
true
|
||||
else
|
||||
_ ->
|
||||
|
|
|
|||
|
|
@ -77,8 +77,7 @@ defmodule PlausibleWeb.Live.SSOManagement do
|
|||
~H"""
|
||||
<form id="sso-init" for={} phx-submit="init-sso">
|
||||
<p class="text-sm">
|
||||
Single Sign-On (SSO) enables team members to sign in without having to register an account. For more details,
|
||||
<.styled_link href="https://plausible.io/docs/sso">see our documentation</.styled_link>.
|
||||
Single Sign-On (SSO) enables team members to sign in without having to register an account. For more details, <.styled_link href="https://plausible.io/docs/sso">see our documentation</.styled_link>.
|
||||
</p>
|
||||
|
||||
<.button type="submit">Start Configuring SSO</.button>
|
||||
|
|
|
|||
|
|
@ -11,8 +11,7 @@
|
|||
</:subtitle>
|
||||
|
||||
<p class="text-sm">
|
||||
To access this team, you must first
|
||||
<.styled_link href="/logout">log out</.styled_link>
|
||||
To access this team, you must first <.styled_link href="/logout">log out</.styled_link>
|
||||
and log in as SSO user.
|
||||
</p>
|
||||
</.focus_box>
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ defmodule PlausibleWeb do
|
|||
|
||||
def controller do
|
||||
quote do
|
||||
use Phoenix.Controller, namespace: PlausibleWeb
|
||||
use Phoenix.Controller, formats: [html: "View", json: "View"]
|
||||
|
||||
import Plug.Conn
|
||||
import PlausibleWeb.ControllerHelpers
|
||||
|
|
@ -58,8 +58,7 @@ defmodule PlausibleWeb do
|
|||
def view do
|
||||
quote do
|
||||
use Phoenix.View,
|
||||
root: "lib/plausible_web/templates",
|
||||
namespace: PlausibleWeb
|
||||
root: "lib/plausible_web/templates"
|
||||
|
||||
# Import convenience functions from controllers
|
||||
import Phoenix.Controller, only: [view_module: 1]
|
||||
|
|
@ -76,8 +75,7 @@ defmodule PlausibleWeb do
|
|||
def extra_view do
|
||||
quote do
|
||||
use Phoenix.View,
|
||||
root: "extra/lib/plausible_web/templates",
|
||||
namespace: PlausibleWeb
|
||||
root: "extra/lib/plausible_web/templates"
|
||||
|
||||
# Import convenience functions from controllers
|
||||
import Phoenix.Controller, only: [view_module: 1]
|
||||
|
|
@ -107,7 +105,7 @@ defmodule PlausibleWeb do
|
|||
|
||||
def plugins_api_controller do
|
||||
quote do
|
||||
use Phoenix.Controller, namespace: PlausibleWeb.Plugins.API
|
||||
use Phoenix.Controller, formats: [:json]
|
||||
import Plug.Conn
|
||||
import PlausibleWeb.Router.Helpers
|
||||
|
||||
|
|
@ -124,9 +122,7 @@ defmodule PlausibleWeb do
|
|||
|
||||
def plugins_api_view do
|
||||
quote do
|
||||
use Phoenix.View,
|
||||
namespace: PlausibleWeb.Plugins.API,
|
||||
root: ""
|
||||
use Phoenix.View, root: ""
|
||||
|
||||
alias PlausibleWeb.Router.Helpers
|
||||
import PlausibleWeb.Plugins.API.Views.Pagination, only: [render_metadata_links: 4]
|
||||
|
|
|
|||
|
|
@ -13,8 +13,9 @@ defmodule PlausibleWeb.Team.Notice do
|
|||
>
|
||||
<p>
|
||||
You can also create a team and assign different roles to team members, such as admin,
|
||||
editor, viewer or billing. Team members will gain access to all your sites.
|
||||
<.styled_link href={Routes.team_setup_path(PlausibleWeb.Endpoint, :setup)}>
|
||||
editor, viewer or billing. Team members will gain access to all your sites. <.styled_link href={
|
||||
Routes.team_setup_path(PlausibleWeb.Endpoint, :setup)
|
||||
}>
|
||||
Create your team here
|
||||
</.styled_link>.
|
||||
</p>
|
||||
|
|
|
|||
|
|
@ -249,7 +249,8 @@ defmodule PlausibleWeb.Live.ChoosePlan do
|
|||
~H"""
|
||||
You have used
|
||||
<span :if={@pageview_usage[:last_30_days]} class="inline">
|
||||
<b><%= PlausibleWeb.AuthView.delimit_integer(@pageview_usage.last_30_days.total) %></b> billable pageviews in the last 30 days.
|
||||
<b>{PlausibleWeb.AuthView.delimit_integer(@pageview_usage.last_30_days.total)}</b>
|
||||
billable pageviews in the last 30 days.
|
||||
</span>
|
||||
<span :if={@pageview_usage[:last_cycle]} class="inline">
|
||||
<b>{PlausibleWeb.AuthView.delimit_integer(@pageview_usage.last_cycle.total)}</b>
|
||||
|
|
@ -261,7 +262,8 @@ defmodule PlausibleWeb.Live.ChoosePlan do
|
|||
href={Routes.settings_path(PlausibleWeb.Endpoint, :subscription)}
|
||||
>
|
||||
"Subscription" section
|
||||
</a> in your account settings.
|
||||
</a>
|
||||
in your account settings.
|
||||
"""
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -181,8 +181,10 @@ defmodule PlausibleWeb.Live.GoalSettings.Form do
|
|||
~H"""
|
||||
<div id="pageviews-form" class="py-2" {@rest}>
|
||||
<div class="text-sm pb-6 text-gray-500 dark:text-gray-400 text-justify rounded-md">
|
||||
Pageview goals allow you to measure how many people visit a specific page or section of your site. Learn more in
|
||||
<.styled_link href="https://plausible.io/docs/pageview-goals" new_tab={true}>
|
||||
Pageview goals allow you to measure how many people visit a specific page or section of your site. Learn more in <.styled_link
|
||||
href="https://plausible.io/docs/pageview-goals"
|
||||
new_tab={true}
|
||||
>
|
||||
our docs
|
||||
</.styled_link>.
|
||||
</div>
|
||||
|
|
@ -257,8 +259,10 @@ defmodule PlausibleWeb.Live.GoalSettings.Form do
|
|||
~H"""
|
||||
<div id="scroll-form" class="py-2" x-data={@js} {@rest}>
|
||||
<div class="text-sm pb-6 text-gray-500 dark:text-gray-400 text-justify rounded-md">
|
||||
Scroll Depth goals allow you to see how many people scroll beyond your desired scroll depth percentage threshold. Learn more in
|
||||
<.styled_link href="https://plausible.io/docs/scroll-depth" new_tab={true}>
|
||||
Scroll Depth goals allow you to see how many people scroll beyond your desired scroll depth percentage threshold. Learn more in <.styled_link
|
||||
href="https://plausible.io/docs/scroll-depth"
|
||||
new_tab={true}
|
||||
>
|
||||
our docs
|
||||
</.styled_link>.
|
||||
</div>
|
||||
|
|
@ -330,8 +334,10 @@ defmodule PlausibleWeb.Live.GoalSettings.Form do
|
|||
<div id="custom-events-form" class="py-2" {@rest}>
|
||||
<div id="event-fields">
|
||||
<div class="text-sm pb-6 text-gray-500 dark:text-gray-400 text-justify rounded-md">
|
||||
Custom Events are not tracked by default - you have to configure them on your site to be sent to Plausible. See examples and learn more in
|
||||
<.styled_link href="https://plausible.io/docs/custom-event-goals" new_tab={true}>
|
||||
Custom Events are not tracked by default - you have to configure them on your site to be sent to Plausible. See examples and learn more in <.styled_link
|
||||
href="https://plausible.io/docs/custom-event-goals"
|
||||
new_tab={true}
|
||||
>
|
||||
our docs
|
||||
</.styled_link>.
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -58,9 +58,7 @@ defmodule PlausibleWeb.Live.ResetPasswordForm do
|
|||
Set password →
|
||||
</.button>
|
||||
<p class="text-center text-gray-500 text-xs mt-4">
|
||||
Don't have an account?
|
||||
<.styled_link href="/register">Register</.styled_link>
|
||||
instead.
|
||||
Don't have an account? <.styled_link href="/register">Register</.styled_link> instead.
|
||||
</p>
|
||||
</.form>
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -495,8 +495,7 @@ defmodule PlausibleWeb.Live.Sites do
|
|||
<p>
|
||||
The site uses <span x-text="selectedInvitation && selectedInvitation.missing_features"></span>,
|
||||
which your current subscription does not support. After accepting ownership of this site,
|
||||
you will not be able to access them unless you
|
||||
<.styled_link
|
||||
you will not be able to access them unless you <.styled_link
|
||||
class="inline-block"
|
||||
href={Routes.billing_path(PlausibleWeb.Endpoint, :choose_plan)}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ defmodule PlausibleWeb.Router do
|
|||
on_ee(do: plug(Plausible.Plugs.HandleExpiredSession))
|
||||
on_ee(do: plug(Plausible.Plugs.SSOTeamAccess))
|
||||
plug PlausibleWeb.Plugs.UserSessionTouch
|
||||
plug :put_root_layout, html: {PlausibleWeb.LayoutView, :app}
|
||||
end
|
||||
|
||||
on_ee do
|
||||
|
|
@ -28,6 +29,7 @@ defmodule PlausibleWeb.Router do
|
|||
plug PlausibleWeb.AuthPlug
|
||||
on_ee(do: plug(Plausible.Plugs.HandleExpiredSession))
|
||||
plug PlausibleWeb.Plugs.UserSessionTouch
|
||||
plug :put_root_layout, html: {PlausibleWeb.LayoutView, :app}
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -35,6 +37,7 @@ defmodule PlausibleWeb.Router do
|
|||
plug :accepts, ["html"]
|
||||
plug :put_secure_browser_headers
|
||||
plug PlausibleWeb.Plugs.NoRobots
|
||||
plug :put_root_layout, html: {PlausibleWeb.LayoutView, :app}
|
||||
end
|
||||
|
||||
pipeline :csrf do
|
||||
|
|
|
|||
|
|
@ -95,7 +95,6 @@
|
|||
</div>
|
||||
|
||||
<div class="text-center mt-8 dark:text-gray-100">
|
||||
Questions?
|
||||
<.styled_link href="https://plausible.io/contact">Contact us</.styled_link>
|
||||
Questions? <.styled_link href="https://plausible.io/contact">Contact us</.styled_link>
|
||||
</div>
|
||||
</.focus_box>
|
||||
|
|
|
|||
|
|
@ -2,6 +2,6 @@ You used to have an active account with {Plausible.product_name()}, a simple, li
|
|||
<br /><br />
|
||||
We've noticed that you're still sending us stats so we're writing to inform you that we'll stop accepting stats from your sites {@time}. We're an independent, bootstrapped service and we don't sell your data, so this will reduce our server costs and help keep us sustainable.
|
||||
<br /><br /> If you'd like to continue counting your site stats in a privacy-friendly way, please
|
||||
<a href={plausible_url() <> "?__team=#{@team.identifier}"}>login to your Plausible account</a> and start a subscription.
|
||||
<br /><br />
|
||||
<a href={plausible_url() <> "?__team=#{@team.identifier}"}>login to your Plausible account</a>
|
||||
and start a subscription. <br /><br />
|
||||
Do you have any questions or need help with anything? Just reply to this email and we'll gladly help.
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
Plausible is tracking your website stats without compromising the user experience and the privacy of your visitors.
|
||||
<br /><br /> Here's how to get even more out of your Plausible experience: <br /><br /> *
|
||||
<a href="https://plausible.io/docs/custom-event-goals">Set up custom events</a> and
|
||||
<a href="https://plausible.io/docs/pageview-goals">pageview goals</a> to count actions you want your visitors to take<br />
|
||||
<a href="https://plausible.io/docs/custom-event-goals">Set up custom events</a>
|
||||
and <a href="https://plausible.io/docs/pageview-goals">pageview goals</a>
|
||||
to count actions you want your visitors to take<br />
|
||||
* Running an ecommerce? Assign monetary values to custom events to track
|
||||
<a href="https://plausible.io/docs/ecommerce-revenue-tracking">revenue attribution</a>
|
||||
<br /> * Follow the journey from a landing page to conversion with
|
||||
|
|
@ -9,11 +10,13 @@ Plausible is tracking your website stats without compromising the user experienc
|
|||
<br /> *
|
||||
<a href="https://plausible.io/docs/manual-link-tagging">
|
||||
Tag your social media, email and paid links
|
||||
</a> to see which campaigns are responsible for most conversions<br />
|
||||
* <a href="https://plausible.io/docs/custom-props/introduction">Send custom properties</a>
|
||||
</a>
|
||||
to see which campaigns are responsible for most conversions<br /> *
|
||||
<a href="https://plausible.io/docs/custom-props/introduction">Send custom properties</a>
|
||||
to collect data that we don't track automatically <br /> * Explore our
|
||||
<a href="https://plausible.io/docs/stats-api">stats API</a> to retrieve your stats and our
|
||||
<a href="https://plausible.io/docs/sites-api">sites API</a> to create and manage sites programmatically<br />
|
||||
<a href="https://plausible.io/docs/stats-api">stats API</a>
|
||||
to retrieve your stats and our <a href="https://plausible.io/docs/sites-api">sites API</a>
|
||||
to create and manage sites programmatically<br />
|
||||
<br /><br />
|
||||
<a href={plausible_url()}>View your Plausible dashboard now</a>
|
||||
for the most valuable traffic insights at a glance. <br /><br />
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
We've recorded {@current_visitors} visitors on
|
||||
<a href={"https://" <> @site.domain}><%= @site.domain %></a> in the last 12 hours.
|
||||
<a href={"https://" <> @site.domain}>{@site.domain}</a>
|
||||
in the last 12 hours.
|
||||
<%= if @dashboard_link do %>
|
||||
<br /><br /> View dashboard: <a href={@dashboard_link}>{@dashboard_link}</a>
|
||||
<br /><br /> Something looks off? Please
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
{@inviter.email} has invited you to the {@site.domain} site on {Plausible.product_name()}.
|
||||
<a href={Routes.site_url(PlausibleWeb.Endpoint, :index) <> "?__team=none"}>Click here</a> to view and respond to the invitation. The invitation
|
||||
<a href={Routes.site_url(PlausibleWeb.Endpoint, :index) <> "?__team=none"}>Click here</a>
|
||||
to view and respond to the invitation. The invitation
|
||||
will expire 48 hours after this email is sent.
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
{@inviter.email} has invited you to the "{@team.name}" team on {Plausible.product_name()}.
|
||||
<a href={Routes.site_url(PlausibleWeb.Endpoint, :index)}>Click here</a> to view and respond to the invitation. The invitation
|
||||
<a href={Routes.site_url(PlausibleWeb.Endpoint, :index)}>Click here</a>
|
||||
to view and respond to the invitation. The invitation
|
||||
will expire 48 hours after this email is sent.
|
||||
|
|
|
|||
|
|
@ -1,2 +1,5 @@
|
|||
{@invitee_email} has accepted your invitation to {@site.domain}.
|
||||
<a href={Routes.site_url(PlausibleWeb.Endpoint, :settings_general, @site.domain) <> "?__team=#{@team.identifier}"}>Click here</a> to view site settings.
|
||||
<a href={Routes.site_url(PlausibleWeb.Endpoint, :settings_general, @site.domain) <> "?__team=#{@team.identifier}"}>
|
||||
Click here
|
||||
</a>
|
||||
to view site settings.
|
||||
|
|
|
|||
|
|
@ -1,2 +1,5 @@
|
|||
{@guest_invitation.team_invitation.email} has rejected your invitation to {@guest_invitation.site.domain}.
|
||||
<a href={Routes.site_url(PlausibleWeb.Endpoint, :settings_general, @guest_invitation.site.domain) <> "?__team=#{@team.identifier}"}>Click here</a> to view site settings.
|
||||
<a href={Routes.site_url(PlausibleWeb.Endpoint, :settings_general, @guest_invitation.site.domain) <> "?__team=#{@team.identifier}"}>
|
||||
Click here
|
||||
</a>
|
||||
to view site settings.
|
||||
|
|
|
|||
|
|
@ -1,2 +1,5 @@
|
|||
{@inviter.email} has promoted you to a team member in the "{@team.name}" team on {Plausible.product_name()}.
|
||||
<a href={PlausibleWeb.Router.Helpers.site_url(PlausibleWeb.Endpoint, :index) <> "?__team=#{@team.identifier}"}>Click here</a> to view sites managed by the team.
|
||||
<a href={PlausibleWeb.Router.Helpers.site_url(PlausibleWeb.Endpoint, :index) <> "?__team=#{@team.identifier}"}>
|
||||
Click here
|
||||
</a>
|
||||
to view sites managed by the team.
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@
|
|||
:register_from_invitation_form,
|
||||
@invitation_id
|
||||
)
|
||||
}>Click here</a> to create your account. The link is valid for 48 hours after this email is sent.
|
||||
<br /><br />
|
||||
}>
|
||||
Click here
|
||||
</a>
|
||||
to create your account. The link is valid for 48 hours after this email is sent. <br /><br />
|
||||
Plausible is a lightweight and open-source website analytics tool. We hope you like our simple and ethical approach to tracking website visitors.
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@
|
|||
:register_from_invitation_form,
|
||||
@invitation_id
|
||||
)
|
||||
}>Click here</a> to create your account. The link is valid for 48 hours after this email is sent.
|
||||
<br /><br />
|
||||
}>
|
||||
Click here
|
||||
</a>
|
||||
to create your account. The link is valid for 48 hours after this email is sent. <br /><br />
|
||||
Plausible is a lightweight and open-source website analytics tool. We hope you like our simple and ethical approach to tracking website visitors.
|
||||
|
|
|
|||
|
|
@ -1,2 +1,5 @@
|
|||
{@site_transfer.email} has rejected the ownership transfer of {@site_transfer.site.domain}.
|
||||
<a href={Routes.site_url(PlausibleWeb.Endpoint, :settings_general, @site_transfer.site.domain) <> "?__team=#{@team.identifier}"}>Click here</a> to view site settings.
|
||||
<a href={Routes.site_url(PlausibleWeb.Endpoint, :settings_general, @site_transfer.site.domain) <> "?__team=#{@team.identifier}"}>
|
||||
Click here
|
||||
</a>
|
||||
to view site settings.
|
||||
|
|
|
|||
|
|
@ -3,12 +3,16 @@
|
|||
<br /><br />
|
||||
<% end %>
|
||||
To finish your setup for {@site.domain}, review
|
||||
<a href={"#{plausible_url()}/#{URI.encode_www_form(@site.domain)}/installation?__team=#{@site_team.identifier}"}>your installation</a> and start collecting visitor statistics.
|
||||
<br /><br />
|
||||
<a href={"#{plausible_url()}/#{URI.encode_www_form(@site.domain)}/installation?__team=#{@site_team.identifier}"}>
|
||||
your installation
|
||||
</a>
|
||||
and start collecting visitor statistics. <br /><br />
|
||||
This Plausible script is 45 times smaller than Google Analytics script so you’ll have a fast loading site while getting all the important traffic insights on one single page.
|
||||
<br /><br /> On WordPress? We have a
|
||||
<a href="https://plausible.io/wordpress-analytics-plugin">WordPress plugin</a> that makes the process simpler. We also have
|
||||
<a href="https://plausible.io/docs/integration-guides">integration guides</a> for different site builders to help you start counting stats in no time.
|
||||
<a href="https://plausible.io/wordpress-analytics-plugin">WordPress plugin</a>
|
||||
that makes the process simpler. We also have
|
||||
<a href="https://plausible.io/docs/integration-guides">integration guides</a>
|
||||
for different site builders to help you start counting stats in no time.
|
||||
<%= if ee?() do %>
|
||||
<br /><br /> Do reply back to this email if you have any questions or need some guidance.
|
||||
<% end %>
|
||||
|
|
|
|||
|
|
@ -1,2 +1,5 @@
|
|||
{@user.email} has transferred {@site.domain} to the "{@team.name}" team on Plausible Analytics.
|
||||
<a href={Routes.stats_url(PlausibleWeb.Endpoint, :stats, @site.domain, []) <> "?__team=#{@team.identifier}"}>Click here</a> to view the stats.
|
||||
<a href={Routes.stats_url(PlausibleWeb.Endpoint, :stats, @site.domain, []) <> "?__team=#{@team.identifier}"}>
|
||||
Click here
|
||||
</a>
|
||||
to view the stats.
|
||||
|
|
|
|||
|
|
@ -1,2 +1,5 @@
|
|||
{@invitee_email} has accepted your invitation to "{@team.name}" team.
|
||||
<a href={Routes.settings_url(PlausibleWeb.Endpoint, :team_general) <> "?__team=#{@team.identifier}"}>Click here</a> to view team settings.
|
||||
<a href={Routes.settings_url(PlausibleWeb.Endpoint, :team_general) <> "?__team=#{@team.identifier}"}>
|
||||
Click here
|
||||
</a>
|
||||
to view team settings.
|
||||
|
|
|
|||
|
|
@ -1,2 +1,5 @@
|
|||
{@team_invitation.email} has rejected your invitation to \"{@team.name}\" team.
|
||||
<a href={Routes.settings_url(PlausibleWeb.Endpoint, :team_general) <> "?__team=#{@team.identifier}"}>Click here</a> to view team settings.
|
||||
<a href={Routes.settings_url(PlausibleWeb.Endpoint, :team_general) <> "?__team=#{@team.identifier}"}>
|
||||
Click here
|
||||
</a>
|
||||
to view team settings.
|
||||
|
|
|
|||
|
|
@ -1,15 +1,18 @@
|
|||
We are building Plausible to provide a simple and ethical approach to tracking website visitors.
|
||||
We're super excited to have you on board! <br /><br />
|
||||
Here's how to get the most out of your Plausible experience: <br /><br /> *
|
||||
<a href="https://plausible.io/docs/email-reports">Enable email reports</a> and notifications for
|
||||
<a href="https://plausible.io/docs/traffic-spikes">traffic spikes</a>
|
||||
<a href="https://plausible.io/docs/email-reports">Enable email reports</a>
|
||||
and notifications for <a href="https://plausible.io/docs/traffic-spikes">traffic spikes</a>
|
||||
<br /> *
|
||||
<a href="https://plausible.io/docs/google-search-console-integration">Integrate with Search Console</a> to get keyword phrases people find your site with<br />
|
||||
* <a href="https://plausible.io/docs/users-roles">Invite team members and other collaborators</a>
|
||||
<a href="https://plausible.io/docs/google-search-console-integration">
|
||||
Integrate with Search Console
|
||||
</a>
|
||||
to get keyword phrases people find your site with<br /> *
|
||||
<a href="https://plausible.io/docs/users-roles">Invite team members and other collaborators</a>
|
||||
<br /> * Set up easy goals including
|
||||
<a href="https://plausible.io/docs/error-pages-tracking-404">404 error pages</a>,
|
||||
<a href="https://plausible.io/docs/file-downloads-tracking">file downloads</a> and
|
||||
<a href="https://plausible.io/docs/outbound-link-click-tracking">outbound link clicks</a>
|
||||
<a href="https://plausible.io/docs/file-downloads-tracking">file downloads</a>
|
||||
and <a href="https://plausible.io/docs/outbound-link-click-tracking">outbound link clicks</a>
|
||||
<br /> * <a href="https://plausible.io/docs/excluding">Opt out from counting your own visits</a>
|
||||
<br /> * If you're concerned about adblockers,
|
||||
<a href="https://plausible.io/docs/proxy/introduction">set up a proxy to bypass them</a>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
Time flies! This is a reminder that your annual subscription for {Plausible.product_name()} will expire on {@next_bill_date}.
|
||||
<br /><br /> You need to
|
||||
<a href={PlausibleWeb.Router.Helpers.billing_url(PlausibleWeb.Endpoint, :choose_plan) <> "?__team=#{@team.identifier}"}>renew your subscription</a> if you want to continue using Plausible to count your website stats in a privacy-friendly way.
|
||||
<a href={PlausibleWeb.Router.Helpers.billing_url(PlausibleWeb.Endpoint, :choose_plan) <> "?__team=#{@team.identifier}"}>
|
||||
renew your subscription
|
||||
</a>
|
||||
if you want to continue using Plausible to count your website stats in a privacy-friendly way.
|
||||
<br /><br />
|
||||
If you don't want to continue your subscription, there's no action required. You will lose access to your dashboard on {@next_bill_date} and we'll stop accepting stats on {@accept_traffic_until}.
|
||||
<br /><br />
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
<%= render_layout "app.html", assigns do %>
|
||||
<% options = account_settings_sidebar(@conn) %>
|
||||
<div class="container pt-6">
|
||||
<.styled_link class="font-semibold text-sm" href="/sites">
|
||||
|
|
@ -53,4 +52,3 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
<%= render_layout "app.html", assigns do %>
|
||||
<% options = site_settings_sidebar(@conn) %>
|
||||
<div class="container pt-6">
|
||||
<.styled_link
|
||||
|
|
@ -36,4 +35,3 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
|
|
|
|||
|
|
@ -40,8 +40,7 @@
|
|||
<:help_content>
|
||||
Full access to
|
||||
<.styled_link href="https://plausible.io/docs/stats-api">Stats API</.styled_link>
|
||||
and
|
||||
<.styled_link href="https://plausible.io/docs/sites-api">Sites API</.styled_link>
|
||||
and <.styled_link href="https://plausible.io/docs/sites-api">Sites API</.styled_link>
|
||||
</:help_content>
|
||||
</.input>
|
||||
|
||||
|
|
|
|||
10
mix.exs
10
mix.exs
|
|
@ -16,6 +16,7 @@ defmodule Plausible.MixProject do
|
|||
test_coverage: [
|
||||
tool: ExCoveralls
|
||||
],
|
||||
listeners: [Phoenix.CodeReloader],
|
||||
releases: [
|
||||
plausible: [
|
||||
include_executables_for: [:unix],
|
||||
|
|
@ -67,7 +68,7 @@ defmodule Plausible.MixProject do
|
|||
{:bamboo_postmark, git: "https://github.com/plausible/bamboo_postmark.git", branch: "main"},
|
||||
{:bamboo_smtp, "~> 4.1"},
|
||||
{:bamboo_mua, "~> 0.2.0"},
|
||||
{:bcrypt_elixir, "~> 3.0"},
|
||||
{:bcrypt_elixir, "~> 3.3"},
|
||||
{:bypass, "~> 2.1", only: [:dev, :test, :ce_test]},
|
||||
{:ecto_ch, "~> 0.7.1"},
|
||||
{:cloak, "~> 1.1"},
|
||||
|
|
@ -85,6 +86,7 @@ defmodule Plausible.MixProject do
|
|||
{:excoveralls, "~> 0.10", only: :test},
|
||||
{:finch, "~> 0.19.0"},
|
||||
{:floki, "~> 0.36"},
|
||||
{:lazy_html, "~> 0.1.8"},
|
||||
{:fun_with_flags, "~> 1.11.0"},
|
||||
{:fun_with_flags_ui, "~> 1.0"},
|
||||
{:locus, "~> 2.3"},
|
||||
|
|
@ -103,13 +105,13 @@ defmodule Plausible.MixProject do
|
|||
{:opentelemetry_exporter, "~> 1.6.0"},
|
||||
{:opentelemetry_phoenix, "~> 1.0"},
|
||||
{:opentelemetry_oban, "~> 1.1.1"},
|
||||
{:phoenix, "~> 1.7.0"},
|
||||
{:phoenix, "~> 1.8.0"},
|
||||
{:phoenix_view, "~> 2.0"},
|
||||
{:phoenix_ecto, "~> 4.5"},
|
||||
{:phoenix_html, "~> 4.1"},
|
||||
{:phoenix_live_reload, "~> 1.2", only: [:dev, :ce_dev]},
|
||||
{:phoenix_pubsub, "~> 2.0"},
|
||||
{:phoenix_live_view, "~> 1.0"},
|
||||
{:phoenix_live_view, "~> 1.1"},
|
||||
{:php_serializer, "~> 2.0"},
|
||||
{:plug, "~> 1.13", override: true},
|
||||
{:plug_cowboy, "~> 2.3"},
|
||||
|
|
@ -153,7 +155,7 @@ defmodule Plausible.MixProject do
|
|||
{:odgn_json_pointer, "~> 3.0.1"},
|
||||
{:phoenix_bakery, "~> 0.1.2", only: [:ce, :ce_dev, :ce_test]},
|
||||
{:site_encrypt, github: "sasa1977/site_encrypt", only: [:ce, :ce_dev, :ce_test]},
|
||||
{:phoenix_storybook, "~> 0.8"},
|
||||
{:phoenix_storybook, "~> 0.9"},
|
||||
{:libcluster, "~> 3.5"}
|
||||
]
|
||||
end
|
||||
|
|
|
|||
35
mix.lock
35
mix.lock
|
|
@ -5,10 +5,11 @@
|
|||
"bamboo_mua": {:hex, :bamboo_mua, "0.2.2", "c50cd41ef684155669e2d99d428fbb87e13797a80829a162b47d3c0a7f7e7ecd", [:mix], [{:bamboo, "~> 2.0", [hex: :bamboo, repo: "hexpm", optional: false]}, {:mail, "~> 0.3.0", [hex: :mail, repo: "hexpm", optional: false]}, {:mua, "~> 0.2.3", [hex: :mua, repo: "hexpm", optional: false]}], "hexpm", "5fe6e3676640578c6fe8f040b34dda8991ebef8566c0601a984eb4771b85b11f"},
|
||||
"bamboo_postmark": {:git, "https://github.com/plausible/bamboo_postmark.git", "c6a773d1b7a4e5c9ec802ace64b5bb526504c25a", [branch: "main"]},
|
||||
"bamboo_smtp": {:hex, :bamboo_smtp, "4.2.2", "e9f57a2300df9cb496c48751bd7668a86a2b89aa2e79ccaa34e0c46a5f64c3ae", [:mix], [{:bamboo, "~> 2.2.0", [hex: :bamboo, repo: "hexpm", optional: false]}, {:gen_smtp, "~> 1.2.0", [hex: :gen_smtp, repo: "hexpm", optional: false]}], "hexpm", "28cac2ec8adaae02aed663bf68163992891a3b44cfd7ada0bebe3e09bed7207f"},
|
||||
"bcrypt_elixir": {:hex, :bcrypt_elixir, "3.1.0", "0b110a9a6c619b19a7f73fa3004aa11d6e719a67e672d1633dc36b6b2290a0f7", [:make, :mix], [{:comeonin, "~> 5.3", [hex: :comeonin, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "2ad2acb5a8bc049e8d5aa267802631912bb80d5f4110a178ae7999e69dca1bf7"},
|
||||
"bcrypt_elixir": {:hex, :bcrypt_elixir, "3.3.2", "d50091e3c9492d73e17fc1e1619a9b09d6a5ef99160eb4d736926fd475a16ca3", [:make, :mix], [{:comeonin, "~> 5.3", [hex: :comeonin, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "471be5151874ae7931911057d1467d908955f93554f7a6cd1b7d804cac8cef53"},
|
||||
"bunt": {:hex, :bunt, "1.0.0", "081c2c665f086849e6d57900292b3a161727ab40431219529f13c4ddcf3e7a44", [:mix], [], "hexpm", "dc5f86aa08a5f6fa6b8096f0735c4e76d54ae5c9fa2c143e5a1fc7c1cd9bb6b5"},
|
||||
"bypass": {:hex, :bypass, "2.1.0", "909782781bf8e20ee86a9cabde36b259d44af8b9f38756173e8f5e2e1fabb9b1", [:mix], [{:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.0", [hex: :plug_cowboy, repo: "hexpm", optional: false]}, {:ranch, "~> 1.3", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "d9b5df8fa5b7a6efa08384e9bbecfe4ce61c77d28a4282f79e02f1ef78d96b80"},
|
||||
"castore": {:hex, :castore, "1.0.15", "8aa930c890fe18b6fe0a0cff27b27d0d4d231867897bd23ea772dee561f032a3", [:mix], [], "hexpm", "96ce4c69d7d5d7a0761420ef743e2f4096253931a3ba69e5ff8ef1844fe446d3"},
|
||||
"cc_precompiler": {:hex, :cc_precompiler, "0.1.11", "8c844d0b9fb98a3edea067f94f616b3f6b29b959b6b3bf25fee94ffe34364768", [:mix], [{:elixir_make, "~> 0.7", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "3427232caf0835f94680e5bcf082408a70b48ad68a5f5c0b02a3bea9f3a075b9"},
|
||||
"certifi": {:hex, :certifi, "2.14.0", "ed3bef654e69cde5e6c022df8070a579a79e8ba2368a00acf3d75b82d9aceeed", [:rebar3], [], "hexpm", "ea59d87ef89da429b8e905264fdec3419f84f2215bb3d81e07a18aac919026c3"},
|
||||
"ch": {:hex, :ch, "0.4.1", "716fc326a0d29212a35c15e5350355550ff1290a244e6f37bf3eac4318aeeb76", [:mix], [{:db_connection, "~> 2.0", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:ecto, "~> 3.13.0", [hex: :ecto, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mint, "~> 1.0", [hex: :mint, repo: "hexpm", optional: false]}], "hexpm", "e6a4cf90d22030afde77e1a2895ebba2888032ccc5f1bec947b26b90a9152ffc"},
|
||||
"chatterbox": {:hex, :ts_chatterbox, "0.15.1", "5cac4d15dd7ad61fc3c4415ce4826fc563d4643dee897a558ec4ea0b1c835c9c", [:rebar3], [{:hpack, "~> 0.3.0", [hex: :hpack_erl, repo: "hexpm", optional: false]}], "hexpm", "4f75b91451338bc0da5f52f3480fa6ef6e3a2aeecfc33686d6b3d0a0948f31aa"},
|
||||
|
|
@ -17,12 +18,12 @@
|
|||
"cloak_ecto": {:hex, :cloak_ecto, "1.2.0", "e86a3df3bf0dc8980f70406bcb0af2858bac247d55494d40bc58a152590bd402", [:mix], [{:cloak, "~> 1.1.1", [hex: :cloak, repo: "hexpm", optional: false]}, {:ecto, "~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]}], "hexpm", "8bcc677185c813fe64b786618bd6689b1707b35cd95acaae0834557b15a0c62f"},
|
||||
"combination": {:hex, :combination, "0.0.3", "746aedca63d833293ec6e835aa1f34974868829b1486b1e1cb0685f0b2ae1f41", [:mix], [], "hexpm", "72b099f463df42ef7dc6371d250c7070b57b6c5902853f69deb894f79eda18ca"},
|
||||
"combine": {:hex, :combine, "0.10.0", "eff8224eeb56498a2af13011d142c5e7997a80c8f5b97c499f84c841032e429f", [:mix], [], "hexpm", "1b1dbc1790073076580d0d1d64e42eae2366583e7aecd455d1215b0d16f2451b"},
|
||||
"comeonin": {:hex, :comeonin, "5.4.0", "246a56ca3f41d404380fc6465650ddaa532c7f98be4bda1b4656b3a37cc13abe", [:mix], [], "hexpm", "796393a9e50d01999d56b7b8420ab0481a7538d0caf80919da493b4a6e51faf1"},
|
||||
"comeonin": {:hex, :comeonin, "5.5.1", "5113e5f3800799787de08a6e0db307133850e635d34e9fab23c70b6501669510", [:mix], [], "hexpm", "65aac8f19938145377cee73973f192c5645873dcf550a8a6b18187d17c13ccdb"},
|
||||
"con_cache": {:git, "https://github.com/aerosol/con_cache", "d050e133742e512cf2caa4598607e60dd0161072", [branch: "ensure-dirty-ops-emit-telemetry"]},
|
||||
"cors_plug": {:hex, :cors_plug, "3.0.3", "7c3ac52b39624bc616db2e937c282f3f623f25f8d550068b6710e58d04a0e330", [:mix], [{:plug, "~> 1.13", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "3f2d759e8c272ed3835fab2ef11b46bddab8c1ab9528167bd463b6452edf830d"},
|
||||
"cowboy": {:hex, :cowboy, "2.13.0", "09d770dd5f6a22cc60c071f432cd7cb87776164527f205c5a6b0f24ff6b38990", [:make, :rebar3], [{:cowlib, ">= 2.14.0 and < 3.0.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, ">= 1.8.0 and < 3.0.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "e724d3a70995025d654c1992c7b11dbfea95205c047d86ff9bf1cda92ddc5614"},
|
||||
"cowboy": {:hex, :cowboy, "2.14.0", "565dcf221ba99b1255b0adcec24d2d8dbe79e46ec79f30f8373cceadc6a41e2a", [:make, :rebar3], [{:cowlib, ">= 2.16.0 and < 3.0.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, ">= 1.8.0 and < 3.0.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "ea99769574550fe8a83225c752e8a62780a586770ef408816b82b6fe6d46476b"},
|
||||
"cowboy_telemetry": {:hex, :cowboy_telemetry, "0.4.0", "f239f68b588efa7707abce16a84d0d2acf3a0f50571f8bb7f56a15865aae820c", [:rebar3], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7d98bac1ee4565d31b62d59f8823dfd8356a169e7fcbb83831b8a5397404c9de"},
|
||||
"cowlib": {:hex, :cowlib, "2.14.0", "623791c56c1cc9df54a71a9c55147a401549917f00a2e48a6ae12b812c586ced", [:make, :rebar3], [], "hexpm", "0af652d1550c8411c3b58eed7a035a7fb088c0b86aff6bc504b0bc3b7f791aa2"},
|
||||
"cowlib": {:hex, :cowlib, "2.16.0", "54592074ebbbb92ee4746c8a8846e5605052f29309d3a873468d76cdf932076f", [:make, :rebar3], [], "hexpm", "7f478d80d66b747344f0ea7708c187645cfcc08b11aa424632f78e25bf05db51"},
|
||||
"credo": {:hex, :credo, "1.7.7", "771445037228f763f9b2afd612b6aa2fd8e28432a95dbbc60d8e03ce71ba4446", [:mix], [{:bunt, "~> 0.2.1 or ~> 1.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "8bc87496c9aaacdc3f90f01b7b0582467b69b4bd2441fe8aae3109d843cc2f2e"},
|
||||
"ctx": {:hex, :ctx, "0.6.0", "8ff88b70e6400c4df90142e7f130625b82086077a45364a78d208ed3ed53c7fe", [:rebar3], [], "hexpm", "a14ed2d1b67723dbebbe423b28d7615eb0bdcba6ff28f2d1f1b0a7e1d4aa5fc2"},
|
||||
"db_connection": {:hex, :db_connection, "2.8.0", "64fd82cfa6d8e25ec6660cea73e92a4cbc6a18b31343910427b702838c4b33b2", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "008399dae5eee1bf5caa6e86d204dcb44242c82b1ed5e22c881f2c34da201b15"},
|
||||
|
|
@ -30,13 +31,13 @@
|
|||
"dialyxir": {:hex, :dialyxir, "1.4.3", "edd0124f358f0b9e95bfe53a9fcf806d615d8f838e2202a9f430d59566b6b53b", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "bf2cfb75cd5c5006bec30141b131663299c661a864ec7fbbc72dfa557487a986"},
|
||||
"digital_token": {:hex, :digital_token, "1.0.0", "454a4444061943f7349a51ef74b7fb1ebd19e6a94f43ef711f7dae88c09347df", [:mix], [{:cldr_utils, "~> 2.17", [hex: :cldr_utils, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "8ed6f5a8c2fa7b07147b9963db506a1b4c7475d9afca6492136535b064c9e9e6"},
|
||||
"double": {:hex, :double, "0.8.2", "8e1cfcccdaef76c18846bc08e555555a2a699b806fa207b6468572a60513cc6a", [:mix], [], "hexpm", "90287642b2ec86125e0457aaba2ab0e80f7d7050cc80a0cef733e59bd70aa67c"},
|
||||
"earmark": {:hex, :earmark, "1.4.47", "7e7596b84fe4ebeb8751e14cbaeaf4d7a0237708f2ce43630cfd9065551f94ca", [:mix], [], "hexpm", "3e96bebea2c2d95f3b346a7ff22285bc68a99fbabdad9b655aa9c6be06c698f8"},
|
||||
"earmark": {:hex, :earmark, "1.4.48", "5f41e579d85ef812351211842b6e005f6e0cef111216dea7d4b9d58af4608434", [:mix], [], "hexpm", "a461a0ddfdc5432381c876af1c86c411fd78a25790c75023c7a4c035fdc858f9"},
|
||||
"earmark_parser": {:hex, :earmark_parser, "1.4.41", "ab34711c9dc6212dda44fcd20ecb87ac3f3fce6f0ca2f28d4a00e4154f8cd599", [:mix], [], "hexpm", "a81a04c7e34b6617c2792e291b5a2e57ab316365c2644ddc553bb9ed863ebefa"},
|
||||
"ecto": {:hex, :ecto, "3.13.2", "7d0c0863f3fc8d71d17fc3ad3b9424beae13f02712ad84191a826c7169484f01", [:mix], [{:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "669d9291370513ff56e7b7e7081b7af3283d02e046cf3d403053c557894a0b3e"},
|
||||
"ecto_ch": {:hex, :ecto_ch, "0.7.1", "d7d6a2b7cc411d1196ae295e74f9913c0218451cbfa49cf16f3ffff5405677b8", [:mix], [{:ch, "~> 0.4.0", [hex: :ch, repo: "hexpm", optional: false]}, {:ecto_sql, "~> 3.13.0", [hex: :ecto_sql, repo: "hexpm", optional: false]}], "hexpm", "5f07a2729df584fdc7d3325b93022b822bc2b6eee87f179b2317975514320b8f"},
|
||||
"ecto_network": {:hex, :ecto_network, "1.5.0", "a930c910975e7a91237b858ebf0f4ad7b2aae32fa846275aa203cb858459ec73", [:mix], [{:ecto_sql, ">= 3.0.0", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:phoenix_html, ">= 0.0.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:postgrex, ">= 0.14.0", [hex: :postgrex, repo: "hexpm", optional: false]}], "hexpm", "4d614434ae3e6d373a2f693d56aafaa3f3349714668ffd6d24e760caf578aa2f"},
|
||||
"ecto_sql": {:hex, :ecto_sql, "3.13.2", "a07d2461d84107b3d037097c822ffdd36ed69d1cf7c0f70e12a3d1decf04e2e1", [:mix], [{:db_connection, "~> 2.4.1 or ~> 2.5", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.13.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.7", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.19 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1 or ~> 2.2", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "539274ab0ecf1a0078a6a72ef3465629e4d6018a3028095dc90f60a19c371717"},
|
||||
"elixir_make": {:hex, :elixir_make, "0.7.7", "7128c60c2476019ed978210c245badf08b03dbec4f24d05790ef791da11aa17c", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}], "hexpm", "5bc19fff950fad52bbe5f211b12db9ec82c6b34a9647da0c2224b8b8464c7e6c"},
|
||||
"elixir_make": {:hex, :elixir_make, "0.9.0", "6484b3cd8c0cee58f09f05ecaf1a140a8c97670671a6a0e7ab4dc326c3109726", [:mix], [], "hexpm", "db23d4fd8b757462ad02f8aa73431a426fe6671c80b200d9710caf3d1dd0ffdb"},
|
||||
"envy": {:hex, :envy, "1.1.1", "0bc9bd654dec24fcdf203f7c5aa1b8f30620f12cfb28c589d5e9c38fe1b07475", [:mix], [], "hexpm", "7061eb1a47415fd757145d8dec10dc0b1e48344960265cb108f194c4252c3a89"},
|
||||
"eqrcode": {:hex, :eqrcode, "0.2.1", "d12838813e8fc87b8940cc05f9baadb189031f6009facdc56ff074375ec73b6e", [:mix], [], "hexpm", "d5828a222b904c68360e7dc2a40c3ef33a1328b7c074583898040f389f928025"},
|
||||
"erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"},
|
||||
|
|
@ -55,7 +56,8 @@
|
|||
"expo": {:hex, :expo, "1.1.0", "f7b9ed7fb5745ebe1eeedf3d6f29226c5dd52897ac67c0f8af62a07e661e5c75", [:mix], [], "hexpm", "fbadf93f4700fb44c331362177bdca9eeb8097e8b0ef525c9cc501cb9917c960"},
|
||||
"file_system": {:hex, :file_system, "1.0.1", "79e8ceaddb0416f8b8cd02a0127bdbababe7bf4a23d2a395b983c1f8b3f73edd", [:mix], [], "hexpm", "4414d1f38863ddf9120720cd976fce5bdde8e91d8283353f0e31850fa89feb9e"},
|
||||
"finch": {:hex, :finch, "0.19.0", "c644641491ea854fc5c1bbaef36bfc764e3f08e7185e1f084e35e0672241b76d", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.6.2 or ~> 1.7", [hex: :mint, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.4 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 1.1", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "fc5324ce209125d1e2fa0fcd2634601c52a787aff1cd33ee833664a5af4ea2b6"},
|
||||
"floki": {:hex, :floki, "0.37.0", "b83e0280bbc6372f2a403b2848013650b16640cd2470aea6701f0632223d719e", [:mix], [], "hexpm", "516a0c15a69f78c47dc8e0b9b3724b29608aa6619379f91b1ffa47109b5d0dd3"},
|
||||
"fine": {:hex, :fine, "0.1.4", "b19a89c1476c7c57afb5f9314aed5960b5bc95d5277de4cb5ee8e1d1616ce379", [:mix], [], "hexpm", "be3324cc454a42d80951cf6023b9954e9ff27c6daa255483b3e8d608670303f5"},
|
||||
"floki": {:hex, :floki, "0.38.0", "62b642386fa3f2f90713f6e231da0fa3256e41ef1089f83b6ceac7a3fd3abf33", [:mix], [], "hexpm", "a5943ee91e93fb2d635b612caf5508e36d37548e84928463ef9dd986f0d1abd9"},
|
||||
"fun_with_flags": {:hex, :fun_with_flags, "1.11.0", "a9019d0300e9755c53111cf5b2aba640d7f0de2a8a03a0bd0c593e943c3e9ec5", [:mix], [{:ecto_sql, "~> 3.0", [hex: :ecto_sql, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.0", [hex: :phoenix_pubsub, repo: "hexpm", optional: true]}, {:redix, "~> 1.0", [hex: :redix, repo: "hexpm", optional: true]}], "hexpm", "448ec640cd1ade4728979ae5b3e7592b0fc8b0f99cf40785d048515c27d09743"},
|
||||
"fun_with_flags_ui": {:hex, :fun_with_flags_ui, "1.0.0", "d764a4d1cc1233bdbb18dfb416a6ef96d0ecf4a5dc5a0201f7aa0b13cf2e7802", [:mix], [{:cowboy, ">= 2.0.0", [hex: :cowboy, repo: "hexpm", optional: true]}, {:fun_with_flags, "~> 1.11", [hex: :fun_with_flags, repo: "hexpm", optional: false]}, {:plug, "~> 1.12", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, ">= 2.0.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}], "hexpm", "b0c145894c00d65d5dc20ee5b1f18457985d1fd0b87866f0b41894d5979e55e0"},
|
||||
"gen_cycle": {:hex, :gen_cycle, "1.0.4", "2315199f1256116328fad6a9d4371c2fb0bc39c7f5111b88d2de582300c931cc", [:rebar3], [], "hexpm", "67817e31b352bb00715f80a5571b3c069e26e994b2ebafa376acf76a2d0f66d8"},
|
||||
|
|
@ -73,17 +75,18 @@
|
|||
"jason": {:hex, :jason, "1.4.4", "b9226785a9aa77b6857ca22832cffa5d5011a667207eb2a0ad56adb5db443b8a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "c5eb0cab91f094599f94d55bc63409236a8ec69a21a67814529e8d5f6cc90b3b"},
|
||||
"joken": {:hex, :joken, "2.6.0", "b9dd9b6d52e3e6fcb6c65e151ad38bf4bc286382b5b6f97079c47ade6b1bcc6a", [:mix], [{:jose, "~> 1.11.5", [hex: :jose, repo: "hexpm", optional: false]}], "hexpm", "5a95b05a71cd0b54abd35378aeb1d487a23a52c324fa7efdffc512b655b5aaa7"},
|
||||
"jose": {:hex, :jose, "1.11.6", "613fda82552128aa6fb804682e3a616f4bc15565a048dabd05b1ebd5827ed965", [:mix, :rebar3], [], "hexpm", "6275cb75504f9c1e60eeacb771adfeee4905a9e182103aa59b53fed651ff9738"},
|
||||
"lazy_html": {:hex, :lazy_html, "0.1.8", "677a8642e644eef8de98f3040e2520d42d0f0f8bd6c5cd49db36504e34dffe91", [:make, :mix], [{:cc_precompiler, "~> 0.1", [hex: :cc_precompiler, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.9.0", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:fine, "~> 0.1.0", [hex: :fine, repo: "hexpm", optional: false]}], "hexpm", "0d8167d930b704feb94b41414ca7f5779dff9bca7fcf619fcef18de138f08736"},
|
||||
"libcluster": {:hex, :libcluster, "3.5.0", "5ee4cfde4bdf32b2fef271e33ce3241e89509f4344f6c6a8d4069937484866ba", [:mix], [{:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.3", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "ebf6561fcedd765a4cd43b4b8c04b1c87f4177b5fb3cbdfe40a780499d72f743"},
|
||||
"location": {:git, "https://github.com/plausible/location.git", "a89bf79985c3c3d0830477ae587001156a646ce8", []},
|
||||
"locus": {:hex, :locus, "2.3.11", "ddfab230e3fb8b45f47416ed0fb8776c6d6d00f38687f6d37647ed7502c33d8e", [:rebar3], [{:tls_certificate_check, "~> 1.9", [hex: :tls_certificate_check, repo: "hexpm", optional: false]}], "hexpm", "ad855e9b998adc6ec5c57b9d0e5130b0e40a927be7b50d8e104df245c60ede1a"},
|
||||
"mail": {:hex, :mail, "0.3.1", "cb0a14e4ed8904e4e5a08214e686ccf6f9099346885db17d8c309381f865cc5c", [:mix], [], "hexpm", "1db701e89865c1d5fa296b2b57b1cd587587cca8d8a1a22892b35ef5a8e352a6"},
|
||||
"makeup": {:hex, :makeup, "1.2.1", "e90ac1c65589ef354378def3ba19d401e739ee7ee06fb47f94c687016e3713d1", [:mix], [{:nimble_parsec, "~> 1.4", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "d36484867b0bae0fea568d10131197a4c2e47056a6fbe84922bf6ba71c8d17ce"},
|
||||
"makeup_eex": {:hex, :makeup_eex, "1.0.0", "436d4c00204c250b17a775d64e197798aaf374627e6a4f2d3fd3074a8db61db4", [:mix], [{:makeup, "~> 1.2.1 or ~> 1.3", [hex: :makeup, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 1.0", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_html, "~> 0.1.0 or ~> 1.0", [hex: :makeup_html, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "3bb699bc519e4f509f1bf8a2e0ba0e08429edf3580053cd31a4f9c1bc5da86c8"},
|
||||
"makeup_eex": {:hex, :makeup_eex, "2.0.2", "88983b72aadb2e8408b06f7c9413804ce7eae2ca2a5a35cb738c6a9cb393c155", [:mix], [{:makeup, "~> 1.2.1 or ~> 1.3", [hex: :makeup, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 1.0", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_html, "~> 0.2.0 or ~> 1.0", [hex: :makeup_html, repo: "hexpm", optional: true]}, {:nimble_parsec, "~> 1.2", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "30ac121dda580298ff3378324ffaec94aad5a5b67e0cc6af177c67d5f45629b9"},
|
||||
"makeup_elixir": {:hex, :makeup_elixir, "1.0.1", "e928a4f984e795e41e3abd27bfc09f51db16ab8ba1aebdba2b3a575437efafc2", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "7284900d412a3e5cfd97fdaed4f5ed389b8f2b4cb49efc0eb3bd10e2febf9507"},
|
||||
"makeup_erlang": {:hex, :makeup_erlang, "1.0.1", "c7f58c120b2b5aa5fd80d540a89fdf866ed42f1f3994e4fe189abebeab610839", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "8a89a1eeccc2d798d6ea15496a6e4870b75e014d1af514b1b71fa33134f57814"},
|
||||
"makeup_html": {:hex, :makeup_html, "0.1.2", "19d4050c0978a4f1618ffe43054c0049f91fe5feeb9ae8d845b5dc79c6008ae5", [:mix], [{:makeup, "~> 1.2", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "b7fb9afedd617d167e6644a0430e49c1279764bfd3153da716d4d2459b0998c5"},
|
||||
"makeup_html": {:hex, :makeup_html, "0.2.0", "9f810da8d43d625ccd3f7ea25997e588fa541d80e0a8c6b895157ad5c7e9ca13", [:mix], [{:makeup, "~> 1.2", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "0856f7beb9a6a642ab1307e06d990fe39f0ba58690d0b8e662aa2e027ba331b2"},
|
||||
"metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"},
|
||||
"mime": {:hex, :mime, "2.0.6", "8f18486773d9b15f95f4f4f1e39b710045fa1de891fada4516559967276e4dc2", [:mix], [], "hexpm", "c9945363a6b26d747389aac3643f8e0e09d30499a138ad64fe8fd1d13d9b153e"},
|
||||
"mime": {:hex, :mime, "2.0.7", "b8d739037be7cd402aee1ba0306edfdef982687ee7e9859bee6198c1e7e2f128", [:mix], [], "hexpm", "6171188e399ee16023ffc5b76ce445eb6d9672e2e241d2df6050f3c771e80ccd"},
|
||||
"mimerl": {:hex, :mimerl, "1.3.0", "d0cd9fc04b9061f82490f6581e0128379830e78535e017f7780f37fea7545726", [:rebar3], [], "hexpm", "a1e15a50d1887217de95f0b9b0793e32853f7c258a5cd227650889b38839fe9d"},
|
||||
"mint": {:hex, :mint, "1.7.1", "113fdb2b2f3b59e47c7955971854641c61f378549d73e829e1768de90fc1abf1", [:mix], [{:castore, "~> 0.1.0 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:hpax, "~> 0.1.1 or ~> 0.2.0 or ~> 1.0", [hex: :hpax, repo: "hexpm", optional: false]}], "hexpm", "fceba0a4d0f24301ddee3024ae116df1c3f4bb7a563a731f45fdfeb9d39a231b"},
|
||||
"mjml": {:hex, :mjml, "3.1.0", "549e985bc03be1af563c62a34c8e62bdb8d0baaa6b31af705a5bdf67e20f22b7", [:mix], [{:rustler, ">= 0.0.0", [hex: :rustler, repo: "hexpm", optional: true]}, {:rustler_precompiled, "~> 0.7.0", [hex: :rustler_precompiled, repo: "hexpm", optional: false]}], "hexpm", "987674d296b14b628e5e5d2d8b910e6501cdfafa0239527d8b633880dc595344"},
|
||||
|
|
@ -115,20 +118,20 @@
|
|||
"parent": {:hex, :parent, "0.12.1", "495c4386f06de0df492e0a7a7199c10323a55e9e933b27222060dd86dccd6d62", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "2ab589ef1f37bfcedbfb5ecfbab93354972fb7391201b8907a866dadd20b39d1"},
|
||||
"parse_trans": {:hex, :parse_trans, "3.4.1", "6e6aa8167cb44cc8f39441d05193be6e6f4e7c2946cb2759f015f8c56b76e5ff", [:rebar3], [], "hexpm", "620a406ce75dada827b82e453c19cf06776be266f5a67cff34e1ef2cbb60e49a"},
|
||||
"peep": {:hex, :peep, "3.4.2", "49d4ca116d994779351959dfee971fb2c7d6506f1821374f3cc4fd39a3d3fadb", [:mix], [{:nimble_options, "~> 1.1", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:plug, "~> 1.16", [hex: :plug, repo: "hexpm", optional: true]}, {:telemetry_metrics, "~> 1.0", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "cae224b09e224bf5584f5375108becf71e2288572a099a122e66735289cd33f4"},
|
||||
"phoenix": {:hex, :phoenix, "1.7.20", "6bababaf27d59f5628f9b608de902a021be2cecefb8231e1dbdc0a2e2e480e9b", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.7", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:websock_adapter, "~> 0.5.3", [hex: :websock_adapter, repo: "hexpm", optional: false]}], "hexpm", "6be2ab98302e8784a31829e0d50d8bdfa81a23cd912c395bafd8b8bfb5a086c2"},
|
||||
"phoenix": {:hex, :phoenix, "1.8.1", "865473a60a979551a4879db79fbfb4503e41cd809e77c85af79716578b6a456d", [:mix], [{:bandit, "~> 1.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.7", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:websock_adapter, "~> 0.5.3", [hex: :websock_adapter, repo: "hexpm", optional: false]}], "hexpm", "84d77d2b2e77c3c7e7527099bd01ef5c8560cd149c036d6b3a40745f11cd2fb2"},
|
||||
"phoenix_bakery": {:hex, :phoenix_bakery, "0.1.2", "ca57673caea1a98f1cc763f94032796a015774d27eaa3ce5feef172195470452", [:mix], [{:brotli, "~> 0.3.0", [hex: :brotli, repo: "hexpm", optional: true]}, {:ezstd, "~> 1.0", [hex: :ezstd, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.6", [hex: :phoenix, repo: "hexpm", optional: false]}], "hexpm", "45cc8cecc5c3002b922447c16389761718c07c360432328b04680034e893ea5b"},
|
||||
"phoenix_ecto": {:hex, :phoenix_ecto, "4.6.3", "f686701b0499a07f2e3b122d84d52ff8a31f5def386e03706c916f6feddf69ef", [:mix], [{:ecto, "~> 3.5", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.1", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.16 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}], "hexpm", "909502956916a657a197f94cc1206d9a65247538de8a5e186f7537c895d95764"},
|
||||
"phoenix_html": {:hex, :phoenix_html, "4.2.1", "35279e2a39140068fc03f8874408d58eef734e488fc142153f055c5454fd1c08", [:mix], [], "hexpm", "cff108100ae2715dd959ae8f2a8cef8e20b593f8dfd031c9cba92702cf23e053"},
|
||||
"phoenix_html": {:hex, :phoenix_html, "4.3.0", "d3577a5df4b6954cd7890c84d955c470b5310bb49647f0a114a6eeecc850f7ad", [:mix], [], "hexpm", "3eaa290a78bab0f075f791a46a981bbe769d94bc776869f4f3063a14f30497ad"},
|
||||
"phoenix_html_helpers": {:hex, :phoenix_html_helpers, "1.0.1", "7eed85c52eff80a179391036931791ee5d2f713d76a81d0d2c6ebafe1e11e5ec", [:mix], [{:phoenix_html, "~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "cffd2385d1fa4f78b04432df69ab8da63dc5cf63e07b713a4dcf36a3740e3090"},
|
||||
"phoenix_live_reload": {:hex, :phoenix_live_reload, "1.5.3", "f2161c207fda0e4fb55165f650f7f8db23f02b29e3bff00ff7ef161d6ac1f09d", [:mix], [{:file_system, "~> 0.3 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.4", [hex: :phoenix, repo: "hexpm", optional: false]}], "hexpm", "b4ec9cd73cb01ff1bd1cac92e045d13e7030330b74164297d1aee3907b54803c"},
|
||||
"phoenix_live_view": {:hex, :phoenix_live_view, "1.0.4", "327491b033e79db2f887b065c5a2993228449091883d74cfa1baa12f8c98d5eb", [:mix], [{:floki, "~> 0.36", [hex: :floki, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.6.15 or ~> 1.7.0", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 3.3 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.15", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "a9865316ddf8d78f382d63af278d20436b52d262b60239956817a61279514366"},
|
||||
"phoenix_live_view": {:hex, :phoenix_live_view, "1.1.13", "11f48f8fbe5d7d0731d4e122a692e0f9ae8d5f98c54d573d29046833c34eada3", [:mix], [{:igniter, ">= 0.6.16 and < 1.0.0-0", [hex: :igniter, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:lazy_html, "~> 0.1.0", [hex: :lazy_html, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.6.15 or ~> 1.7.0 or ~> 1.8.0-rc", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 3.3 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.15", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "9d06e93573b8419ef8ee832b4a9bfe0def10b15f7c129ea477dfa54f0136f7ec"},
|
||||
"phoenix_pubsub": {:hex, :phoenix_pubsub, "2.1.3", "3168d78ba41835aecad272d5e8cd51aa87a7ac9eb836eabc42f6e57538e3731d", [:mix], [], "hexpm", "bba06bc1dcfd8cb086759f0edc94a8ba2bc8896d5331a1e2c2902bf8e36ee502"},
|
||||
"phoenix_storybook": {:hex, :phoenix_storybook, "0.8.0", "10a78f1ae3885ba2ca75160390f1fd6d9cec96ee9da722274a7841c259e5931d", [:mix], [{:earmark, "~> 1.4", [hex: :earmark, repo: "hexpm", optional: false]}, {:jason, "~> 1.3", [hex: :jason, repo: "hexpm", optional: true]}, {:makeup_eex, "~> 1.0.0", [hex: :makeup_eex, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.7.0", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html_helpers, "~> 1.0", [hex: :phoenix_html_helpers, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 1.0", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: false]}], "hexpm", "a955496db61bb43e0a64259464c01cbcfc043842ad11af9e6c3dfeb6068d5480"},
|
||||
"phoenix_storybook": {:hex, :phoenix_storybook, "0.9.3", "4f94e731d4c40d4dd7d1eddf7d5c6914366da7d78552dc565b222e4036d0d76f", [:mix], [{:earmark, "~> 1.4", [hex: :earmark, repo: "hexpm", optional: false]}, {:jason, "~> 1.3", [hex: :jason, repo: "hexpm", optional: true]}, {:makeup_eex, "~> 2.0.2", [hex: :makeup_eex, repo: "hexpm", optional: false]}, {:makeup_html, "~> 0.2.0", [hex: :makeup_html, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.8.1", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html_helpers, "~> 1.0", [hex: :phoenix_html_helpers, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 1.1.0", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: false]}], "hexpm", "4c8658b756fd8238f7e8e4343a0f12bdb91d4eba592b1c4e8118b37b6fd43e4b"},
|
||||
"phoenix_template": {:hex, :phoenix_template, "1.0.4", "e2092c132f3b5e5b2d49c96695342eb36d0ed514c5b252a77048d5969330d639", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}], "hexpm", "2c0c81f0e5c6753faf5cca2f229c9709919aba34fab866d3bc05060c9c444206"},
|
||||
"phoenix_view": {:hex, :phoenix_view, "2.0.4", "b45c9d9cf15b3a1af5fb555c674b525391b6a1fe975f040fb4d913397b31abf4", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}], "hexpm", "4e992022ce14f31fe57335db27a28154afcc94e9983266835bb3040243eb620b"},
|
||||
"php_serializer": {:hex, :php_serializer, "2.0.0", "b43f31aca22ed7321f32da2b94fe2ddf9b6739a965cb51541969119e572e821d", [:mix], [], "hexpm", "61e402e99d9062c0225a3f4fcf7e43b4cba1b8654944c0e7c139c3ca9de481da"},
|
||||
"plug": {:hex, :plug, "1.16.1", "40c74619c12f82736d2214557dedec2e9762029b2438d6d175c5074c933edc9d", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "a13ff6b9006b03d7e33874945b2755253841b238c34071ed85b0e86057f8cddc"},
|
||||
"plug_cowboy": {:hex, :plug_cowboy, "2.7.3", "1304d36752e8bdde213cea59ef424ca932910a91a07ef9f3874be709c4ddb94b", [:mix], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:cowboy_telemetry, "~> 0.3", [hex: :cowboy_telemetry, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "77c95524b2aa5364b247fa17089029e73b951ebc1adeef429361eab0bb55819d"},
|
||||
"plug": {:hex, :plug, "1.18.1", "5067f26f7745b7e31bc3368bc1a2b818b9779faa959b49c934c17730efc911cf", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "57a57db70df2b422b564437d2d33cf8d33cd16339c1edb190cd11b1a3a546cc2"},
|
||||
"plug_cowboy": {:hex, :plug_cowboy, "2.7.4", "729c752d17cf364e2b8da5bdb34fb5804f56251e88bb602aff48ae0bd8673d11", [:mix], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:cowboy_telemetry, "~> 0.3", [hex: :cowboy_telemetry, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "9b85632bd7012615bae0a5d70084deb1b25d2bcbb32cab82d1e9a1e023168aa3"},
|
||||
"plug_crypto": {:hex, :plug_crypto, "1.2.5", "918772575e48e81e455818229bf719d4ab4181fcbf7f85b68a35620f78d89ced", [:mix], [], "hexpm", "26549a1d6345e2172eb1c233866756ae44a9609bd33ee6f99147ab3fd87fd842"},
|
||||
"polymorphic_embed": {:hex, :polymorphic_embed, "5.0.3", "37444e0af941026a2c29b0539b6471bdd6737a6492a19264bf2bb0118e3ac242", [:mix], [{:attrs, "~> 0.6", [hex: :attrs, repo: "hexpm", optional: false]}, {:ecto, "~> 3.12", [hex: :ecto, repo: "hexpm", optional: false]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 4.1", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:phoenix_html_helpers, "~> 1.0", [hex: :phoenix_html_helpers, repo: "hexpm", optional: true]}, {:phoenix_live_view, "~> 0.20 or ~> 1.0", [hex: :phoenix_live_view, repo: "hexpm", optional: true]}], "hexpm", "2fed44f57abf0a0fc7642e0eb0807a55b65de1562712cc0620772cbbb80e49c1"},
|
||||
"postgrex": {:hex, :postgrex, "0.19.3", "a0bda6e3bc75ec07fca5b0a89bffd242ca209a4822a9533e7d3e84ee80707e19", [:mix], [{:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "d31c28053655b78f47f948c85bb1cf86a9c1f8ead346ba1aa0d0df017fa05b61"},
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ defmodule PlausibleWeb.Components.BillingTest do
|
|||
refute class_of_element(html, "#feature-gate-inner-block-container") =~
|
||||
"pointer-events-none"
|
||||
|
||||
refute class_of_element(html, "#feature-gate-overlay") =~ "backdrop-blur"
|
||||
refute element_exists?(html, "#feature-gate-overlay")
|
||||
end
|
||||
|
||||
test "renders upgrade cta linking to the upgrade page if user role is :owner", %{user: user} do
|
||||
|
|
|
|||
|
|
@ -480,11 +480,10 @@ defmodule PlausibleWeb.AuthControllerTest do
|
|||
test "renders `return_to` query param as hidden input", %{conn: conn} do
|
||||
conn = get(conn, "/login?return_to=/dummy.site")
|
||||
|
||||
[input_value] =
|
||||
input_value =
|
||||
conn
|
||||
|> html_response(200)
|
||||
|> Floki.parse_document!()
|
||||
|> Floki.attribute("input[name=return_to]", "value")
|
||||
|> text_of_attr("input[name=return_to]", "value")
|
||||
|
||||
assert input_value == "/dummy.site"
|
||||
end
|
||||
|
|
@ -1180,7 +1179,7 @@ defmodule PlausibleWeb.AuthControllerTest do
|
|||
|
||||
assert element_exists?(
|
||||
html,
|
||||
~s|a[data-method="post"][data-to="#{Routes.auth_path(conn, :initiate_2fa_setup)}"|
|
||||
~s|a[data-method="post"][data-to="#{Routes.auth_path(conn, :initiate_2fa_setup)}"]|
|
||||
)
|
||||
end
|
||||
|
||||
|
|
@ -1205,7 +1204,7 @@ defmodule PlausibleWeb.AuthControllerTest do
|
|||
|
||||
assert html = html_response(conn, 200)
|
||||
|
||||
assert list = [_ | _] = find(html, "#recovery-codes-list > *")
|
||||
assert list = [_ | _] = find(html, "#recovery-codes-list > *") |> LazyHTML.to_tree()
|
||||
assert length(list) == 10
|
||||
|
||||
assert user |> Repo.reload!() |> Auth.TOTP.enabled?()
|
||||
|
|
@ -1290,7 +1289,7 @@ defmodule PlausibleWeb.AuthControllerTest do
|
|||
|
||||
assert html = html_response(conn, 200)
|
||||
|
||||
assert list = [_ | _] = find(html, "#recovery-codes-list > *")
|
||||
assert list = [_ | _] = find(html, "#recovery-codes-list > *") |> LazyHTML.to_tree()
|
||||
assert length(list) == 10
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -265,7 +265,9 @@ defmodule PlausibleWeb.BillingControllerTest do
|
|||
|
||||
assert doc =~ "Looking to adjust your plan?"
|
||||
assert doc =~ "You're currently on a custom plan."
|
||||
assert Floki.text(doc) =~ "please contact us at hello@plausible.io"
|
||||
|
||||
assert LazyHTML.text(LazyHTML.from_document(doc)) =~
|
||||
"please contact us at hello@plausible.io"
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -109,12 +109,11 @@ defmodule PlausibleWeb.ErrorReportControllerTest do
|
|||
text =
|
||||
email
|
||||
|> Map.fetch!(:html_body)
|
||||
|> Floki.parse_document!()
|
||||
|> Floki.text()
|
||||
|> text()
|
||||
|
||||
assert text =~ "Reported by: Alice Bob"
|
||||
assert text =~ "Sentry trace: some-trace"
|
||||
assert text =~ "User feedback:\nhello world"
|
||||
assert text =~ "User feedback: hello world"
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -138,7 +137,7 @@ defmodule PlausibleWeb.ErrorReportControllerTest do
|
|||
|> get("/")
|
||||
|
||||
assert html = render_to_string(ErrorView, unquote(error) <> ".html", %{conn: conn})
|
||||
text = html |> Floki.parse_document!() |> Floki.text()
|
||||
text = text(html)
|
||||
assert text =~ "There has been a server error"
|
||||
assert text =~ "But don't worry, we're on it!"
|
||||
|
||||
|
|
|
|||
|
|
@ -533,7 +533,7 @@ defmodule PlausibleWeb.SiteControllerTest do
|
|||
{"Custom properties", "/#{site.domain}/settings/properties"},
|
||||
{"Integrations", "/#{site.domain}/settings/integrations"},
|
||||
{"Imports & exports", "/#{site.domain}/settings/imports-exports"},
|
||||
{"Shields", ""},
|
||||
{"Shields", nil},
|
||||
{"IP addresses", "/#{site.domain}/settings/shields/ip_addresses"},
|
||||
{"Countries", "/#{site.domain}/settings/shields/countries"},
|
||||
{"Pages", "/#{site.domain}/settings/shields/pages"},
|
||||
|
|
@ -565,7 +565,7 @@ defmodule PlausibleWeb.SiteControllerTest do
|
|||
{"Custom properties", "/#{site.domain}/settings/properties"},
|
||||
{"Integrations", "/#{site.domain}/settings/integrations"},
|
||||
{"Imports & exports", "/#{site.domain}/settings/imports-exports"},
|
||||
{"Shields", ""},
|
||||
{"Shields", nil},
|
||||
{"IP addresses", "/#{site.domain}/settings/shields/ip_addresses"},
|
||||
{"Countries", "/#{site.domain}/settings/shields/countries"},
|
||||
{"Pages", "/#{site.domain}/settings/shields/pages"},
|
||||
|
|
@ -902,10 +902,9 @@ defmodule PlausibleWeb.SiteControllerTest do
|
|||
conn = get(conn, "/#{site.domain}/settings/imports-exports")
|
||||
resp = html_response(conn, 200)
|
||||
|
||||
assert text_of_attr(resp, ~s|a[href]|, "href") =~
|
||||
"https://accounts.google.com/o/oauth2/"
|
||||
assert element_exists?(resp, ~s|a[href^="https://accounts.google.com/o/oauth2/"]|)
|
||||
|
||||
assert resp =~ "Import data"
|
||||
assert(resp =~ "Import data")
|
||||
assert resp =~ "There are no imports yet"
|
||||
assert resp =~ "Export data"
|
||||
end
|
||||
|
|
@ -927,8 +926,7 @@ defmodule PlausibleWeb.SiteControllerTest do
|
|||
conn = get(conn, "/#{site.domain}/settings/imports-exports")
|
||||
resp = html_response(conn, 200)
|
||||
|
||||
buttons = find(resp, ~s|a[data-method="delete"]|)
|
||||
assert length(buttons) == 4
|
||||
assert elem_count(resp, ~s|a[data-method="delete"]|) == 4
|
||||
|
||||
assert resp =~ "Google Analytics (123456)"
|
||||
assert resp =~ "9.9k"
|
||||
|
|
@ -1880,8 +1878,8 @@ defmodule PlausibleWeb.SiteControllerTest do
|
|||
resp = html_response(conn, 200)
|
||||
assert resp =~ Routes.site_path(conn, :change_domain_submit, site.domain)
|
||||
|
||||
assert text(resp) =~
|
||||
"Once you change your domain, you must update Plausible Installation on your site within 72 hours"
|
||||
assert resp =~
|
||||
"Once you change your domain, you <i>must</i>\n update Plausible Installation on your site within 72 hours"
|
||||
end
|
||||
|
||||
test "domain change form submission when no change is made", %{conn: conn, site: site} do
|
||||
|
|
@ -2050,6 +2048,7 @@ defmodule PlausibleWeb.SiteControllerTest do
|
|||
)
|
||||
|
||||
html = html_response(conn, 200)
|
||||
|
||||
assert text(html) =~ "This site's usage is over the limits of the team's subscription"
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ defmodule PlausibleWeb.SSOControllerTest do
|
|||
|
||||
assert html =~ "Enter your Single Sign-On email"
|
||||
assert element_exists?(html, "input[name=email]")
|
||||
assert text_of_attr(html, "input[name=return_to]", "value") == ""
|
||||
assert text_of_attr(html, ~s|input[name="return_to"]|, "value") == nil
|
||||
end
|
||||
|
||||
test "renders autosubmit js snippet when instructed", %{conn: conn} do
|
||||
|
|
@ -420,13 +420,11 @@ defmodule PlausibleWeb.SSOControllerTest do
|
|||
|
||||
assert ["Grace Holmes", "Kate Loselet", "Frank Rubin", "Grace Holmes"] =
|
||||
find(html, "table#sso-sessions-list tr td:nth-of-type(1)")
|
||||
|> Enum.map(&Floki.text/1)
|
||||
|> Enum.map(&String.trim/1)
|
||||
|> Enum.map(&text/1)
|
||||
|
||||
assert ["Device 2", "Device 4", "Device 1", "Device 3"] =
|
||||
find(html, "table#sso-sessions-list tr td:nth-of-type(2)")
|
||||
|> Enum.map(&Floki.text/1)
|
||||
|> Enum.map(&String.trim/1)
|
||||
|> Enum.map(&text/1)
|
||||
end
|
||||
|
||||
test "shows empty state when there are no sessions", %{conn: conn} do
|
||||
|
|
|
|||
|
|
@ -30,13 +30,10 @@ defmodule PlausibleWeb.StatsControllerTest do
|
|||
assert text_of_attr(resp, @react_container, "data-current-user-id") == "null"
|
||||
assert text_of_attr(resp, @react_container, "data-embedded") == ""
|
||||
|
||||
[{"div", attrs, _}] = find(resp, @react_container)
|
||||
assert Enum.all?(attrs, fn {k, v} -> is_binary(k) and is_binary(v) end)
|
||||
|
||||
assert ["noindex, nofollow"] ==
|
||||
assert "noindex, nofollow" ==
|
||||
resp
|
||||
|> find("meta[name=robots]")
|
||||
|> Floki.attribute("content")
|
||||
|> text_of_attr("content")
|
||||
|
||||
assert text_of_element(resp, "title") == "Plausible · #{site.domain}"
|
||||
end
|
||||
|
|
@ -84,10 +81,10 @@ defmodule PlausibleWeb.StatsControllerTest do
|
|||
resp = html_response(conn, 200)
|
||||
assert element_exists?(resp, @react_container)
|
||||
|
||||
assert ["index, nofollow"] ==
|
||||
assert "index, nofollow" ==
|
||||
resp
|
||||
|> find("meta[name=robots]")
|
||||
|> Floki.attribute("content")
|
||||
|> text_of_attr("content")
|
||||
|
||||
assert text_of_element(resp, "title") == "Plausible Analytics: Live Demo"
|
||||
assert resp =~ "Login"
|
||||
|
|
@ -335,9 +332,6 @@ defmodule PlausibleWeb.StatsControllerTest do
|
|||
conn = get(conn, "/" <> site.domain)
|
||||
resp = html_response(conn, 200)
|
||||
assert resp =~ "This dashboard is actually locked"
|
||||
|
||||
[{"div", attrs, _}] = find(resp, @react_container)
|
||||
assert Enum.all?(attrs, fn {k, v} -> is_binary(k) and is_binary(v) end)
|
||||
end
|
||||
|
||||
test "can view private locked verification without stats", %{conn: conn} do
|
||||
|
|
@ -356,9 +350,7 @@ defmodule PlausibleWeb.StatsControllerTest do
|
|||
|
||||
conn = get(conn, "/" <> site.domain)
|
||||
resp = html_response(conn, 200)
|
||||
|
||||
[{"div", attrs, _}] = find(resp, @react_container)
|
||||
assert Enum.all?(attrs, fn {k, v} -> is_binary(k) and is_binary(v) end)
|
||||
assert resp =~ "This dashboard is actually locked"
|
||||
end
|
||||
|
||||
on_ee do
|
||||
|
|
@ -1373,9 +1365,6 @@ defmodule PlausibleWeb.StatsControllerTest do
|
|||
assert text_of_attr(resp, @react_container, "data-current-user-id") == "null"
|
||||
assert text_of_attr(resp, @react_container, "data-current-user-role") == "public"
|
||||
assert Plug.Conn.get_resp_header(conn, "x-frame-options") == []
|
||||
|
||||
[{"div", attrs, _}] = find(resp, @react_container)
|
||||
assert Enum.all?(attrs, fn {k, v} -> is_binary(k) and is_binary(v) end)
|
||||
end
|
||||
|
||||
test "does not show header, does not show footer on embedded pages", %{conn: conn} do
|
||||
|
|
|
|||
|
|
@ -27,11 +27,11 @@ defmodule PlausibleWeb.Live.Components.ComboBoxTest do
|
|||
options = new_options(10)
|
||||
assert doc = render_sample_component(options, selected: List.last(options))
|
||||
|
||||
assert element_exists?(doc, "input[type=hidden][name=test-submit-name][value=10]")
|
||||
assert element_exists?(doc, ~s|input[type="hidden"][name="test-submit-name"][value="10"]|)
|
||||
|
||||
assert element_exists?(
|
||||
doc,
|
||||
~s|input[type=text][name=display-test-component][value="TestOption 10"]|
|
||||
~s|input[type="text"][name="display-test-component"][value="TestOption 10"]|
|
||||
)
|
||||
end
|
||||
|
||||
|
|
@ -56,7 +56,7 @@ defmodule PlausibleWeb.Live.Components.ComboBoxTest do
|
|||
refute element_exists?(doc, suggestion_li(16))
|
||||
refute element_exists?(doc, suggestion_li(17))
|
||||
|
||||
assert Floki.text(doc) =~ "Max results reached"
|
||||
assert text(doc) =~ "Max results reached"
|
||||
end
|
||||
|
||||
test "renders up to n suggestions if provided" do
|
||||
|
|
@ -71,8 +71,8 @@ defmodule PlausibleWeb.Live.Components.ComboBoxTest do
|
|||
|
||||
test "Alpine.js: renders attrs focusing suggestion elements" do
|
||||
assert doc = render_sample_component(new_options(10))
|
||||
li1 = doc |> find(suggestion_li(1)) |> List.first()
|
||||
li2 = doc |> find(suggestion_li(2)) |> List.first()
|
||||
li1 = doc |> find(suggestion_li(1))
|
||||
li2 = doc |> find(suggestion_li(2))
|
||||
|
||||
assert text_of_attr(li1, "@mouseenter") == "setFocus(1)"
|
||||
assert text_of_attr(li2, "@mouseenter") == "setFocus(2)"
|
||||
|
|
@ -204,7 +204,7 @@ defmodule PlausibleWeb.Live.Components.ComboBoxTest do
|
|||
|> element("li#dropdown-test-component-option-1 a")
|
||||
|> render_click()
|
||||
|
||||
assert element_exists?(doc, "input[type=hidden][name=some_submit_name][value=20]")
|
||||
assert element_exists?(doc, ~s|input[type="hidden"][name="some_submit_name"][value="20"]|)
|
||||
end
|
||||
|
||||
test "limits the suggestions", %{conn: conn} do
|
||||
|
|
@ -254,7 +254,7 @@ defmodule PlausibleWeb.Live.Components.ComboBoxTest do
|
|||
|> element("li#dropdown-test-creatable-component-option-1 a")
|
||||
|> render_click()
|
||||
|
||||
assert element_exists?(doc, "input[type=hidden][name=some_submit_name][value=20]")
|
||||
assert element_exists?(doc, ~s|input[type="hidden"][name="some_submit_name"][value="20"]|)
|
||||
end
|
||||
|
||||
test "suggests creating custom value", %{conn: conn} do
|
||||
|
|
@ -303,14 +303,14 @@ defmodule PlausibleWeb.Live.Components.ComboBoxTest do
|
|||
{:ok, lv, html} = live_isolated(conn, CreatableView, session: %{})
|
||||
regular_option = find(html, "li#dropdown-test-creatable-component-option-1 a")
|
||||
|
||||
assert Floki.attribute(regular_option, "x-on:click") == ["selectionInProgress = true"]
|
||||
assert text_of_attr(regular_option, "x-on:click") == "selectionInProgress = true"
|
||||
|
||||
creatable_option =
|
||||
lv
|
||||
|> type_into_combo("test-creatable-component", "my new option")
|
||||
|> find("input[type=hidden][name=some_submit_name][value=\"my new option\"]")
|
||||
|
||||
assert Floki.attribute(creatable_option, "x-on:click") == []
|
||||
assert text_of_attr(creatable_option, "x-on:click") == nil
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -31,9 +31,8 @@ defmodule PlausibleWeb.Live.Components.FormTest do
|
|||
test "renders weak password warning and hints when password too short" do
|
||||
doc = render_password_input_with_strength("too-short")
|
||||
|
||||
assert [warning_p, hint_p] = find(doc, "p")
|
||||
assert text(warning_p) == "Password is too weak"
|
||||
assert text(hint_p) != ""
|
||||
assert text_of_element(doc, "p:first-of-type") == "Password is too weak"
|
||||
assert text_of_element(doc, "p:last-of-type") != ""
|
||||
end
|
||||
|
||||
test "does not render hints and suggestions paragraph when there's none" do
|
||||
|
|
@ -46,7 +45,7 @@ defmodule PlausibleWeb.Live.Components.FormTest do
|
|||
}
|
||||
)
|
||||
|
||||
assert [warning_p] = find(doc, "p")
|
||||
assert warning_p = find(doc, "p")
|
||||
assert text(warning_p) == "Password is too weak"
|
||||
end
|
||||
|
||||
|
|
@ -54,7 +53,7 @@ defmodule PlausibleWeb.Live.Components.FormTest do
|
|||
too_long_password = String.duplicate("very-long-very-secret-1234567890", 10)
|
||||
doc = render_password_input_with_strength(too_long_password)
|
||||
|
||||
assert [error_p] = find(doc, "p")
|
||||
assert error_p = find(doc, "p")
|
||||
assert text(error_p) =~ "cannot be longer than"
|
||||
end
|
||||
end
|
||||
|
|
@ -63,7 +62,7 @@ defmodule PlausibleWeb.Live.Components.FormTest do
|
|||
test "renders for long enough password" do
|
||||
doc = render_password_length_hint("very-secret-and-very-long-123", 12)
|
||||
|
||||
assert [p_hint] = find(doc, "p")
|
||||
assert p_hint = find(doc, "p")
|
||||
assert text_of_attr(p_hint, "class") =~ "text-gray-500"
|
||||
assert text(p_hint) == "Min 12 characters"
|
||||
end
|
||||
|
|
@ -71,7 +70,7 @@ defmodule PlausibleWeb.Live.Components.FormTest do
|
|||
test "renders for too short password" do
|
||||
doc = render_password_length_hint("too-short", 12)
|
||||
|
||||
assert [p_hint] = find(doc, "p")
|
||||
assert p_hint = find(doc, "p")
|
||||
assert text_of_attr(p_hint, "class") =~ "text-red-500"
|
||||
assert text(p_hint) == "Min 12 characters"
|
||||
end
|
||||
|
|
@ -80,7 +79,7 @@ defmodule PlausibleWeb.Live.Components.FormTest do
|
|||
too_long_password = String.duplicate("very-long-very-secret-1234567890", 10)
|
||||
doc = render_password_length_hint(too_long_password, 12)
|
||||
|
||||
assert [p_hint] = find(doc, "p")
|
||||
assert p_hint = find(doc, "p")
|
||||
assert text_of_attr(p_hint, "class") =~ "text-gray-500"
|
||||
assert text(p_hint) == "Min 12 characters"
|
||||
end
|
||||
|
|
@ -92,7 +91,7 @@ defmodule PlausibleWeb.Live.Components.FormTest do
|
|||
meter = find(doc, "div.rounded-full")
|
||||
|
||||
assert text_of_attr(meter, "style") == "width: 0%"
|
||||
assert [p_warning] = find(doc, "p")
|
||||
assert p_warning = find(doc, "p")
|
||||
assert text(p_warning) == "Password is too weak"
|
||||
end
|
||||
|
||||
|
|
@ -101,7 +100,7 @@ defmodule PlausibleWeb.Live.Components.FormTest do
|
|||
meter = find(doc, "div.rounded-full")
|
||||
|
||||
assert text_of_attr(meter, "style") == "width: 25%"
|
||||
assert [p_warning] = find(doc, "p")
|
||||
assert p_warning = find(doc, "p")
|
||||
assert text(p_warning) == "Password is too weak"
|
||||
end
|
||||
|
||||
|
|
@ -110,7 +109,7 @@ defmodule PlausibleWeb.Live.Components.FormTest do
|
|||
meter = find(doc, "div.rounded-full")
|
||||
|
||||
assert text_of_attr(meter, "style") == "width: 50%"
|
||||
assert [p_warning] = find(doc, "p")
|
||||
assert p_warning = find(doc, "p")
|
||||
assert text(p_warning) == "Password is too weak"
|
||||
end
|
||||
|
||||
|
|
@ -119,7 +118,7 @@ defmodule PlausibleWeb.Live.Components.FormTest do
|
|||
meter = find(doc, "div.rounded-full")
|
||||
|
||||
assert text_of_attr(meter, "style") == "width: 75%"
|
||||
assert find(doc, "p") == []
|
||||
refute element_exists?(doc, "p")
|
||||
end
|
||||
|
||||
test "renders very strong level" do
|
||||
|
|
@ -127,7 +126,7 @@ defmodule PlausibleWeb.Live.Components.FormTest do
|
|||
meter = find(doc, "div.rounded-full")
|
||||
|
||||
assert text_of_attr(meter, "style") == "width: 100%"
|
||||
assert find(doc, "p") == []
|
||||
refute element_exists?(doc, "p")
|
||||
end
|
||||
|
||||
test "renders hints paragraph when warning hint is present" do
|
||||
|
|
@ -138,8 +137,7 @@ defmodule PlausibleWeb.Live.Components.FormTest do
|
|||
suggestions: []
|
||||
)
|
||||
|
||||
assert [_p_warning, p_hint] = find(doc, "p")
|
||||
assert text(p_hint) == "Test warning hint."
|
||||
assert text_of_element(doc, "p:last-of-type") == "Test warning hint."
|
||||
end
|
||||
|
||||
test "renders only first suggestion when no warning present" do
|
||||
|
|
@ -150,9 +148,7 @@ defmodule PlausibleWeb.Live.Components.FormTest do
|
|||
suggestions: ["Test suggestion 1.", "Test suggestion 2."]
|
||||
)
|
||||
|
||||
assert [_p_warning, p_hint] = find(doc, "p")
|
||||
assert text(p_hint) =~ "Test suggestion 1."
|
||||
refute text(p_hint) =~ "Test suggestion 2."
|
||||
assert text_of_element(doc, "p:last-of-type") == "Test suggestion 1."
|
||||
end
|
||||
|
||||
@tag :slow
|
||||
|
|
@ -164,10 +160,7 @@ defmodule PlausibleWeb.Live.Components.FormTest do
|
|||
suggestions: ["Test suggestion 1.", "Test suggestion 2."]
|
||||
)
|
||||
|
||||
assert [_p_warning, p_hint] = find(doc, "p")
|
||||
assert text(p_hint) =~ "Test warning hint."
|
||||
refute text(p_hint) =~ "Test suggestion 1."
|
||||
refute text(p_hint) =~ "Test suggestion 2."
|
||||
assert text_of_element(doc, "p:last-of-type") == "Test warning hint."
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -421,7 +421,7 @@ defmodule PlausibleWeb.Live.CustomerSupport.TeamsTest do
|
|||
|
||||
assert text_of_element(
|
||||
html,
|
||||
~s|select[name="enterprise_plan[billing_interval]"] option[selected="selected"]|
|
||||
~s|select[name="enterprise_plan[billing_interval]"] option[selected]|
|
||||
) ==
|
||||
"monthly"
|
||||
|
||||
|
|
@ -444,17 +444,17 @@ defmodule PlausibleWeb.Live.CustomerSupport.TeamsTest do
|
|||
|
||||
assert element_exists?(
|
||||
html,
|
||||
~s|input[name="enterprise_plan[features[]][stats_api]"][checked="checked"]|
|
||||
~s|input[name="enterprise_plan[features[]][stats_api]"][checked]|
|
||||
)
|
||||
|
||||
assert element_exists?(
|
||||
html,
|
||||
~s|input[name="enterprise_plan[features[]][funnels]"][checked="checked"]|
|
||||
~s|input[name="enterprise_plan[features[]][funnels]"][checked]|
|
||||
)
|
||||
|
||||
refute element_exists?(
|
||||
html,
|
||||
~s|input[name="enterprise_plan[features[]][revenue_goals]"][checked="checked"]|
|
||||
~s|input[name="enterprise_plan[features[]][revenue_goals]"][checked]|
|
||||
)
|
||||
|
||||
assert text(html) =~ "Update Plan"
|
||||
|
|
@ -788,8 +788,7 @@ defmodule PlausibleWeb.Live.CustomerSupport.TeamsTest do
|
|||
|> element(~s|button[phx-click="reveal-audit-entry"][phx-value-id="#{entry.id}"]|)
|
||||
|> render_click()
|
||||
|
||||
assert text_of_element(html, ~s|textarea|) ==
|
||||
"{ &quot;foo&quot;: &quot;bar&quot; }"
|
||||
assert text_of_element(html, ~s|textarea|) == ~s|{ "foo": "bar" }|
|
||||
end
|
||||
|
||||
test "shows audit entries when user id does not exists", %{conn: conn, user: user} do
|
||||
|
|
|
|||
|
|
@ -25,13 +25,12 @@ defmodule PlausibleWeb.Live.CustomerSupport.UsersTest do
|
|||
assert text =~ user.name
|
||||
assert text =~ user.email
|
||||
|
||||
assert [uid] = find(html, "#user-identifier")
|
||||
assert uid = find(html, "#user-identifier")
|
||||
assert text_of_attr(uid, "value") == "#{user.id}"
|
||||
|
||||
team = team_of(user)
|
||||
|
||||
assert [_] =
|
||||
find(
|
||||
assert element_exists?(
|
||||
html,
|
||||
~s|a[href="#{Routes.customer_support_team_path(PlausibleWeb.Endpoint, :show, team.id)}"]|
|
||||
)
|
||||
|
|
|
|||
|
|
@ -127,7 +127,7 @@ defmodule PlausibleWeb.Live.CustomerSupportTest do
|
|||
end
|
||||
|
||||
defp assert_search_result(doc, type, id) do
|
||||
assert [link] = find(doc, ~s|a[data-test-type="#{type}"][data-test-id="#{id}"]|)
|
||||
assert link = find(doc, ~s|a[data-test-type="#{type}"][data-test-id="#{id}"]|)
|
||||
|
||||
assert text_of_attr(link, "href") ==
|
||||
apply(Routes, :"customer_support_#{type}_path", [
|
||||
|
|
@ -138,7 +138,7 @@ defmodule PlausibleWeb.Live.CustomerSupportTest do
|
|||
end
|
||||
|
||||
defp refute_search_result(doc, type, id) do
|
||||
assert find(doc, ~s|a[data-test-type="#{type}"][data-test-id="#{id}"]|) == []
|
||||
refute element_exists?(doc, ~s|a[data-test-type="#{type}"][data-test-id="#{id}"]|)
|
||||
end
|
||||
|
||||
defp type_into_input(lv, id, text) do
|
||||
|
|
|
|||
|
|
@ -70,8 +70,8 @@ defmodule PlausibleWeb.Live.FunnelSettings.FormTest do
|
|||
|> element("li#dropdown-step-1-option-1 a")
|
||||
|> render_click()
|
||||
|
||||
assert element_exists?(doc, ~s/#li#dropdown-step-1-option-15/)
|
||||
refute element_exists?(doc, ~s/#li#dropdown-step-1-option-16/)
|
||||
assert element_exists?(doc, ~s/li#dropdown-step-1-option-15/)
|
||||
refute element_exists?(doc, ~s/li#dropdown-step-1-option-16/)
|
||||
end
|
||||
|
||||
test "removing one option alters suggestions for other", %{conn: conn, site: site} do
|
||||
|
|
|
|||
|
|
@ -19,9 +19,9 @@ defmodule PlausibleWeb.Live.FunnelSettingsTest do
|
|||
|> Plausible.Repo.update!()
|
||||
|
||||
conn = get(conn, "/#{site.domain}/settings/funnels")
|
||||
resp = conn |> html_response(200) |> text()
|
||||
resp = conn |> html_response(200)
|
||||
|
||||
assert resp =~ "please upgrade your subscription"
|
||||
assert text(resp) =~ "please upgrade your subscription"
|
||||
end
|
||||
|
||||
test "lists funnels for the site and renders help link", %{conn: conn, site: site} do
|
||||
|
|
@ -53,12 +53,12 @@ defmodule PlausibleWeb.Live.FunnelSettingsTest do
|
|||
|
||||
assert element_exists?(
|
||||
resp,
|
||||
~s/button[phx-click="delete-funnel"][phx-value-funnel-id=#{f1_id}]#delete-funnel-#{f1_id}/
|
||||
~s/button[phx-click="delete-funnel"][phx-value-funnel-id="#{f1_id}"]#delete-funnel-#{f1_id}/
|
||||
)
|
||||
|
||||
assert element_exists?(
|
||||
resp,
|
||||
~s/button[phx-click="delete-funnel"][phx-value-funnel-id=#{f2_id}]#delete-funnel-#{f2_id}/
|
||||
~s/button[phx-click="delete-funnel"][phx-value-funnel-id="#{f2_id}"]#delete-funnel-#{f2_id}/
|
||||
)
|
||||
end
|
||||
|
||||
|
|
@ -77,7 +77,7 @@ defmodule PlausibleWeb.Live.FunnelSettingsTest do
|
|||
conn = get(conn, "/#{site.domain}/settings/funnels")
|
||||
|
||||
doc = conn |> html_response(200)
|
||||
assert Floki.text(doc) =~ "Set up a few goals first"
|
||||
assert text(doc) =~ "Set up a few goals first"
|
||||
|
||||
add_goals_path = Routes.site_path(conn, :settings_goals, site.domain)
|
||||
assert element_exists?(doc, ~s/a[href="#{add_goals_path}"]/)
|
||||
|
|
@ -316,7 +316,7 @@ defmodule PlausibleWeb.Live.FunnelSettingsTest do
|
|||
lv = get_liveview(conn, site)
|
||||
|
||||
lv
|
||||
|> element(~s/button[phx-click="edit-funnel"][phx-value-funnel-id=#{f1_id}]/)
|
||||
|> element(~s/button[phx-click="edit-funnel"][phx-value-funnel-id="#{f1_id}"]/)
|
||||
|> render_click()
|
||||
|
||||
assert lv = find_live_child(lv, "funnels-form")
|
||||
|
|
@ -337,7 +337,7 @@ defmodule PlausibleWeb.Live.FunnelSettingsTest do
|
|||
lv = get_liveview(conn, site)
|
||||
|
||||
lv
|
||||
|> element(~s/button[phx-click="edit-funnel"][phx-value-funnel-id=#{f1_id}]/)
|
||||
|> element(~s/button[phx-click="edit-funnel"][phx-value-funnel-id="#{f1_id}"]/)
|
||||
|> render_click()
|
||||
|
||||
assert lv = find_live_child(lv, "funnels-form")
|
||||
|
|
|
|||
|
|
@ -248,7 +248,7 @@ defmodule PlausibleWeb.Live.GoalSettings.FormTest do
|
|||
lv |> element(~s/button#edit-goal-#{g.id}/) |> render_click()
|
||||
|
||||
html = render(lv)
|
||||
assert element_exists?(html, ~s|#page_path_input_modalseq0[value="/go/to/blog/**"|)
|
||||
assert element_exists?(html, ~s|#page_path_input_modalseq0[value="/go/to/blog/**"]|)
|
||||
|
||||
lv
|
||||
|> element("#goals-form-modalseq0 form")
|
||||
|
|
@ -269,7 +269,7 @@ defmodule PlausibleWeb.Live.GoalSettings.FormTest do
|
|||
lv |> element(~s/button#edit-goal-#{g.id}/) |> render_click()
|
||||
|
||||
html = render(lv)
|
||||
assert element_exists?(html, ~s|#page_path_input_modalseq0[value="/go/to/blog/**"|)
|
||||
assert element_exists?(html, ~s|#page_path_input_modalseq0[value="/go/to/blog/**"]|)
|
||||
|
||||
lv
|
||||
|> element("#goals-form-modalseq0 form")
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ defmodule PlausibleWeb.Live.GoalSettingsTest do
|
|||
|
||||
refute element_exists?(
|
||||
resp,
|
||||
~s/button[phx-click="edit-goal"][phx-value-goal-id=#{g3.id}][disabled]#edit-goal-#{g3.id}/
|
||||
~s/button[phx-click="edit-goal"][phx-value-goal-id="#{g3.id}"][disabled]#edit-goal-#{g3.id}/
|
||||
)
|
||||
end
|
||||
|
||||
|
|
@ -58,12 +58,12 @@ defmodule PlausibleWeb.Live.GoalSettingsTest do
|
|||
for g <- goals do
|
||||
assert element_exists?(
|
||||
resp,
|
||||
~s/button[phx-click="delete-goal"][phx-value-goal-id=#{g.id}]#delete-goal-#{g.id}/
|
||||
~s/button[phx-click="delete-goal"][phx-value-goal-id="#{g.id}"]#delete-goal-#{g.id}/
|
||||
)
|
||||
|
||||
assert element_exists?(
|
||||
resp,
|
||||
~s/button[phx-click="edit-goal"][phx-value-goal-id=#{g.id}]#edit-goal-#{g.id}/
|
||||
~s/button[phx-click="edit-goal"][phx-value-goal-id="#{g.id}"]#edit-goal-#{g.id}/
|
||||
)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -174,7 +174,7 @@ defmodule PlausibleWeb.Live.InstallationTest do
|
|||
{lv, html} = get_lv(conn, site, "?installation_type=manual")
|
||||
|
||||
assert text_of_element(html, "textarea#snippet") ==
|
||||
"&lt;script defer data-domain=&quot;#{site.domain}&quot; src=&quot;http://localhost:8000/js/script.js&quot;&gt;&lt;/script&gt;"
|
||||
~s|<script defer data-domain="#{site.domain}" src="http://localhost:8000/js/script.js"></script>|
|
||||
|
||||
for {param, script_extension} <- PlausibleWeb.Live.Installation.script_extension_params() do
|
||||
lv
|
||||
|
|
@ -188,7 +188,9 @@ defmodule PlausibleWeb.Live.InstallationTest do
|
|||
|
||||
lv
|
||||
|> element(~s|form#snippet-form|)
|
||||
|> render_change(%{})
|
||||
|> render_change(%{
|
||||
param => "off"
|
||||
})
|
||||
|
||||
html = lv |> render()
|
||||
assert text_of_element(html, "textarea#snippet") =~ "/js/script.js"
|
||||
|
|
@ -214,7 +216,9 @@ defmodule PlausibleWeb.Live.InstallationTest do
|
|||
|
||||
lv
|
||||
|> element(~s|form#snippet-form|)
|
||||
|> render_change(%{})
|
||||
|> render_change(%{
|
||||
param => "off"
|
||||
})
|
||||
|
||||
html = lv |> render()
|
||||
assert text_of_element(html, "textarea#snippet") =~ "/js/script.js"
|
||||
|
|
@ -235,16 +239,18 @@ defmodule PlausibleWeb.Live.InstallationTest do
|
|||
html = lv |> render()
|
||||
|
||||
assert text_of_element(html, "textarea#snippet") =~
|
||||
"function() { (window.plausible.q = window.plausible.q || []).push(arguments) }&lt;/script&gt;"
|
||||
"function() { (window.plausible.q = window.plausible.q || []).push(arguments) }</script>"
|
||||
|
||||
lv
|
||||
|> element(~s|form#snippet-form|)
|
||||
|> render_change(%{})
|
||||
|> render_change(%{
|
||||
"track_404_pages" => "off"
|
||||
})
|
||||
|
||||
html = lv |> render()
|
||||
|
||||
refute text_of_element(html, "textarea#snippet") =~
|
||||
"function() { (window.plausible.q = window.plausible.q || []).push(arguments) }&lt;/script&gt;"
|
||||
"function() { (window.plausible.q = window.plausible.q || []).push(arguments) }</script>"
|
||||
end
|
||||
|
||||
test "turning on file-downloads, outbound-links and 404 creates special goals", %{
|
||||
|
|
@ -295,7 +301,8 @@ defmodule PlausibleWeb.Live.InstallationTest do
|
|||
|> element(~s|form#snippet-form|)
|
||||
|> render_change(%{
|
||||
"file_downloads" => "on",
|
||||
"outbound_links" => "on"
|
||||
"outbound_links" => "on",
|
||||
"track_404_pages" => "off"
|
||||
})
|
||||
|
||||
assert render(lv) =~ "Snippet updated and goal deleted"
|
||||
|
|
@ -303,14 +310,20 @@ defmodule PlausibleWeb.Live.InstallationTest do
|
|||
lv
|
||||
|> element(~s|form#snippet-form|)
|
||||
|> render_change(%{
|
||||
"file_downloads" => "on"
|
||||
"file_downloads" => "on",
|
||||
"outbound_links" => "off",
|
||||
"track_404_pages" => "off"
|
||||
})
|
||||
|
||||
assert render(lv) =~ "Snippet updated and goal deleted"
|
||||
|
||||
lv
|
||||
|> element(~s|form#snippet-form|)
|
||||
|> render_change(%{})
|
||||
|> render_change(%{
|
||||
"file_downloads" => "off",
|
||||
"outbound_links" => "off",
|
||||
"track_404_pages" => "off"
|
||||
})
|
||||
|
||||
assert render(lv) =~ "Snippet updated and goal deleted"
|
||||
|
||||
|
|
@ -336,7 +349,12 @@ defmodule PlausibleWeb.Live.InstallationTest do
|
|||
|
||||
lv
|
||||
|> element(~s|form#snippet-form|)
|
||||
|> render_change(%{})
|
||||
|> render_change(%{
|
||||
"tagged_events" => "off",
|
||||
"hash_based_routing" => "off",
|
||||
"pageview_props" => "off",
|
||||
"revenue_tracking" => "off"
|
||||
})
|
||||
|
||||
assert render(lv) =~ "Snippet updated. Please insert the newest snippet into your site"
|
||||
end
|
||||
|
|
|
|||
|
|
@ -418,6 +418,7 @@ defmodule PlausibleWeb.Live.InstallationV2Test do
|
|||
|
||||
html = render_async(lv, 500)
|
||||
assert html =~ "Verify Tag Manager installation"
|
||||
|
||||
assert text(html) =~ "We've detected your website is using Google Tag Manager"
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -56,12 +56,12 @@ defmodule PlausibleWeb.Live.PluginsAPISettingsTest do
|
|||
|
||||
assert element_exists?(
|
||||
resp,
|
||||
~s/button[phx-click="revoke-token"][phx-value-token-id=#{t1.id}]#revoke-token-#{t1.id}/
|
||||
~s/button[phx-click="revoke-token"][phx-value-token-id="#{t1.id}"]#revoke-token-#{t1.id}/
|
||||
)
|
||||
|
||||
assert element_exists?(
|
||||
resp,
|
||||
~s/button[phx-click="revoke-token"][phx-value-token-id=#{t2.id}]#revoke-token-#{t2.id}/
|
||||
~s/button[phx-click="revoke-token"][phx-value-token-id="#{t2.id}"]#revoke-token-#{t2.id}/
|
||||
)
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -147,7 +147,7 @@ defmodule PlausibleWeb.Live.PropsSettings.FormTest do
|
|||
|
||||
defp type_into_combo(lv, id, text) do
|
||||
lv
|
||||
|> element("input##{id}")
|
||||
|> element("input#{id}")
|
||||
|> render_change(%{
|
||||
"_target" => ["display-#{id}"],
|
||||
"display-#{id}" => "#{text}"
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ defmodule PlausibleWeb.Live.RegisterFormTest do
|
|||
email_input,
|
||||
password_input,
|
||||
password_confirmation_input | _
|
||||
] = find(html, "input")
|
||||
] = find(html, "input") |> Enum.into([])
|
||||
|
||||
assert String.length(text_of_attr(csrf_input, "value")) > 0
|
||||
assert text_of_attr(action_input, "value") == "register_form"
|
||||
|
|
@ -130,11 +130,11 @@ defmodule PlausibleWeb.Live.RegisterFormTest do
|
|||
test "pushing send-metrics-after event submits the form", %{conn: conn} do
|
||||
lv = get_liveview(conn, "/register")
|
||||
|
||||
refute render(lv) =~ ~s|phx-trigger-action="phx-trigger-action"|
|
||||
refute render(lv) =~ ~s|phx-trigger-action=""|
|
||||
|
||||
render_hook(lv, "send-metrics-after", %{event_name: "Signup", params: %{}})
|
||||
|
||||
assert render(lv) =~ ~s|phx-trigger-action="phx-trigger-action"|
|
||||
assert render(lv) =~ ~s|phx-trigger-action=""|
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -171,7 +171,7 @@ defmodule PlausibleWeb.Live.RegisterFormTest do
|
|||
name_input,
|
||||
password_input,
|
||||
password_confirmation_input | _
|
||||
] = find(html, "input")
|
||||
] = find(html, "input") |> Enum.into([])
|
||||
|
||||
assert String.length(text_of_attr(csrf_input, "value")) > 0
|
||||
assert text_of_attr(action_input, "value") == "register_from_invitation_form"
|
||||
|
|
@ -220,7 +220,7 @@ defmodule PlausibleWeb.Live.RegisterFormTest do
|
|||
name_input,
|
||||
password_input,
|
||||
password_confirmation_input | _
|
||||
] = find(html, "input")
|
||||
] = find(html, "input") |> Enum.into([])
|
||||
|
||||
assert String.length(text_of_attr(csrf_input, "value")) > 0
|
||||
assert text_of_attr(action_input, "value") == "register_from_invitation_form"
|
||||
|
|
@ -272,7 +272,7 @@ defmodule PlausibleWeb.Live.RegisterFormTest do
|
|||
_csrf_input,
|
||||
_action_input,
|
||||
email_input | _
|
||||
] = find(html, "input")
|
||||
] = find(html, "input") |> Enum.into([])
|
||||
|
||||
# attempt at tampering with form
|
||||
assert text_of_attr(email_input, "value") == "mary.sue@plausible.test"
|
||||
|
|
@ -311,11 +311,11 @@ defmodule PlausibleWeb.Live.RegisterFormTest do
|
|||
} do
|
||||
lv = get_liveview(conn, "/register/invitation/#{guest_invitation.invitation_id}")
|
||||
|
||||
refute render(lv) =~ ~s|phx-trigger-action="phx-trigger-action"|
|
||||
refute render(lv) =~ ~s|phx-trigger-action=""|
|
||||
|
||||
render_hook(lv, "send-metrics-after", %{event_name: "Signup via invitation", params: %{}})
|
||||
|
||||
assert render(lv) =~ ~s|phx-trigger-action="phx-trigger-action"|
|
||||
assert render(lv) =~ ~s|phx-trigger-action=""|
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,8 @@ defmodule PlausibleWeb.Live.ResetPasswordFormTest do
|
|||
type_into_passowrd(lv, "very-secret-and-very-long-123")
|
||||
html = lv |> element("form") |> render_submit()
|
||||
|
||||
assert [csrf_input, password_input | _] = find(html, "input")
|
||||
csrf_input = find(html, ~s|input[name="_csrf_token"]|)
|
||||
password_input = find(html, ~s|input[name="user[password]"]|)
|
||||
assert String.length(text_of_attr(csrf_input, "value")) > 0
|
||||
assert text_of_attr(password_input, "value") == "very-secret-and-very-long-123"
|
||||
assert %{password_hash: new_hash} = Repo.one(User)
|
||||
|
|
|
|||
|
|
@ -33,10 +33,10 @@ defmodule PlausibleWeb.Live.Shields.CountriesTest do
|
|||
assert remove_button_1 = find(resp, "#remove-country-rule-#{r1.id}")
|
||||
assert remove_button_2 = find(resp, "#remove-country-rule-#{r2.id}")
|
||||
|
||||
assert text_of_attr(remove_button_1, "phx-click" == "remove-country-rule")
|
||||
assert text_of_attr(remove_button_1, "phx-value-rule-id" == r1.id)
|
||||
assert text_of_attr(remove_button_2, "phx-click" == "remove-country-rule")
|
||||
assert text_of_attr(remove_button_2, "phx-value-rule-id" == r2.id)
|
||||
assert text_of_attr(remove_button_1, "phx-click") == "remove-country-rule"
|
||||
assert text_of_attr(remove_button_1, "phx-value-rule-id") == r1.id
|
||||
assert text_of_attr(remove_button_2, "phx-click") == "remove-country-rule"
|
||||
assert text_of_attr(remove_button_2, "phx-value-rule-id") == r2.id
|
||||
end
|
||||
|
||||
test "add rule button is rendered", %{conn: conn, site: site} do
|
||||
|
|
|
|||
|
|
@ -34,10 +34,10 @@ defmodule PlausibleWeb.Live.Shields.HostnamesTest do
|
|||
assert remove_button_1 = find(resp, "#remove-hostname-rule-#{r1.id}")
|
||||
assert remove_button_2 = find(resp, "#remove-hostname-rule-#{r2.id}")
|
||||
|
||||
assert text_of_attr(remove_button_1, "phx-click" == "remove-hostname-rule")
|
||||
assert text_of_attr(remove_button_1, "phx-value-rule-id" == r1.id)
|
||||
assert text_of_attr(remove_button_2, "phx-click" == "remove-hostname-rule")
|
||||
assert text_of_attr(remove_button_2, "phx-value-rule-id" == r2.id)
|
||||
assert text_of_attr(remove_button_1, "phx-click") == "remove-hostname-rule"
|
||||
assert text_of_attr(remove_button_1, "phx-value-rule-id") == r1.id
|
||||
assert text_of_attr(remove_button_2, "phx-click") == "remove-hostname-rule"
|
||||
assert text_of_attr(remove_button_2, "phx-value-rule-id") == r2.id
|
||||
end
|
||||
|
||||
test "add rule button is rendered", %{conn: conn, site: site} do
|
||||
|
|
|
|||
|
|
@ -36,10 +36,10 @@ defmodule PlausibleWeb.Live.Shields.IPAddressesTest do
|
|||
assert remove_button_1 = find(resp, "#remove-ip-rule-#{r1.id}")
|
||||
assert remove_button_2 = find(resp, "#remove-ip-rule-#{r2.id}")
|
||||
|
||||
assert text_of_attr(remove_button_1, "phx-click" == "remove-ip-rule")
|
||||
assert text_of_attr(remove_button_1, "phx-value-rule-id" == r1.id)
|
||||
assert text_of_attr(remove_button_2, "phx-click" == "remove-ip-rule")
|
||||
assert text_of_attr(remove_button_2, "phx-value-rule-id" == r2.id)
|
||||
assert text_of_attr(remove_button_1, "phx-click") == "remove-ip-rule"
|
||||
assert text_of_attr(remove_button_1, "phx-value-rule-id") == r1.id
|
||||
assert text_of_attr(remove_button_2, "phx-click") == "remove-ip-rule"
|
||||
assert text_of_attr(remove_button_2, "phx-value-rule-id") == r2.id
|
||||
end
|
||||
|
||||
test "add rule button is rendered", %{conn: conn, site: site} do
|
||||
|
|
|
|||
|
|
@ -33,10 +33,10 @@ defmodule PlausibleWeb.Live.Shields.PagesTest do
|
|||
assert remove_button_1 = find(resp, "#remove-page-rule-#{r1.id}")
|
||||
assert remove_button_2 = find(resp, "#remove-page-rule-#{r2.id}")
|
||||
|
||||
assert text_of_attr(remove_button_1, "phx-click" == "remove-page-rule")
|
||||
assert text_of_attr(remove_button_1, "phx-value-rule-id" == r1.id)
|
||||
assert text_of_attr(remove_button_2, "phx-click" == "remove-page-rule")
|
||||
assert text_of_attr(remove_button_2, "phx-value-rule-id" == r2.id)
|
||||
assert text_of_attr(remove_button_1, "phx-click") == "remove-page-rule"
|
||||
assert text_of_attr(remove_button_1, "phx-value-rule-id") == r1.id
|
||||
assert text_of_attr(remove_button_2, "phx-click") == "remove-page-rule"
|
||||
assert text_of_attr(remove_button_2, "phx-value-rule-id") == r2.id
|
||||
end
|
||||
|
||||
test "add rule button is rendered", %{conn: conn, site: site} do
|
||||
|
|
|
|||
|
|
@ -73,26 +73,22 @@ defmodule PlausibleWeb.Live.SitesTest do
|
|||
assert text_of_element(html, "#invitation-#{invitation2.invitation_id}") =~
|
||||
"G.I. Jane has invited you to join the \"My Personal Sites\" as editor member."
|
||||
|
||||
assert [_] =
|
||||
find(
|
||||
assert element_exists?(
|
||||
html,
|
||||
~s|#invitation-#{invitation1.invitation_id} a[href="#{Routes.invitation_path(PlausibleWeb.Endpoint, :accept_invitation, invitation1.invitation_id)}"]|
|
||||
)
|
||||
|
||||
assert [_] =
|
||||
find(
|
||||
assert element_exists?(
|
||||
html,
|
||||
~s|#invitation-#{invitation1.invitation_id} a[href="#{Routes.invitation_path(PlausibleWeb.Endpoint, :reject_invitation, invitation1.invitation_id)}"]|
|
||||
)
|
||||
|
||||
assert [_] =
|
||||
find(
|
||||
assert element_exists?(
|
||||
html,
|
||||
~s|#invitation-#{invitation2.invitation_id} a[href="#{Routes.invitation_path(PlausibleWeb.Endpoint, :accept_invitation, invitation2.invitation_id)}"]|
|
||||
)
|
||||
|
||||
assert [_] =
|
||||
find(
|
||||
assert element_exists?(
|
||||
html,
|
||||
~s|#invitation-#{invitation2.invitation_id} a[href="#{Routes.invitation_path(PlausibleWeb.Endpoint, :reject_invitation, invitation2.invitation_id)}"]|
|
||||
)
|
||||
|
|
@ -356,7 +352,8 @@ defmodule PlausibleWeb.Live.SitesTest do
|
|||
|> element(button_selector)
|
||||
|> render_click()
|
||||
|
||||
assert text(html) =~ "Looks like you've hit the pinned sites limit!"
|
||||
assert html =~
|
||||
LazyHTML.html_escape("Looks like you've hit the pinned sites limit!")
|
||||
end
|
||||
|
||||
test "does not allow pinning site user doesn't have access to", %{conn: conn, user: user} do
|
||||
|
|
|
|||
|
|
@ -210,7 +210,7 @@ defmodule PlausibleWeb.Live.SSOMangementTest do
|
|||
|
||||
assert text_of_attr(
|
||||
html,
|
||||
~s|#sso-policy_sso_default_role option[selected="selected"]|,
|
||||
~s|#sso-policy_sso_default_role option[selected]|,
|
||||
"value"
|
||||
) == "viewer"
|
||||
|
||||
|
|
@ -229,7 +229,7 @@ defmodule PlausibleWeb.Live.SSOMangementTest do
|
|||
|
||||
assert text_of_attr(
|
||||
html,
|
||||
~s|#sso-policy_sso_default_role option[selected="selected"]|,
|
||||
~s|#sso-policy_sso_default_role option[selected]|,
|
||||
"value"
|
||||
) == "admin"
|
||||
|
||||
|
|
|
|||
|
|
@ -166,14 +166,14 @@ defmodule PlausibleWeb.Live.TeamMangementTest do
|
|||
|
||||
html = render(lv)
|
||||
|
||||
assert length(find(html, member_el())) == 1
|
||||
assert elem_count(html, member_el()) == 1
|
||||
|
||||
assert text_of_element(html, "#{guest_el()}:first-of-type button") == "Guest"
|
||||
|
||||
change_role(lv, 1, "viewer", guest_el())
|
||||
html = render(lv)
|
||||
|
||||
assert length(find(html, member_el())) == 2
|
||||
assert elem_count(html, member_el()) == 2
|
||||
refute element_exists?(html, "#guest-list")
|
||||
end
|
||||
|
||||
|
|
@ -226,8 +226,8 @@ defmodule PlausibleWeb.Live.TeamMangementTest do
|
|||
|
||||
html = render(lv)
|
||||
|
||||
assert html |> find(member_el()) |> Enum.count() == 4
|
||||
assert html |> find(guest_el()) |> Enum.count() == 1
|
||||
assert elem_count(html, member_el()) == 4
|
||||
assert elem_count(html, guest_el()) == 1
|
||||
|
||||
pending = find(html, "#{member_el()}:nth-of-type(1)") |> text()
|
||||
sent = find(html, "#{member_el()}:nth-of-type(2)") |> text()
|
||||
|
|
@ -259,7 +259,7 @@ defmodule PlausibleWeb.Live.TeamMangementTest do
|
|||
|
||||
html = render(lv)
|
||||
|
||||
assert html |> find(member_el()) |> Enum.count() == 1
|
||||
assert elem_count(html, member_el()) == 1
|
||||
refute element_exists?(html, "#guest-list")
|
||||
|
||||
assert_email_delivered_with(
|
||||
|
|
@ -296,8 +296,8 @@ defmodule PlausibleWeb.Live.TeamMangementTest do
|
|||
|
||||
html = render(lv)
|
||||
|
||||
assert html |> find(member_el()) |> Enum.count() == 3
|
||||
assert html |> find(guest_el()) |> Enum.count() == 1
|
||||
assert elem_count(html, member_el()) == 3
|
||||
assert elem_count(html, guest_el()) == 1
|
||||
|
||||
sent = find(html, "#{member_el()}:nth-of-type(1)") |> text()
|
||||
owner = find(html, "#{member_el()}:nth-of-type(2)") |> text()
|
||||
|
|
@ -324,7 +324,7 @@ defmodule PlausibleWeb.Live.TeamMangementTest do
|
|||
|
||||
html = render(lv)
|
||||
|
||||
assert html |> find(member_el()) |> Enum.count() == 1
|
||||
assert elem_count(html, member_el()) == 1
|
||||
refute element_exists?(html, "#guest-list")
|
||||
|
||||
assert_email_delivered_with(
|
||||
|
|
|
|||
|
|
@ -196,14 +196,14 @@ defmodule PlausibleWeb.Live.TeamSetupTest do
|
|||
|
||||
html = render(lv)
|
||||
|
||||
assert length(find(html, member_el())) == 1
|
||||
assert elem_count(html, member_el()) == 1
|
||||
|
||||
assert text_of_element(html, "#{guest_el()}:first-of-type button") == "Guest"
|
||||
|
||||
change_role(lv, 1, "viewer", guest_el())
|
||||
html = render(lv)
|
||||
|
||||
assert length(find(html, member_el())) == 2
|
||||
assert elem_count(html, member_el()) == 2
|
||||
refute element_exists?(html, "#guest-list")
|
||||
|
||||
save_layout(lv)
|
||||
|
|
@ -263,8 +263,8 @@ defmodule PlausibleWeb.Live.TeamSetupTest do
|
|||
|
||||
html = lv |> render()
|
||||
|
||||
assert [_ | _] = find(html, "#{member_el()}:nth-of-type(1) a")
|
||||
assert find(html, "#{member_el()}:nth-of-type(2) a") == []
|
||||
assert element_exists?(html, "#{member_el()}:nth-of-type(1) a")
|
||||
refute element_exists?(html, "#{member_el()}:nth-of-type(2) a")
|
||||
end
|
||||
|
||||
test "allows removing any type of entry", %{
|
||||
|
|
@ -288,8 +288,8 @@ defmodule PlausibleWeb.Live.TeamSetupTest do
|
|||
|
||||
html = render(lv)
|
||||
|
||||
assert html |> find(member_el()) |> Enum.count() == 4
|
||||
assert html |> find(guest_el()) |> Enum.count() == 1
|
||||
assert elem_count(html, member_el()) == 4
|
||||
assert elem_count(html, guest_el()) == 1
|
||||
|
||||
pending = find(html, "#{member_el()}:nth-of-type(1)") |> text()
|
||||
sent = find(html, "#{member_el()}:nth-of-type(2)") |> text()
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
defmodule PlausibleWeb.FaviconTest do
|
||||
use Plausible.DataCase, async: true
|
||||
use Plug.Test
|
||||
import Plug.Test
|
||||
alias PlausibleWeb.Favicon
|
||||
|
||||
import Mox
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
defmodule PlausibleWeb.Plugs.NoRobotsTest do
|
||||
use Plausible.DataCase, async: true
|
||||
use Plug.Test
|
||||
import Plug.Test
|
||||
import Plug.Conn
|
||||
|
||||
alias PlausibleWeb.Plugs.NoRobots
|
||||
|
||||
|
|
|
|||
|
|
@ -14,8 +14,8 @@ defmodule PlausibleWeb.TrackerPlugTest do
|
|||
do regenerate the files before running tests, so they're up to date.
|
||||
"""
|
||||
use PlausibleWeb.ConnCase, async: true
|
||||
use Plug.Test
|
||||
use Plausible.Teams.Test
|
||||
import Plug.Test
|
||||
|
||||
alias PlausibleWeb.Tracker
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
defmodule Plausible.Test.Support.HTML do
|
||||
Code.ensure_compiled!(Floki)
|
||||
|
||||
@moduledoc """
|
||||
Floki wrappers to help make assertions about HTML/DOM structures
|
||||
LazyHTML wrappers to help make assertions about HTML/DOM structures
|
||||
"""
|
||||
|
||||
def element_exists?(html, selector) do
|
||||
|
|
@ -12,14 +10,10 @@ defmodule Plausible.Test.Support.HTML do
|
|||
|> Kernel.not()
|
||||
end
|
||||
|
||||
def find(html, value) when is_binary(html) do
|
||||
def find(html, selector) do
|
||||
html
|
||||
|> Floki.parse_document!()
|
||||
|> Floki.find(value)
|
||||
end
|
||||
|
||||
def find(html, value) do
|
||||
Floki.find(html, value)
|
||||
|> lazy_parse()
|
||||
|> LazyHTML.query(selector)
|
||||
end
|
||||
|
||||
def submit_button(html, form) do
|
||||
|
|
@ -30,17 +24,20 @@ defmodule Plausible.Test.Support.HTML do
|
|||
element_exists?(html, "form[action=\"" <> action_path <> "\"]")
|
||||
end
|
||||
|
||||
def text_of_element(html, element) do
|
||||
def text_of_element(html, selector) do
|
||||
html
|
||||
|> find(element)
|
||||
|> Floki.text()
|
||||
|> String.trim()
|
||||
|> String.replace(~r/\s+/, " ")
|
||||
|> find(selector)
|
||||
|> text()
|
||||
end
|
||||
|
||||
def elem_count(html, selector) do
|
||||
find(html, selector) |> Enum.count()
|
||||
end
|
||||
|
||||
def text(element) do
|
||||
element
|
||||
|> Floki.text()
|
||||
|> lazy_parse()
|
||||
|> LazyHTML.text()
|
||||
|> String.trim()
|
||||
|> String.replace(~r/\s+/, " ")
|
||||
end
|
||||
|
|
@ -49,7 +46,7 @@ defmodule Plausible.Test.Support.HTML do
|
|||
empty? =
|
||||
html
|
||||
|> find(element)
|
||||
|> Floki.attribute(attr)
|
||||
|> LazyHTML.attribute(attr)
|
||||
|> Enum.empty?()
|
||||
|
||||
not empty?
|
||||
|
|
@ -61,20 +58,34 @@ defmodule Plausible.Test.Support.HTML do
|
|||
|> text_of_attr("class")
|
||||
end
|
||||
|
||||
def text_of_attr(html, element, attr) do
|
||||
def text_of_attr(html, selector, attr) do
|
||||
html
|
||||
|> find(element)
|
||||
|> find(selector)
|
||||
|> text_of_attr(attr)
|
||||
end
|
||||
|
||||
def text_of_attr(element, attr) do
|
||||
element
|
||||
|> Floki.attribute(attr)
|
||||
|> Floki.text()
|
||||
|> String.trim()
|
||||
case LazyHTML.attribute(lazy_parse(element), attr) do
|
||||
[] ->
|
||||
nil
|
||||
|
||||
[value] ->
|
||||
value
|
||||
|
||||
[_ | _] ->
|
||||
raise "Multiple attributes found. Narrow down the element you are looking for"
|
||||
end
|
||||
end
|
||||
|
||||
def name_of(element) do
|
||||
List.first(Floki.attribute(element, "name"))
|
||||
text_of_attr(element, "name")
|
||||
end
|
||||
|
||||
defp lazy_parse(%LazyHTML{} = lazy) do
|
||||
lazy
|
||||
end
|
||||
|
||||
defp lazy_parse(element) when is_binary(element) do
|
||||
LazyHTML.from_fragment(element)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -388,14 +388,9 @@ defmodule Plausible.Workers.SendEmailReportTest do
|
|||
html_body: html_body
|
||||
})
|
||||
|
||||
page_names = find(html_body, ".page-name")
|
||||
assert length(page_names) == 5
|
||||
|
||||
referrer_names = find(html_body, ".referrer-name")
|
||||
assert length(referrer_names) == 5
|
||||
|
||||
goal_names = find(html_body, ".goal-name")
|
||||
assert length(goal_names) == 5
|
||||
assert elem_count(html_body, ".page-name") == 5
|
||||
assert elem_count(html_body, ".referrer-name") == 5
|
||||
assert elem_count(html_body, ".goal-name") == 5
|
||||
end
|
||||
|
||||
test "email subject includes month name" do
|
||||
|
|
|
|||
Loading…
Reference in New Issue