Skip to content

Commit d69b5da

Browse files
authored
feature: add test sandbox mode (#73)
Fixes #31
1 parent d6ecaab commit d69b5da

File tree

88 files changed

+7101
-84
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

88 files changed

+7101
-84
lines changed

.github/workflows/elixir_tests.yml

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,14 @@ jobs:
2424
image: "postgres:17-alpine"
2525
env:
2626
POSTGRES_PASSWORD: password
27-
POSTGRES_DB: electric
27+
POSTGRES_DB: phoenix_sync
2828
options: >-
2929
--health-cmd pg_isready
3030
--health-interval 10s
3131
--health-timeout 5s
3232
--health-retries 5
3333
ports:
34-
- 54321:5432
34+
- 55555:5432
3535

3636
steps:
3737
- uses: actions/checkout@v4
@@ -60,7 +60,7 @@ jobs:
6060
with:
6161
path: |
6262
_build/*/lib
63-
!_build/*/lib/electric_phoenix
63+
!_build/*/lib/phoenix_sync
6464
key: ${{ runner.os }}-build-${{ env.MIX_ENV }}-[${{ github.ref_name }}]-${{ github.sha }}
6565
restore-keys: |
6666
${{ runner.os }}-build-${{ env.MIX_ENV }}-[${{ github.ref_name }}]-${{ github.sha }}
@@ -77,9 +77,6 @@ jobs:
7777
- name: Run tests
7878
run: mix test --trace
7979

80-
- name: Test installation as a dependency
81-
run: mix test.as_a_dep
82-
8380
test-as-dep:
8481
name: Test installation as a dependency
8582
runs-on: ubuntu-latest
@@ -99,6 +96,38 @@ jobs:
9996
- name: Test installation as a dependency
10097
run: mix test.as_a_dep
10198

99+
test-apps:
100+
name: Test integration apps
101+
runs-on: ubuntu-latest
102+
env:
103+
MIX_ENV: test
104+
services:
105+
postgres:
106+
image: "postgres:17-alpine"
107+
env:
108+
POSTGRES_PASSWORD: password
109+
POSTGRES_DB: phoenix_sync
110+
options: >-
111+
--health-cmd pg_isready
112+
--health-interval 10s
113+
--health-timeout 5s
114+
--health-retries 5
115+
ports:
116+
- 55555:5432
117+
steps:
118+
- uses: actions/checkout@v4
119+
120+
- uses: erlef/setup-beam@v1
121+
with:
122+
version-type: strict
123+
version-file: ".tool-versions"
124+
125+
- name: Install dependencies
126+
run: mix deps.get
127+
128+
- name: Run tests on apps
129+
run: mix test.apps
130+
102131
formatting:
103132
name: mix format --check-formatted
104133
runs-on: ubuntu-latest

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,10 @@ children = [
349349
]
350350
```
351351

352+
## Testing
353+
354+
See `Phoenix.Sync.Sandbox` for details on how to test sync endpoints (liveview, controllers and routers) in your Phoenix/Ecto application.
355+
352356
## Notes
353357

354358
### ElectricSQL
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[
2+
import_deps: [:ecto, :ecto_sql, :phoenix],
3+
subdirectories: ["priv/*/migrations"],
4+
plugins: [Phoenix.LiveView.HTMLFormatter],
5+
inputs: ["*.{heex,ex,exs}", "{config,lib,test}/**/*.{heex,ex,exs}", "priv/*/seeds.exs"]
6+
]
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# The directory Mix will write compiled artifacts to.
2+
_build/
3+
4+
# If you run "mix test --cover", coverage assets end up here.
5+
cover/
6+
7+
# The directory Mix downloads your dependencies sources to.
8+
deps/
9+
10+
# Where 3rd-party dependencies like ExDoc output generated docs.
11+
doc/
12+
13+
# Ignore .fetch files in case you like to edit your project deps locally.
14+
.fetch
15+
16+
# If the VM crashes, it generates a dump, let's ignore it too.
17+
erl_crash.dump
18+
19+
# Also ignore archive artifacts (built via "mix archive.build").
20+
*.ez
21+
22+
# Temporary files, for example, from tests.
23+
tmp/
24+
25+
# Ignore package tarball (built via "mix hex.build").
26+
phoenix_sync_example-*.tar
27+
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
A small Phoenix app for testing behavior of the Phoenix Sync libraryy in-situ.
2+
3+
**Not an official example** -- see the [examples folder for those](../../examples).
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# This file is responsible for configuring your application
2+
# and its dependencies with the aid of the Config module.
3+
#
4+
# This configuration file is loaded before any dependency and
5+
# is restricted to this project.
6+
7+
# General application configuration
8+
import Config
9+
10+
config :phoenix_sync_example,
11+
ecto_repos: [PhoenixSyncExample.Repo],
12+
generators: [timestamp_type: :utc_datetime, binary_id: true]
13+
14+
# Configures the endpoint
15+
config :phoenix_sync_example, PhoenixSyncExampleWeb.Endpoint,
16+
url: [host: "localhost"],
17+
adapter: Bandit.PhoenixAdapter,
18+
render_errors: [
19+
formats: [html: PhoenixSyncExampleWeb.ErrorHTML, json: PhoenixSyncExampleWeb.ErrorJSON],
20+
layout: false
21+
],
22+
pubsub_server: PhoenixSyncExample.PubSub,
23+
live_view: [signing_salt: "tLgDbjrX"]
24+
25+
# Configures Elixir's Logger
26+
config :logger, :console,
27+
format: "$time $metadata[$level] $message\n",
28+
metadata: [:request_id]
29+
30+
# Use Jason for JSON parsing in Phoenix
31+
config :phoenix, :json_library, Jason
32+
33+
# Import environment specific config. This must remain at the bottom
34+
# of this file so it overrides the configuration defined above.
35+
import_config "#{config_env()}.exs"
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
import Config
2+
3+
# Configure your database
4+
config :phoenix_sync_example, PhoenixSyncExample.Repo,
5+
username: "postgres",
6+
password: "password",
7+
hostname: "localhost",
8+
database: "phoenix_sync_example_dev",
9+
port: 55555,
10+
stacktrace: true,
11+
show_sensitive_data_on_connection_error: true,
12+
pool_size: 10
13+
14+
# For development, we disable any cache and enable
15+
# debugging and code reloading.
16+
#
17+
# The watchers configuration can be used to run external
18+
# watchers to your application. For example, we can use it
19+
# to bundle .js and .css sources.
20+
# Binding to loopback ipv4 address prevents access from other machines.
21+
config :phoenix_sync_example, PhoenixSyncExampleWeb.Endpoint,
22+
# Change to `ip: {0, 0, 0, 0}` to allow access from other machines.
23+
http: [ip: {127, 0, 0, 1}, port: 4000],
24+
check_origin: false,
25+
code_reloader: true,
26+
debug_errors: true,
27+
secret_key_base: "uBmq7NHSNLSxZJ+aqrrggr+2tIiPQh39Xe5c0G13UPk5HWbDF6e7A2EN0BlGL/qd",
28+
watchers: []
29+
30+
# ## SSL Support
31+
#
32+
# In order to use HTTPS in development, a self-signed
33+
# certificate can be generated by running the following
34+
# Mix task:
35+
#
36+
# mix phx.gen.cert
37+
#
38+
# Run `mix help phx.gen.cert` for more information.
39+
#
40+
# The `http:` config above can be replaced with:
41+
#
42+
# https: [
43+
# port: 4001,
44+
# cipher_suite: :strong,
45+
# keyfile: "priv/cert/selfsigned_key.pem",
46+
# certfile: "priv/cert/selfsigned.pem"
47+
# ],
48+
#
49+
# If desired, both `http:` and `https:` keys can be
50+
# configured to run both http and https servers on
51+
# different ports.
52+
53+
# Watch static and templates for browser reloading.
54+
config :phoenix_sync_example, PhoenixSyncExampleWeb.Endpoint,
55+
live_reload: [
56+
patterns: [
57+
~r"priv/static/(?!uploads/).*(js|css|png|jpeg|jpg|gif|svg)$",
58+
~r"lib/phoenix_sync_example_web/(controllers|live|components)/.*(ex|heex)$"
59+
]
60+
]
61+
62+
# Enable dev routes for dashboard and mailbox
63+
config :phoenix_sync_example, dev_routes: true
64+
65+
# Do not include metadata nor timestamps in development logs
66+
config :logger, :console, format: "[$level] $message\n"
67+
68+
# Set a higher stacktrace during development. Avoid configuring such
69+
# in production as building large stacktraces may be expensive.
70+
config :phoenix, :stacktrace_depth, 20
71+
72+
# Initialize plugs at runtime for faster development compilation
73+
config :phoenix, :plug_init_mode, :runtime
74+
75+
config :phoenix_live_view,
76+
# Include HEEx debug annotations as HTML comments in rendered markup
77+
debug_heex_annotations: true,
78+
# Enable helpful, but potentially expensive runtime checks
79+
enable_expensive_runtime_checks: true
80+
81+
config :phoenix_sync,
82+
env: config_env(),
83+
repo: PhoenixSyncExample.Repo,
84+
mode: :embedded
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import Config
2+
3+
# Do not print debug messages in production
4+
config :logger, level: :info
5+
6+
# Runtime production configuration, including reading
7+
# of environment variables, is done on config/runtime.exs.
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
import Config
2+
3+
# config/runtime.exs is executed for all environments, including
4+
# during releases. It is executed after compilation and before the
5+
# system starts, so it is typically used to load production configuration
6+
# and secrets from environment variables or elsewhere. Do not define
7+
# any compile-time configuration in here, as it won't be applied.
8+
# The block below contains prod specific runtime configuration.
9+
10+
# ## Using releases
11+
#
12+
# If you use `mix release`, you need to explicitly enable the server
13+
# by passing the PHX_SERVER=true when you start it:
14+
#
15+
# PHX_SERVER=true bin/phoenix_sync_example start
16+
#
17+
# Alternatively, you can use `mix phx.gen.release` to generate a `bin/server`
18+
# script that automatically sets the env var above.
19+
if System.get_env("PHX_SERVER") do
20+
config :phoenix_sync_example, PhoenixSyncExampleWeb.Endpoint, server: true
21+
end
22+
23+
if config_env() == :prod do
24+
database_url =
25+
System.get_env("DATABASE_URL") ||
26+
raise """
27+
environment variable DATABASE_URL is missing.
28+
For example: ecto://USER:PASS@HOST/DATABASE
29+
"""
30+
31+
maybe_ipv6 = if System.get_env("ECTO_IPV6") in ~w(true 1), do: [:inet6], else: []
32+
33+
config :phoenix_sync_example, PhoenixSyncExample.Repo,
34+
# ssl: true,
35+
url: database_url,
36+
pool_size: String.to_integer(System.get_env("POOL_SIZE") || "10"),
37+
socket_options: maybe_ipv6
38+
39+
# The secret key base is used to sign/encrypt cookies and other secrets.
40+
# A default value is used in config/dev.exs and config/test.exs but you
41+
# want to use a different value for prod and you most likely don't want
42+
# to check this value into version control, so we use an environment
43+
# variable instead.
44+
secret_key_base =
45+
System.get_env("SECRET_KEY_BASE") ||
46+
raise """
47+
environment variable SECRET_KEY_BASE is missing.
48+
You can generate one by calling: mix phx.gen.secret
49+
"""
50+
51+
host = System.get_env("PHX_HOST") || "example.com"
52+
port = String.to_integer(System.get_env("PORT") || "4000")
53+
54+
config :phoenix_sync_example, :dns_cluster_query, System.get_env("DNS_CLUSTER_QUERY")
55+
56+
config :phoenix_sync_example, PhoenixSyncExampleWeb.Endpoint,
57+
url: [host: host, port: 443, scheme: "https"],
58+
http: [
59+
# Enable IPv6 and bind on all interfaces.
60+
# Set it to {0, 0, 0, 0, 0, 0, 0, 1} for local network only access.
61+
# See the documentation on https://hexdocs.pm/bandit/Bandit.html#t:options/0
62+
# for details about using IPv6 vs IPv4 and loopback vs public addresses.
63+
ip: {0, 0, 0, 0, 0, 0, 0, 0},
64+
port: port
65+
],
66+
secret_key_base: secret_key_base
67+
68+
# ## SSL Support
69+
#
70+
# To get SSL working, you will need to add the `https` key
71+
# to your endpoint configuration:
72+
#
73+
# config :phoenix_sync_example, PhoenixSyncExampleWeb.Endpoint,
74+
# https: [
75+
# ...,
76+
# port: 443,
77+
# cipher_suite: :strong,
78+
# keyfile: System.get_env("SOME_APP_SSL_KEY_PATH"),
79+
# certfile: System.get_env("SOME_APP_SSL_CERT_PATH")
80+
# ]
81+
#
82+
# The `cipher_suite` is set to `:strong` to support only the
83+
# latest and more secure SSL ciphers. This means old browsers
84+
# and clients may not be supported. You can set it to
85+
# `:compatible` for wider support.
86+
#
87+
# `:keyfile` and `:certfile` expect an absolute path to the key
88+
# and cert in disk or a relative path inside priv, for example
89+
# "priv/ssl/server.key". For all supported SSL configuration
90+
# options, see https://hexdocs.pm/plug/Plug.SSL.html#configure/1
91+
#
92+
# We also recommend setting `force_ssl` in your config/prod.exs,
93+
# ensuring no data is ever sent via http, always redirecting to https:
94+
#
95+
# config :phoenix_sync_example, PhoenixSyncExampleWeb.Endpoint,
96+
# force_ssl: [hsts: true]
97+
#
98+
# Check `Plug.SSL` for all available options in `force_ssl`.
99+
end
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import Config
2+
3+
# Configure your database
4+
#
5+
# The MIX_TEST_PARTITION environment variable can be used
6+
# to provide built-in test partitioning in CI environment.
7+
# Run `mix help test` for more information.
8+
config :phoenix_sync_example, PhoenixSyncExample.Repo,
9+
username: "postgres",
10+
password: "password",
11+
hostname: "localhost",
12+
database: "phoenix_sync_example_test#{System.get_env("MIX_TEST_PARTITION")}",
13+
port: 55555,
14+
pool: Ecto.Adapters.SQL.Sandbox,
15+
pool_size: System.schedulers_online() * 2
16+
17+
# We don't run a server during test. If one is required,
18+
# you can enable the server option below.
19+
config :phoenix_sync_example, PhoenixSyncExampleWeb.Endpoint,
20+
http: [ip: {127, 0, 0, 1}, port: 4002],
21+
secret_key_base: "JxgUv3Dd0aEmBGFLgfyPpQPTidmD3BaW9NYtWDCnk0Yo3EaPDQgUNyLOXkm3+//h",
22+
server: false
23+
24+
# Print only warnings and errors during test
25+
config :logger, level: :warning
26+
27+
# Initialize plugs at runtime for faster test compilation
28+
config :phoenix, :plug_init_mode, :runtime
29+
30+
# Enable helpful, but potentially expensive runtime checks
31+
config :phoenix_live_view,
32+
enable_expensive_runtime_checks: true
33+
34+
config :phoenix_sync,
35+
env: config_env(),
36+
mode: :sandbox

0 commit comments

Comments
 (0)