Skip to content

Liveview cohabitation #192

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 19 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,27 @@ before_install:
- sudo apt-get install chromium-chromedriver

elixir:
- 1.6.6
- 1.7.4
- 1.7
- 1.8

otp_release:
- 20.0
- 19.3
- 20.3
- 21.0
- 22.0.1

matrix:
exclude:
- elixir: 1.7
otp_release: 19.3
- elixir: 1.7
otp_release: 20.3
- elixir: 1.7
otp_release: 22.0.1
- elixir: 1.8
otp_release: 19.3
- elixir: 1.8
otp_release: 20.3

env:
- MIX_ENV=test
Expand Down
3 changes: 3 additions & 0 deletions assets/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion config/test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ use Mix.Config
# you can enable the server option below.
config :drab, DrabTestApp.Endpoint,
http: [port: 4001],
server: true
server: true,
live_view: [
signing_salt: "+iGXfLGYMPyowoZribxgrSyeaPz9D/v2"
]

# Print only warnings and errors during test
config :logger, level: :warn
Expand Down
131 changes: 75 additions & 56 deletions lib/drab/client.ex
Original file line number Diff line number Diff line change
Expand Up @@ -148,64 +148,83 @@ defmodule Drab.Client do
@spec api_version() :: String.t()
def api_version(), do: @client_lib_version

@spec get_controller_module(Plug.Conn.t()) :: atom() | nil
defp get_controller_module(conn) do
try do
Phoenix.Controller.controller_module(conn)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For both this and the one in get_controller_action_name is there no way to more safely check this without incurring an exception? Exceptions are pretty cheap when not thrown (although setting up the exception handler is not free in any case), but they are much less cheap when they are actually thrown, which would be very common in LiveView cases. If not this looks good as it is. :-)

Copy link
Contributor Author

@guidotripaldi guidotripaldi Aug 14, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like it either use exceptions in a library but I haven't found a better way, both Phoenix.Controller.controller_module/1 and Phoenix.Controller.action_name/1 raise if the Controller is unavailable.

Any suggestions for some alternatives of course are welcome.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, all it checks is conn.private[:phoenix_controller], similar for the other, which is technically internal and not exposed, although it's never been changed. I wonder if direct access might be warranted, thoughts?

Copy link
Contributor Author

@guidotripaldi guidotripaldi Aug 14, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In fact my first version was similar, it was a check against the presence of : live_view_module in the assigns ( if !conn.assigns[:live_view_module] do), but it was a solution too specific for LV, so searching for a a general solution I thought that is better to use the official API because, although unlikely, the parameters for a direct access could be changed tomorrow, and in a library maybe is preferable do not hack too much.

Copy link
Contributor Author

@guidotripaldi guidotripaldi Aug 14, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually I don't know how much heavy thrown exceptions are, it could be interesting to setup some benchmark so to be aware of the actual costs. In any case we could assume that we don't want exceptions management in Drab and use the conn.private[:phoenix_controller] hack, and switch to the API based solution if tomorrow things will change.

Copy link
Collaborator

@OvermindDL1 OvermindDL1 Aug 14, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, let's test this case:

╰─➤  mix bench map_lookup_or_throw                                                                                                1 ↵
Operating System: Linux"
CPU Information: AMD Phenom(tm) II X6 1090T Processor
Number of Available Cores: 6
Available memory: 15.67 GB
Elixir 1.8.1
Erlang 21.2.2

Benchmark suite executing with the following configuration:
warmup: 2 s
time: 2 s
memory time: 2 s
parallel: 1
inputs: large-10000-existing, large-9999-not-existing, medium-10-existing, medium-9-not-existing, small-1-not-existing, small-2-existing
Estimated total run time: 3 min


Benchmarking Access with input large-10000-existing...
Benchmarking Access with input large-9999-not-existing...
Benchmarking Access with input medium-10-existing...
Benchmarking Access with input medium-9-not-existing...
Benchmarking Access with input small-1-not-existing...
Benchmarking Access with input small-2-existing...
Benchmarking Map.fetch with input large-10000-existing...
Benchmarking Map.fetch with input large-9999-not-existing...
Benchmarking Map.fetch with input medium-10-existing...
Benchmarking Map.fetch with input medium-9-not-existing...
Benchmarking Map.fetch with input small-1-not-existing...
Benchmarking Map.fetch with input small-2-existing...
Benchmarking case with input large-10000-existing...
Benchmarking case with input large-9999-not-existing...
Benchmarking case with input medium-10-existing...
Benchmarking case with input medium-9-not-existing...
Benchmarking case with input small-1-not-existing...
Benchmarking case with input small-2-existing...
Benchmarking catch-Map.fetch! with input large-10000-existing...
Benchmarking catch-Map.fetch! with input large-9999-not-existing...
Benchmarking catch-Map.fetch! with input medium-10-existing...
Benchmarking catch-Map.fetch! with input medium-9-not-existing...
Benchmarking catch-Map.fetch! with input small-1-not-existing...
Benchmarking catch-Map.fetch! with input small-2-existing...
Benchmarking catch-direct-always-fail with input large-10000-existing...
Benchmarking catch-direct-always-fail with input large-9999-not-existing...
Benchmarking catch-direct-always-fail with input medium-10-existing...
Benchmarking catch-direct-always-fail with input medium-9-not-existing...
Benchmarking catch-direct-always-fail with input small-1-not-existing...
Benchmarking catch-direct-always-fail with input small-2-existing...

##### With input large-10000-existing #####
Name                               ips        average  deviation         median         99th %
case                           11.18 M      0.0895 μs     ±6.43%      0.0880 μs       0.106 μs
catch-Map.fetch!                9.60 M       0.104 μs   ±202.32%       0.100 μs       0.150 μs
Map.fetch                       9.54 M       0.105 μs   ±211.47%       0.100 μs        0.22 μs
Access                          7.39 M       0.135 μs    ±17.79%       0.130 μs        0.20 μs
catch-direct-always-fail        5.90 M       0.169 μs    ±56.58%       0.160 μs        0.25 μs

Comparison: 
case                           11.18 M
catch-Map.fetch!                9.60 M - 1.16x slower
Map.fetch                       9.54 M - 1.17x slower
Access                          7.39 M - 1.51x slower
catch-direct-always-fail        5.90 M - 1.89x slower

Memory usage statistics:

Name                        Memory usage
case                           529.25 KB
catch-Map.fetch!               529.25 KB - 1.00x memory usage
Map.fetch                      529.27 KB - 1.00x memory usage
Access                         529.25 KB - 1.00x memory usage
catch-direct-always-fail       529.28 KB - 1.00x memory usage

**All measurements for memory usage were the same**

##### With input large-9999-not-existing #####
Name                               ips        average  deviation         median         99th %
case                           13.22 M      0.0756 μs    ±15.54%      0.0700 μs       0.120 μs
Map.fetch                      10.46 M      0.0956 μs    ±16.55%      0.0900 μs       0.140 μs
Access                          8.05 M       0.124 μs    ±17.15%       0.120 μs       0.180 μs
catch-Map.fetch!                5.75 M       0.174 μs   ±228.92%       0.160 μs        0.27 μs
catch-direct-always-fail        5.69 M       0.176 μs   ±276.39%       0.160 μs        0.37 μs

Comparison: 
case                           13.22 M
Map.fetch                      10.46 M - 1.26x slower
Access                          8.05 M - 1.64x slower
catch-Map.fetch!                5.75 M - 2.30x slower
catch-direct-always-fail        5.69 M - 2.32x slower

Memory usage statistics:

Name                        Memory usage
case                           529.20 KB
Map.fetch                      529.20 KB - 1.00x memory usage
Access                         529.20 KB - 1.00x memory usage
catch-Map.fetch!                0.180 KB - 0.00x memory usage
catch-direct-always-fail       529.23 KB - 1.00x memory usage

**All measurements for memory usage were the same**


##### With input medium-10-existing #####
Name                               ips        average  deviation         median         99th %
case                           16.57 M      0.0604 μs     ±6.70%      0.0590 μs      0.0733 μs
catch-Map.fetch!               11.85 M      0.0844 μs     ±6.72%      0.0820 μs       0.105 μs
Map.fetch                      11.00 M      0.0909 μs   ±434.54%      0.0800 μs        0.21 μs
Access                         10.08 M      0.0992 μs     ±7.51%      0.0960 μs       0.124 μs
catch-direct-always-fail        6.17 M       0.162 μs   ±232.69%       0.150 μs        0.32 μs

Comparison: 
case                           16.57 M
catch-Map.fetch!               11.85 M - 1.40x slower
Map.fetch                      11.00 M - 1.51x slower
Access                         10.08 M - 1.64x slower
catch-direct-always-fail        6.17 M - 2.69x slower

Memory usage statistics:

Name                        Memory usage
case                               592 B
catch-Map.fetch!                   592 B - 1.00x memory usage
Map.fetch                          616 B - 1.04x memory usage
Access                             592 B - 1.00x memory usage
catch-direct-always-fail           624 B - 1.05x memory usage

**All measurements for memory usage were the same**

##### With input medium-9-not-existing #####
Name                               ips        average  deviation         median         99th %
case                           18.67 M      0.0536 μs    ±19.03%      0.0500 μs      0.0800 μs
Map.fetch                      12.84 M      0.0779 μs     ±6.68%      0.0760 μs      0.0970 μs
Access                         10.50 M      0.0952 μs    ±27.39%      0.0900 μs       0.140 μs
catch-Map.fetch!                6.55 M       0.153 μs    ±77.30%       0.140 μs        0.25 μs
catch-direct-always-fail        6.27 M       0.159 μs   ±207.46%       0.150 μs        0.23 μs

Comparison: 
case                           18.67 M
Map.fetch                      12.84 M - 1.45x slower
Access                         10.50 M - 1.78x slower
catch-Map.fetch!                6.55 M - 2.85x slower
catch-direct-always-fail        6.27 M - 2.98x slower

Memory usage statistics:

Name                        Memory usage
case                               552 B
Map.fetch                          552 B - 1.00x memory usage
Access                             552 B - 1.00x memory usage
catch-Map.fetch!                   184 B - 0.33x memory usage
catch-direct-always-fail           584 B - 1.06x memory usage

**All measurements for memory usage were the same**

##### With input small-1-not-existing #####
Name                               ips        average  deviation         median         99th %
case                           16.93 M      0.0591 μs     ±8.03%      0.0590 μs      0.0830 μs
Map.fetch                      14.18 M      0.0705 μs    ±41.16%      0.0680 μs      0.0890 μs
Access                         11.45 M      0.0874 μs    ±26.97%      0.0800 μs       0.130 μs
catch-Map.fetch!                6.78 M       0.148 μs   ±182.52%       0.140 μs        0.26 μs
catch-direct-always-fail        6.20 M       0.161 μs   ±288.91%       0.150 μs        0.26 μs

Comparison: 
case                           16.93 M
Map.fetch                      14.18 M - 1.19x slower
Access                         11.45 M - 1.48x slower
catch-Map.fetch!                6.78 M - 2.50x slower
catch-direct-always-fail        6.20 M - 2.73x slower

Memory usage statistics:

Name                        Memory usage
case                               232 B
Map.fetch                          232 B - 1.00x memory usage
Access                             232 B - 1.00x memory usage
catch-Map.fetch!                   184 B - 0.79x memory usage
catch-direct-always-fail           264 B - 1.14x memory usage

**All measurements for memory usage were the same**

##### With input small-2-existing #####
Name                               ips        average  deviation         median         99th %
case                           17.26 M      0.0579 μs    ±48.24%      0.0580 μs      0.0810 μs
catch-Map.fetch!               13.85 M      0.0722 μs    ±55.45%      0.0700 μs       0.100 μs
Map.fetch                      13.08 M      0.0765 μs     ±9.96%      0.0720 μs       0.109 μs
Access                         11.07 M      0.0903 μs     ±8.15%      0.0890 μs       0.110 μs
catch-direct-always-fail        6.18 M       0.162 μs   ±220.42%       0.150 μs        0.35 μs

Comparison: 
case                           17.26 M
catch-Map.fetch!               13.85 M - 1.25x slower
Map.fetch                      13.08 M - 1.32x slower
Access                         11.07 M - 1.56x slower
catch-direct-always-fail        6.18 M - 2.79x slower

Memory usage statistics:

Name                        Memory usage
case                               272 B
catch-Map.fetch!                   272 B - 1.00x memory usage
Map.fetch                          296 B - 1.09x memory usage
Access                             272 B - 1.00x memory usage
catch-direct-always-fail           304 B - 1.12x memory usage

**All measurements for memory usage were the same**

So in summary, matching via a case extraction is always fastest. The catch-direct-always-fail will be the case where Phoenix's functions will lookup and fail (and it always fails for the same reason that phoenix hard-codes in its keys). The Access pattern is the some_map[some_key] lookup, it's not great either.

In short, a case matcher would be about triple the speed on average. I'm not sure that's really worth caring about then. I'm voting to accept it with the Phoenix calls as it is then. Agree?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the benchmark, interesting results.
I agree, differences are not substantial, and in case we can change our mind anytime

rescue
KeyError ->
nil
end
end

@spec get_controller_action_name(Plug.Conn.t()) :: atom() | nil
defp get_controller_action_name(conn) do
try do
Phoenix.Controller.action_name(conn)
rescue
KeyError -> nil
end
end

@spec generate_drab_js(Plug.Conn.t(), boolean, Keyword.t()) :: String.t()
defp generate_drab_js(conn, connect?, assigns) do
controller = Phoenix.Controller.controller_module(conn)

if enables_drab?(controller) do
commander = commander_for(controller)
view = view_for(controller)
endpoint = Phoenix.Controller.endpoint_module(conn)
action = Phoenix.Controller.action_name(conn)

controller_and_action =
Phoenix.Token.sign(
conn,
"controller_and_action",
controller: controller,
commander: commander,
view: view,
action: action,
assigns: assigns
)

broadcast_topic =
topic(commander.__drab__().broadcasting, controller, conn.request_path, action)

templates = DrabModule.all_templates_for(commander.__drab__().modules)

access_session =
Enum.uniq(
commander.__drab__().access_session ++ Drab.Config.get(endpoint, :access_session)
)

session =
access_session
|> Enum.map(fn x -> {x, Plug.Conn.get_session(conn, x)} end)
|> Enum.into(%{})

session_token = Drab.Core.tokenize_store(conn, session)

bindings = [
controller_and_action: controller_and_action,
endpoint: endpoint,
commander: commander,
templates: templates,
drab_session_token: session_token,
broadcast_topic: broadcast_topic,
connect: connect?,
client_lib_version: @client_lib_version
]

js = render_template(endpoint, "drab.js", bindings)

Phoenix.HTML.raw("""
<script>
#{js}
</script>
""")
else
""
if (controller = get_controller_module(conn)) do
if enables_drab?(controller) do
commander = commander_for(controller)
view = view_for(controller)
endpoint = Phoenix.Controller.endpoint_module(conn)
action = get_controller_action_name(conn)

controller_and_action =
Phoenix.Token.sign(
conn,
"controller_and_action",
controller: controller,
commander: commander,
view: view,
action: action,
assigns: assigns
)

broadcast_topic =
topic(commander.__drab__().broadcasting, controller, conn.request_path, action)

templates = DrabModule.all_templates_for(commander.__drab__().modules)

access_session =
Enum.uniq(
commander.__drab__().access_session ++ Drab.Config.get(endpoint, :access_session)
)

session =
access_session
|> Enum.map(fn x -> {x, Plug.Conn.get_session(conn, x)} end)
|> Enum.into(%{})

session_token = Drab.Core.tokenize_store(conn, session)

bindings = [
controller_and_action: controller_and_action,
endpoint: endpoint,
commander: commander,
templates: templates,
drab_session_token: session_token,
broadcast_topic: broadcast_topic,
connect: connect?,
client_lib_version: @client_lib_version
]

js = render_template(endpoint, "drab.js", bindings)

Phoenix.HTML.raw("""
<script>
#{js}
</script>
""")
else
""
end
end
end

Expand Down
6 changes: 4 additions & 2 deletions mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ defmodule Drab.Mixfile do

defp deps do
[
{:phoenix, "~> 1.2"},
{:phoenix, "~> 1.4.8"},
{:phoenix_html, "~> 2.13"},
{:phoenix_pubsub, "~> 1.0"},
{:phoenix_live_reload, "~> 1.0", only: :dev},
Expand All @@ -63,7 +63,9 @@ defmodule Drab.Mixfile do
{:floki, ">= 0.20.2"},
{:dialyxir, "~> 1.0.0-rc.2", only: [:dev, :test], runtime: false},
# {:credo, "~> 0.9.3", only: [:dev, :test], runtime: false},
{:jason, "~> 1.0"}
{:jason, "~> 1.0"},

{:phoenix_live_view, github: "phoenixframework/phoenix_live_view", only: [:test]}
]
end

Expand Down
18 changes: 10 additions & 8 deletions mix.lock
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
%{
"bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm"},
"certifi": {:hex, :certifi, "2.4.2", "75424ff0f3baaccfd34b1214184b6ef616d89e420b258bb0a5ea7d7bc628f7f0", [:rebar3], [{:parse_trans, "~>3.3", [hex: :parse_trans, repo: "hexpm", optional: false]}], "hexpm"},
"cowboy": {:hex, :cowboy, "1.1.2", "61ac29ea970389a88eca5a65601460162d370a70018afe6f949a29dca91f3bb0", [:rebar3], [{:cowlib, "~> 1.0.2", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "~> 1.3.2", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm"},
"cowlib": {:hex, :cowlib, "1.0.2", "9d769a1d062c9c3ac753096f868ca121e2730b9a377de23dec0f7e08b1df84ee", [:make], [], "hexpm"},
"cowboy": {:hex, :cowboy, "2.6.3", "99aa50e94e685557cad82e704457336a453d4abcb77839ad22dbe71f311fcc06", [:rebar3], [{:cowlib, "~> 2.7.3", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "~> 1.7.1", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm"},
"cowlib": {:hex, :cowlib, "2.7.3", "a7ffcd0917e6d50b4d5fb28e9e2085a0ceb3c97dea310505f7460ff5ed764ce9", [:rebar3], [], "hexpm"},
"credo": {:hex, :credo, "0.9.3", "76fa3e9e497ab282e0cf64b98a624aa11da702854c52c82db1bf24e54ab7c97a", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:poison, ">= 0.0.0", [hex: :poison, repo: "hexpm", optional: false]}], "hexpm"},
"deppie": {:hex, :deppie, "1.1.2", "6e90b0baf70055ee85b5d87c1649f39acb05df3c24d4d46f90a4a03b8e57619f", [:mix], [{:global_flags, "~> 1.0", [hex: :global_flags, repo: "hexpm", optional: false]}], "hexpm"},
"dialyxir": {:hex, :dialyxir, "1.0.0-rc.4", "71b42f5ee1b7628f3e3a6565f4617dfb02d127a0499ab3e72750455e986df001", [:mix], [{:erlex, "~> 0.1", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm"},
Expand All @@ -27,15 +27,17 @@
"mochiweb": {:hex, :mochiweb, "2.18.0", "eb55f1db3e6e960fac4e6db4e2db9ec3602cc9f30b86cd1481d56545c3145d2e", [:rebar3], [], "hexpm"},
"nimble_parsec": {:hex, :nimble_parsec, "0.4.0", "ee261bb53214943679422be70f1658fff573c5d0b0a1ecd0f18738944f818efe", [:mix], [], "hexpm"},
"parse_trans": {:hex, :parse_trans, "3.3.0", "09765507a3c7590a784615cfd421d101aec25098d50b89d7aa1d66646bc571c1", [:rebar3], [], "hexpm"},
"phoenix": {:hex, :phoenix, "1.4.0", "56fe9a809e0e735f3e3b9b31c1b749d4b436e466d8da627b8d82f90eaae714d2", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 1.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 1.0 or ~> 2.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}], "hexpm"},
"phoenix_html": {:hex, :phoenix_html, "2.13.1", "fa8f034b5328e2dfa0e4131b5569379003f34bc1fafdaa84985b0b9d2f12e68b", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
"phoenix": {:hex, :phoenix, "1.4.9", "746d098e10741c334d88143d3c94cab1756435f94387a63441792e66ec0ee974", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 1.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:plug, "~> 1.8.1 or ~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 1.0 or ~> 2.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm"},
"phoenix_html": {:hex, :phoenix_html, "2.13.3", "850e292ff6e204257f5f9c4c54a8cb1f6fbc16ed53d360c2b780a3d0ba333867", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
"phoenix_live_reload": {:hex, :phoenix_live_reload, "1.2.0", "3bb31a9fbd40ffe8652e60c8660dffd72dd231efcdf49b744fb75b9ef7db5dd2", [:mix], [{:file_system, "~> 0.2.1 or ~> 0.3", [hex: :file_system, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.4", [hex: :phoenix, repo: "hexpm", optional: false]}], "hexpm"},
"phoenix_pubsub": {:hex, :phoenix_pubsub, "1.1.1", "6668d787e602981f24f17a5fbb69cc98f8ab085114ebfac6cc36e10a90c8e93c", [:mix], [], "hexpm"},
"plug": {:hex, :plug, "1.7.1", "8516d565fb84a6a8b2ca722e74e2cd25ca0fc9d64f364ec9dbec09d33eb78ccd", [:mix], [{:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}], "hexpm"},
"plug_cowboy": {:hex, :plug_cowboy, "1.0.0", "2e2a7d3409746d335f451218b8bb0858301c3de6d668c3052716c909936eb57a", [:mix], [{:cowboy, "~> 1.0", [hex: :cowboy, repo: "hexpm", optional: false]}, {:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
"phoenix_live_view": {:git, "https://github.com/phoenixframework/phoenix_live_view.git", "0de12cc2666105d2e82d11c008043bc450197179", []},
"phoenix_pubsub": {:hex, :phoenix_pubsub, "1.1.2", "496c303bdf1b2e98a9d26e89af5bba3ab487ba3a3735f74bf1f4064d2a845a3e", [:mix], [], "hexpm"},
"plug": {:hex, :plug, "1.8.3", "12d5f9796dc72e8ac9614e94bda5e51c4c028d0d428e9297650d09e15a684478", [:mix], [{:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm"},
"plug_cowboy": {:hex, :plug_cowboy, "2.1.0", "b75768153c3a8a9e8039d4b25bb9b14efbc58e9c4a6e6a270abff1cd30cbe320", [:mix], [{:cowboy, "~> 2.5", [hex: :cowboy, repo: "hexpm", optional: false]}, {:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
"plug_crypto": {:hex, :plug_crypto, "1.0.0", "18e49317d3fa343f24620ed22795ec29d4a5e602d52d1513ccea0b07d8ea7d4d", [:mix], [], "hexpm"},
"poison": {:hex, :poison, "3.1.0", "d9eb636610e096f86f25d9a46f35a9facac35609a7591b3be3326e99a0484665", [:mix], [], "hexpm"},
"ranch": {:hex, :ranch, "1.3.2", "e4965a144dc9fbe70e5c077c65e73c57165416a901bd02ea899cfd95aa890986", [:rebar3], [], "hexpm"},
"ranch": {:hex, :ranch, "1.7.1", "6b1fab51b49196860b733a49c07604465a47bdb78aa10c1c16a3d199f7f8c881", [:rebar3], [], "hexpm"},
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.4", "f0eafff810d2041e93f915ef59899c923f4568f4585904d010387ed74988e77b", [:make, :mix, :rebar3], [], "hexpm"},
"telemetry": {:hex, :telemetry, "0.4.0", "8339bee3fa8b91cb84d14c2935f8ecf399ccd87301ad6da6b71c09553834b2ab", [:rebar3], [], "hexpm"},
"unicode_util_compat": {:hex, :unicode_util_compat, "0.4.1", "d869e4c68901dd9531385bb0c8c40444ebf624e60b6962d95952775cac5e90cd", [:rebar3], [], "hexpm"},
}
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"dependencies": {
"phoenix": "file:deps/phoenix",
"phoenix_html": "file:deps/phoenix_html",
"phoenix_live_view": "file:deps/phoenix_live_view",
"jquery": ">= 3.1.1",
"bootstrap": "~3.3.7"
},
Expand Down
73 changes: 73 additions & 0 deletions test/integration/lv_cohabitation_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
defmodule DrabTestApp.LVCohabitationTest do
import Drab.Live
use DrabTestApp.IntegrationCase

# setup do
# index_drab() |> navigate_to()
# # wait for the Drab to initialize
# find_element(:id, "page_loaded_indicator")
# [socket: drab_socket()]
# end


describe "LV Cohabitation" do

# Check Drab page updated by COmmander
test "A Drab page should mutate assigns" do
navigate_to_drab_page()
socket = drab_socket()

# mutate assign
assert poke(socket, status: "initialised") == {:ok, 1}

# Process.sleep(500)

# check mutation
assert peek(socket, :status) == {:ok, "initialised"}
end

# Check LV page rendered by Controller
test "A LV page rendered trough a Controller should be available" do
navigate_to_lv_page()
assert true
end

# Check LV page direct render
test "A direct rendered LV page should be available" do
navigate_to_live_page()
assert true
end
end

# Helpers

defp navigate_to_drab_page() do
DrabTestApp.Endpoint
|> cohabitation_url(:index_drab, id: 42)
|> navigate_to()

# # Drab onload is async, so wait a little bitncfor its completionxw
# Process.sleep(500)

find_element(:id, "page_loaded_indicator")
find_element(:id, "muted_assign_indicator_42")
end

defp navigate_to_lv_page() do
DrabTestApp.Endpoint
|> cohabitation_url(:index_lv, id: 42)
|> navigate_to()

find_element(:id, "page_loaded_indicator")
find_element(:id, "muted_assign_indicator_42")
end

defp navigate_to_live_page() do
DrabTestApp.Endpoint
|> cohabitation_live_url(DrabTestApp.LVCohabitationLive, id: 42)
|> navigate_to()

find_element(:id, "muted_assign_indicator_42")
end

end
3 changes: 2 additions & 1 deletion test/support/lib/drab_test_app/endpoint.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ defmodule DrabTestApp.Endpoint do
@moduledoc false

use Phoenix.Endpoint, otp_app: :drab


socket "/live", Phoenix.LiveView.Socket
socket("/socket", DrabTestApp.UserSocket)

# Serve at "/" the static files from "priv/static" directory.
Expand Down
5 changes: 5 additions & 0 deletions test/support/router.ex
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ defmodule DrabTestApp.Router do
plug(:accepts, ["html"])
plug(:fetch_session)
plug(:fetch_flash)
plug Phoenix.LiveView.Flash
plug(:protect_from_forgery)
plug(:put_secure_browser_headers)
end
Expand Down Expand Up @@ -49,6 +50,10 @@ defmodule DrabTestApp.Router do
get("/tests/live/broadcasting", LiveController, :broadcasting, as: :broadcasting)

get("/tests/element", ElementController, :index, as: :element)

get("/tests/cohabitation_drab", LVCohabitationController, :index_drab, as: :cohabitation)
get("/tests/cohabitation_lv", LVCohabitationController, :index_lv, as: :cohabitation)
live("/tests/cohabitation_live", LVCohabitationLive, as: :cohabitation_live)
end

# Other scopes may use custom stacks.
Expand Down
13 changes: 13 additions & 0 deletions test/support/web/commanders/lv_cohabitation_commander.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
defmodule DrabTestApp.LVCohabitationCommander do
@moduledoc false

use Drab.Commander

onload(:page_loaded)

def page_loaded(socket) do
DrabTestApp.IntegrationCase.add_page_loaded_indicator(socket)
DrabTestApp.IntegrationCase.add_pid(socket)
end

end
14 changes: 14 additions & 0 deletions test/support/web/controllers/lv_cohabitation_controller.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
defmodule DrabTestApp.LVCohabitationController do
@moduledoc false

use DrabTestApp.Web, :controller
require Logger

def index_drab(conn, params) do
render(conn, "index_drab.html", status: "unititialised", id: params["id"])
end

def index_lv(conn, params) do
live_render(conn, DrabTestApp.LVCohabitationLive , session: %{status: "unititialised", id: params["id"]})
end
end
Loading