Skip to content
Merged
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
4 changes: 2 additions & 2 deletions installer/lib/phx_new/generator.ex

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Computed Outputs Across Conditional Permutations

Permutation: Full-stack project (Representative of all 16 flag permutations) (Output changed by commit)

Unified Output Diff
--- Before
+++ After
@@ -43,7 +43,6 @@
 - Ensure **clean typography, spacing, and layout balance** for a refined, premium look
 - Focus on **delightful details** like hover effects, loading states, and smooth page transitions
 
-
 <!-- usage-rules-start -->
 
 <!-- phoenix:elixir-start -->
@@ -446,4 +445,4 @@
 - **Never** use `<.form let={f} ...>` in the template, instead **always use `<.form for={@form} ...>`**, then drive all form references from the form assign as in `@form[:field]`. The UI should **always** be driven by a `to_form/2` assigned in the LiveView module that is derived from a changeset
 <!-- phoenix:liveview-end -->
 
-<!-- usage-rules-end -->
\ No newline at end of file
+<!-- usage-rules-end -->

Full Rendered Outputs (Before & After) omitted for brevity.

Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ defmodule Phx.New.Generator do
project.binding[:javascript] && project.binding[:css] &&
@new_project_rules_files["assets.md"],
# generic usage rules
"\n<!-- usage-rules-start -->",
"<!-- usage-rules-start -->",
[
"<!-- phoenix:elixir-start -->\n",
@rules_files["elixir.md"],
Expand Down Expand Up @@ -157,7 +157,7 @@ defmodule Phx.New.Generator do
@rules_files["liveview.md"],
"\n<!-- phoenix:liveview-end -->"
],
"<!-- usage-rules-end -->"
"<!-- usage-rules-end -->\n"
]
|> Enum.reject(fn part -> part == nil or part == false end)
|> Enum.intersperse("\n\n")
Expand Down
9 changes: 4 additions & 5 deletions installer/templates/phx_assets/app.js.eex

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Computed Outputs Across Conditional Permutations

Permutation: html: true, live: true (Output changed by commit)

Unified Output Diff
--- Before
+++ After
@@ -80,4 +80,3 @@
     window.liveReloader = reloader
   })
 }
-
Full Rendered Outputs (Before & After)
Before Commit
// If you want to use Phoenix channels, run `mix help phx.gen.channel`
// to get started and then uncomment the line below.
// import "./user_socket.js"

// You can include dependencies in two ways.
//
// The simplest option is to put them in assets/vendor and
// import them using relative paths:
//
//     import "../vendor/some-package.js"
//
// Alternatively, you can `npm install some-package --prefix assets` and import
// them using a path starting with the package name:
//
//     import "some-package"
//
// If you have dependencies that try to import CSS, esbuild will generate a separate `app.css` file.
// To load it, simply add a second `<link>` to your `root.html.heex` file.

// Include phoenix_html to handle method=PUT/DELETE in forms and buttons.
import "phoenix_html"
// Establish Phoenix Socket and LiveView configuration.
import {Socket} from "phoenix"
import {LiveSocket} from "phoenix_live_view"
import {hooks as colocatedHooks} from "phoenix-colocated/my_app_web"
import topbar from "../vendor/topbar"

const csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content")
const liveSocket = new LiveSocket("/live", Socket, {
  longPollFallbackMs: 2500,
  params: {_csrf_token: csrfToken},
  hooks: {...colocatedHooks},
})

// Show progress bar on live navigation and form submits
topbar.config({barColors: {0: "#29d"}, shadowColor: "rgba(0, 0, 0, .3)"})
window.addEventListener("phx:page-loading-start", _info => topbar.show(300))
window.addEventListener("phx:page-loading-stop", _info => topbar.hide())

// connect if there are any LiveViews on the page
liveSocket.connect()

// expose liveSocket on window for web console debug logs and latency simulation:
// >> liveSocket.enableDebug()
// >> liveSocket.enableLatencySim(1000)  // enabled for duration of browser session
// >> liveSocket.disableLatencySim()
window.liveSocket = liveSocket

// The lines below enable quality of life phoenix_live_reload
// development features:
//
//     1. stream server logs to the browser console
//     2. click on elements to jump to their definitions in your code editor
//
if (process.env.NODE_ENV === "development") {
  window.addEventListener("phx:live_reload:attached", ({detail: reloader}) => {
    // Enable server log streaming to client.
    // Disable with reloader.disableServerLogs()
    reloader.enableServerLogs()

    // Open configured PLUG_EDITOR at file:line of the clicked element's HEEx component
    //
    //   * click with "c" key pressed to open at caller location
    //   * click with "d" key pressed to open at function component definition location
    let keyDown
    window.addEventListener("keydown", e => keyDown = e.key)
    window.addEventListener("keyup", _e => keyDown = null)
    window.addEventListener("click", e => {
      if(keyDown === "c"){
        e.preventDefault()
        e.stopImmediatePropagation()
        reloader.openEditorAtCaller(e.target)
      } else if(keyDown === "d"){
        e.preventDefault()
        e.stopImmediatePropagation()
        reloader.openEditorAtDef(e.target)
      }
    }, true)

    window.liveReloader = reloader
  })
}
After Commit
// If you want to use Phoenix channels, run `mix help phx.gen.channel`
// to get started and then uncomment the line below.
// import "./user_socket.js"

// You can include dependencies in two ways.
//
// The simplest option is to put them in assets/vendor and
// import them using relative paths:
//
//     import "../vendor/some-package.js"
//
// Alternatively, you can `npm install some-package --prefix assets` and import
// them using a path starting with the package name:
//
//     import "some-package"
//
// If you have dependencies that try to import CSS, esbuild will generate a separate `app.css` file.
// To load it, simply add a second `<link>` to your `root.html.heex` file.

// Include phoenix_html to handle method=PUT/DELETE in forms and buttons.
import "phoenix_html"
// Establish Phoenix Socket and LiveView configuration.
import {Socket} from "phoenix"
import {LiveSocket} from "phoenix_live_view"
import {hooks as colocatedHooks} from "phoenix-colocated/my_app_web"
import topbar from "../vendor/topbar"

const csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content")
const liveSocket = new LiveSocket("/live", Socket, {
  longPollFallbackMs: 2500,
  params: {_csrf_token: csrfToken},
  hooks: {...colocatedHooks},
})

// Show progress bar on live navigation and form submits
topbar.config({barColors: {0: "#29d"}, shadowColor: "rgba(0, 0, 0, .3)"})
window.addEventListener("phx:page-loading-start", _info => topbar.show(300))
window.addEventListener("phx:page-loading-stop", _info => topbar.hide())

// connect if there are any LiveViews on the page
liveSocket.connect()

// expose liveSocket on window for web console debug logs and latency simulation:
// >> liveSocket.enableDebug()
// >> liveSocket.enableLatencySim(1000)  // enabled for duration of browser session
// >> liveSocket.disableLatencySim()
window.liveSocket = liveSocket

// The lines below enable quality of life phoenix_live_reload
// development features:
//
//     1. stream server logs to the browser console
//     2. click on elements to jump to their definitions in your code editor
//
if (process.env.NODE_ENV === "development") {
  window.addEventListener("phx:live_reload:attached", ({detail: reloader}) => {
    // Enable server log streaming to client.
    // Disable with reloader.disableServerLogs()
    reloader.enableServerLogs()

    // Open configured PLUG_EDITOR at file:line of the clicked element's HEEx component
    //
    //   * click with "c" key pressed to open at caller location
    //   * click with "d" key pressed to open at function component definition location
    let keyDown
    window.addEventListener("keydown", e => keyDown = e.key)
    window.addEventListener("keyup", _e => keyDown = null)
    window.addEventListener("click", e => {
      if(keyDown === "c"){
        e.preventDefault()
        e.stopImmediatePropagation()
        reloader.openEditorAtCaller(e.target)
      } else if(keyDown === "d"){
        e.preventDefault()
        e.stopImmediatePropagation()
        reloader.openEditorAtDef(e.target)
      }
    }, true)

    window.liveReloader = reloader
  })
}

Permutation: html: true, live: false (Output changed by commit)

Unified Output Diff
--- Before
+++ After
@@ -81,10 +81,9 @@
 //   })
 // }
 
-
 // Handle flash close
 document.querySelectorAll("[role=alert][data-flash]").forEach((el) => {
   el.addEventListener("click", () => {
     el.setAttribute("hidden", "")
   })
-})
\ No newline at end of file
+})
Full Rendered Outputs (Before & After)
Before Commit
// If you want to use Phoenix channels, run `mix help phx.gen.channel`
// to get started and then uncomment the line below.
// import "./user_socket.js"

// You can include dependencies in two ways.
//
// The simplest option is to put them in assets/vendor and
// import them using relative paths:
//
//     import "../vendor/some-package.js"
//
// Alternatively, you can `npm install some-package --prefix assets` and import
// them using a path starting with the package name:
//
//     import "some-package"
//
// If you have dependencies that try to import CSS, esbuild will generate a separate `app.css` file.
// To load it, simply add a second `<link>` to your `root.html.heex` file.

// Include phoenix_html to handle method=PUT/DELETE in forms and buttons.
import "phoenix_html"
// Establish Phoenix Socket and LiveView configuration.
// import {Socket} from "phoenix"
// import {LiveSocket} from "phoenix_live_view"
// import {hooks as colocatedHooks} from "phoenix-colocated/my_app_web"
// import topbar from "../vendor/topbar"

// const csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content")
// const liveSocket = new LiveSocket("/live", Socket, {
//   longPollFallbackMs: 2500,
//   params: {_csrf_token: csrfToken},
//   hooks: {...colocatedHooks},
// })

// Show progress bar on live navigation and form submits
// topbar.config({barColors: {0: "#29d"}, shadowColor: "rgba(0, 0, 0, .3)"})
// window.addEventListener("phx:page-loading-start", _info => topbar.show(300))
// window.addEventListener("phx:page-loading-stop", _info => topbar.hide())

// connect if there are any LiveViews on the page
// liveSocket.connect()

// expose liveSocket on window for web console debug logs and latency simulation:
// >> liveSocket.enableDebug()
// >> liveSocket.enableLatencySim(1000)  // enabled for duration of browser session
// >> liveSocket.disableLatencySim()
// window.liveSocket = liveSocket

// The lines below enable quality of life phoenix_live_reload
// development features:
//
//     1. stream server logs to the browser console
//     2. click on elements to jump to their definitions in your code editor
//
// if (process.env.NODE_ENV === "development") {
//   window.addEventListener("phx:live_reload:attached", ({detail: reloader}) => {
//     // Enable server log streaming to client.
//     // Disable with reloader.disableServerLogs()
//     reloader.enableServerLogs()
// 
//     // Open configured PLUG_EDITOR at file:line of the clicked element's HEEx component
//     //
//     //   * click with "c" key pressed to open at caller location
//     //   * click with "d" key pressed to open at function component definition location
//     let keyDown
//     window.addEventListener("keydown", e => keyDown = e.key)
//     window.addEventListener("keyup", _e => keyDown = null)
//     window.addEventListener("click", e => {
//       if(keyDown === "c"){
//         e.preventDefault()
//         e.stopImmediatePropagation()
//         reloader.openEditorAtCaller(e.target)
//       } else if(keyDown === "d"){
//         e.preventDefault()
//         e.stopImmediatePropagation()
//         reloader.openEditorAtDef(e.target)
//       }
//     }, true)
// 
//     window.liveReloader = reloader
//   })
// }


// Handle flash close
document.querySelectorAll("[role=alert][data-flash]").forEach((el) => {
  el.addEventListener("click", () => {
    el.setAttribute("hidden", "")
  })
})```

##### After Commit
```javascript
// If you want to use Phoenix channels, run `mix help phx.gen.channel`
// to get started and then uncomment the line below.
// import "./user_socket.js"

// You can include dependencies in two ways.
//
// The simplest option is to put them in assets/vendor and
// import them using relative paths:
//
//     import "../vendor/some-package.js"
//
// Alternatively, you can `npm install some-package --prefix assets` and import
// them using a path starting with the package name:
//
//     import "some-package"
//
// If you have dependencies that try to import CSS, esbuild will generate a separate `app.css` file.
// To load it, simply add a second `<link>` to your `root.html.heex` file.

// Include phoenix_html to handle method=PUT/DELETE in forms and buttons.
import "phoenix_html"
// Establish Phoenix Socket and LiveView configuration.
// import {Socket} from "phoenix"
// import {LiveSocket} from "phoenix_live_view"
// import {hooks as colocatedHooks} from "phoenix-colocated/my_app_web"
// import topbar from "../vendor/topbar"

// const csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content")
// const liveSocket = new LiveSocket("/live", Socket, {
//   longPollFallbackMs: 2500,
//   params: {_csrf_token: csrfToken},
//   hooks: {...colocatedHooks},
// })

// Show progress bar on live navigation and form submits
// topbar.config({barColors: {0: "#29d"}, shadowColor: "rgba(0, 0, 0, .3)"})
// window.addEventListener("phx:page-loading-start", _info => topbar.show(300))
// window.addEventListener("phx:page-loading-stop", _info => topbar.hide())

// connect if there are any LiveViews on the page
// liveSocket.connect()

// expose liveSocket on window for web console debug logs and latency simulation:
// >> liveSocket.enableDebug()
// >> liveSocket.enableLatencySim(1000)  // enabled for duration of browser session
// >> liveSocket.disableLatencySim()
// window.liveSocket = liveSocket

// The lines below enable quality of life phoenix_live_reload
// development features:
//
//     1. stream server logs to the browser console
//     2. click on elements to jump to their definitions in your code editor
//
// if (process.env.NODE_ENV === "development") {
//   window.addEventListener("phx:live_reload:attached", ({detail: reloader}) => {
//     // Enable server log streaming to client.
//     // Disable with reloader.disableServerLogs()
//     reloader.enableServerLogs()
// 
//     // Open configured PLUG_EDITOR at file:line of the clicked element's HEEx component
//     //
//     //   * click with "c" key pressed to open at caller location
//     //   * click with "d" key pressed to open at function component definition location
//     let keyDown
//     window.addEventListener("keydown", e => keyDown = e.key)
//     window.addEventListener("keyup", _e => keyDown = null)
//     window.addEventListener("click", e => {
//       if(keyDown === "c"){
//         e.preventDefault()
//         e.stopImmediatePropagation()
//         reloader.openEditorAtCaller(e.target)
//       } else if(keyDown === "d"){
//         e.preventDefault()
//         e.stopImmediatePropagation()
//         reloader.openEditorAtDef(e.target)
//       }
//     }, true)
// 
//     window.liveReloader = reloader
//   })
// }

// Handle flash close
document.querySelectorAll("[role=alert][data-flash]").forEach((el) => {
  el.addEventListener("click", () => {
    el.setAttribute("hidden", "")
  })
})

Permutation: html: false, live: true (Output unchanged)

Unified Output Diff
(No output changes)
Full Rendered Outputs (Before & After)
Before Commit
// If you want to use Phoenix channels, run `mix help phx.gen.channel`
// to get started and then uncomment the line below.
// import "./user_socket.js"

// You can include dependencies in two ways.
//
// The simplest option is to put them in assets/vendor and
// import them using relative paths:
//
//     import "../vendor/some-package.js"
//
// Alternatively, you can `npm install some-package --prefix assets` and import
// them using a path starting with the package name:
//
//     import "some-package"
//
// If you have dependencies that try to import CSS, esbuild will generate a separate `app.css` file.
// To load it, simply add a second `<link>` to your `root.html.heex` file.
After Commit
// If you want to use Phoenix channels, run `mix help phx.gen.channel`
// to get started and then uncomment the line below.
// import "./user_socket.js"

// You can include dependencies in two ways.
//
// The simplest option is to put them in assets/vendor and
// import them using relative paths:
//
//     import "../vendor/some-package.js"
//
// Alternatively, you can `npm install some-package --prefix assets` and import
// them using a path starting with the package name:
//
//     import "some-package"
//
// If you have dependencies that try to import CSS, esbuild will generate a separate `app.css` file.
// To load it, simply add a second `<link>` to your `root.html.heex` file.

Permutation: html: false, live: false (Output unchanged)

Unified Output Diff
(No output changes)
Full Rendered Outputs (Before & After)
Before Commit
// If you want to use Phoenix channels, run `mix help phx.gen.channel`
// to get started and then uncomment the line below.
// import "./user_socket.js"

// You can include dependencies in two ways.
//
// The simplest option is to put them in assets/vendor and
// import them using relative paths:
//
//     import "../vendor/some-package.js"
//
// Alternatively, you can `npm install some-package --prefix assets` and import
// them using a path starting with the package name:
//
//     import "some-package"
//
// If you have dependencies that try to import CSS, esbuild will generate a separate `app.css` file.
// To load it, simply add a second `<link>` to your `root.html.heex` file.
After Commit
// If you want to use Phoenix channels, run `mix help phx.gen.channel`
// to get started and then uncomment the line below.
// import "./user_socket.js"

// You can include dependencies in two ways.
//
// The simplest option is to put them in assets/vendor and
// import them using relative paths:
//
//     import "../vendor/some-package.js"
//
// Alternatively, you can `npm install some-package --prefix assets` and import
// them using a path starting with the package name:
//
//     import "some-package"
//
// If you have dependencies that try to import CSS, esbuild will generate a separate `app.css` file.
// To load it, simply add a second `<link>` to your `root.html.heex` file.

Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
// import "some-package"
//
// If you have dependencies that try to import CSS, esbuild will generate a separate `app.css` file.
// To load it, simply add a second `<link>` to your `root.html.heex` file.
<%= if @html do %>
// To load it, simply add a second `<link>` to your `root.html.heex` file.<%= if @html do %>

@SteffenDE SteffenDE Aug 3, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
// To load it, simply add a second `<link>` to your `root.html.heex` file.<%= if @html do %>
// To load it, simply add a second `<link>` to your `root.html.heex` file.<%= if @html do %>

I think this one is deliberate

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Thanks, good catch. The intention was to remove additional newlines at the end of file when html: false. The correct change that preserves the blank line separating the comment blocks is:

Suggested change
// To load it, simply add a second `<link>` to your `root.html.heex` file.<%= if @html do %>
// To load it, simply add a second `<link>` to your `root.html.heex` file.<%= if @html do %>

I.e., the if moves up, but the blank line remains. Verified across all four permutations of :html and :live.


// Include phoenix_html to handle method=PUT/DELETE in forms and buttons.
import "phoenix_html"
// Establish Phoenix Socket and LiveView configuration.
Expand Down Expand Up @@ -79,12 +79,11 @@ import "phoenix_html"
<%= @live_comment %>
<%= @live_comment %> window.liveReloader = reloader
<%= @live_comment %> })
<%= @live_comment %>}
<%= @live_comment %>}<%= if not @live do %>

<%= if not @live do %>
// Handle flash close
document.querySelectorAll("[role=alert][data-flash]").forEach((el) => {
el.addEventListener("click", () => {
el.setAttribute("hidden", "")
})
})<% end %><% end %>
})<% end %><% end %>
4 changes: 2 additions & 2 deletions installer/templates/phx_gettext/errors.pot.eex

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Computed Outputs Across Conditional Permutations

Permutation: ecto: true (Output unchanged)

Unified Output Diff
(No output changes)
Full Rendered Outputs (Before & After)
Before Commit
## This is a PO Template file.
##
## `msgid`s here are often extracted from source code.
## Add new translations manually only if they're dynamic
## translations that can't be statically extracted.
##
## Run `mix gettext.extract` to bring this file up to
## date. Leave `msgstr`s empty as changing them here has no
## effect: edit them in PO (`.po`) files instead.
## From Ecto.Changeset.cast/4
msgid "can't be blank"
msgstr ""

## From Ecto.Changeset.unique_constraint/3
msgid "has already been taken"
msgstr ""

## From Ecto.Changeset.put_change/3
msgid "is invalid"
msgstr ""

## From Ecto.Changeset.validate_acceptance/3
msgid "must be accepted"
msgstr ""

## From Ecto.Changeset.validate_format/3
msgid "has invalid format"
msgstr ""

## From Ecto.Changeset.validate_subset/3
msgid "has an invalid entry"
msgstr ""

## From Ecto.Changeset.validate_exclusion/3
msgid "is reserved"
msgstr ""

## From Ecto.Changeset.validate_confirmation/3
msgid "does not match confirmation"
msgstr ""

## From Ecto.Changeset.no_assoc_constraint/3
msgid "is still associated with this entry"
msgstr ""

msgid "are still associated with this entry"
msgstr ""

## From Ecto.Changeset.validate_length/3
msgid "should have %{count} item(s)"
msgid_plural "should have %{count} item(s)"
msgstr[0] ""
msgstr[1] ""

msgid "should be %{count} character(s)"
msgid_plural "should be %{count} character(s)"
msgstr[0] ""
msgstr[1] ""

msgid "should be %{count} byte(s)"
msgid_plural "should be %{count} byte(s)"
msgstr[0] ""
msgstr[1] ""

msgid "should have at least %{count} item(s)"
msgid_plural "should have at least %{count} item(s)"
msgstr[0] ""
msgstr[1] ""

msgid "should be at least %{count} character(s)"
msgid_plural "should be at least %{count} character(s)"
msgstr[0] ""
msgstr[1] ""

msgid "should be at least %{count} byte(s)"
msgid_plural "should be at least %{count} byte(s)"
msgstr[0] ""
msgstr[1] ""

msgid "should have at most %{count} item(s)"
msgid_plural "should have at most %{count} item(s)"
msgstr[0] ""
msgstr[1] ""

msgid "should be at most %{count} character(s)"
msgid_plural "should be at most %{count} character(s)"
msgstr[0] ""
msgstr[1] ""

msgid "should be at most %{count} byte(s)"
msgid_plural "should be at most %{count} byte(s)"
msgstr[0] ""
msgstr[1] ""

## From Ecto.Changeset.validate_number/3
msgid "must be less than %{number}"
msgstr ""

msgid "must be greater than %{number}"
msgstr ""

msgid "must be less than or equal to %{number}"
msgstr ""

msgid "must be greater than or equal to %{number}"
msgstr ""

msgid "must be equal to %{number}"
msgstr ""
After Commit
## This is a PO Template file.
##
## `msgid`s here are often extracted from source code.
## Add new translations manually only if they're dynamic
## translations that can't be statically extracted.
##
## Run `mix gettext.extract` to bring this file up to
## date. Leave `msgstr`s empty as changing them here has no
## effect: edit them in PO (`.po`) files instead.
## From Ecto.Changeset.cast/4
msgid "can't be blank"
msgstr ""

## From Ecto.Changeset.unique_constraint/3
msgid "has already been taken"
msgstr ""

## From Ecto.Changeset.put_change/3
msgid "is invalid"
msgstr ""

## From Ecto.Changeset.validate_acceptance/3
msgid "must be accepted"
msgstr ""

## From Ecto.Changeset.validate_format/3
msgid "has invalid format"
msgstr ""

## From Ecto.Changeset.validate_subset/3
msgid "has an invalid entry"
msgstr ""

## From Ecto.Changeset.validate_exclusion/3
msgid "is reserved"
msgstr ""

## From Ecto.Changeset.validate_confirmation/3
msgid "does not match confirmation"
msgstr ""

## From Ecto.Changeset.no_assoc_constraint/3
msgid "is still associated with this entry"
msgstr ""

msgid "are still associated with this entry"
msgstr ""

## From Ecto.Changeset.validate_length/3
msgid "should have %{count} item(s)"
msgid_plural "should have %{count} item(s)"
msgstr[0] ""
msgstr[1] ""

msgid "should be %{count} character(s)"
msgid_plural "should be %{count} character(s)"
msgstr[0] ""
msgstr[1] ""

msgid "should be %{count} byte(s)"
msgid_plural "should be %{count} byte(s)"
msgstr[0] ""
msgstr[1] ""

msgid "should have at least %{count} item(s)"
msgid_plural "should have at least %{count} item(s)"
msgstr[0] ""
msgstr[1] ""

msgid "should be at least %{count} character(s)"
msgid_plural "should be at least %{count} character(s)"
msgstr[0] ""
msgstr[1] ""

msgid "should be at least %{count} byte(s)"
msgid_plural "should be at least %{count} byte(s)"
msgstr[0] ""
msgstr[1] ""

msgid "should have at most %{count} item(s)"
msgid_plural "should have at most %{count} item(s)"
msgstr[0] ""
msgstr[1] ""

msgid "should be at most %{count} character(s)"
msgid_plural "should be at most %{count} character(s)"
msgstr[0] ""
msgstr[1] ""

msgid "should be at most %{count} byte(s)"
msgid_plural "should be at most %{count} byte(s)"
msgstr[0] ""
msgstr[1] ""

## From Ecto.Changeset.validate_number/3
msgid "must be less than %{number}"
msgstr ""

msgid "must be greater than %{number}"
msgstr ""

msgid "must be less than or equal to %{number}"
msgstr ""

msgid "must be greater than or equal to %{number}"
msgstr ""

msgid "must be equal to %{number}"
msgstr ""

Permutation: ecto: false (Output changed by commit)

Unified Output Diff
--- Before
+++ After
@@ -7,4 +7,3 @@
 ## Run `mix gettext.extract` to bring this file up to
 ## date. Leave `msgstr`s empty as changing them here has no
 ## effect: edit them in PO (`.po`) files instead.
-
Full Rendered Outputs (Before & After)
Before Commit
## This is a PO Template file.
##
## `msgid`s here are often extracted from source code.
## Add new translations manually only if they're dynamic
## translations that can't be statically extracted.
##
## Run `mix gettext.extract` to bring this file up to
## date. Leave `msgstr`s empty as changing them here has no
## effect: edit them in PO (`.po`) files instead.
After Commit
## This is a PO Template file.
##
## `msgid`s here are often extracted from source code.
## Add new translations manually only if they're dynamic
## translations that can't be statically extracted.
##
## Run `mix gettext.extract` to bring this file up to
## date. Leave `msgstr`s empty as changing them here has no
## effect: edit them in PO (`.po`) files instead.

Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
##
## Run `mix gettext.extract` to bring this file up to
## date. Leave `msgstr`s empty as changing them here has no
## effect: edit them in PO (`.po`) files instead.
<%= if @ecto do %>## From Ecto.Changeset.cast/4
## effect: edit them in PO (`.po`) files instead.<%= if @ecto do %>
## From Ecto.Changeset.cast/4
msgid "can't be blank"
msgstr ""

Expand Down
11 changes: 5 additions & 6 deletions installer/templates/phx_single/gitignore.eex

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Computed Outputs Across Conditional Permutations

Permutation: (javascript or css): true, sqlite3: true (Output changed by commit)

Unified Output Diff
--- Before
+++ After
@@ -38,4 +38,3 @@
 # Database files
 *.db
 *.db-*
-
Full Rendered Outputs (Before & After)
Before Commit
# The directory Mix will write compiled artifacts to.
/_build/

# If you run "mix test --cover", coverage assets end up here.
/cover/

# The directory Mix downloads your dependencies sources to.
/deps/

# Where 3rd-party dependencies like ExDoc output generated docs.
/doc/

# Ignore .fetch files in case you like to edit your project deps locally.
/.fetch

# If the VM crashes, it generates a dump, let's ignore it too.
erl_crash.dump

# Also ignore archive artifacts (built via "mix archive.build").
*.ez

# Temporary files, for example, from tests.
/tmp/

# Ignore package tarball (built via "mix hex.build").
my_app-*.tar

# Ignore assets that are produced by build tools.
/priv/static/assets/

# Ignore digested assets cache.
/priv/static/cache_manifest.json

# In case you use Node.js/npm, you want to ignore these.
npm-debug.log
/assets/node_modules/

# Database files
*.db
*.db-*

After Commit
# The directory Mix will write compiled artifacts to.
/_build/

# If you run "mix test --cover", coverage assets end up here.
/cover/

# The directory Mix downloads your dependencies sources to.
/deps/

# Where 3rd-party dependencies like ExDoc output generated docs.
/doc/

# Ignore .fetch files in case you like to edit your project deps locally.
/.fetch

# If the VM crashes, it generates a dump, let's ignore it too.
erl_crash.dump

# Also ignore archive artifacts (built via "mix archive.build").
*.ez

# Temporary files, for example, from tests.
/tmp/

# Ignore package tarball (built via "mix hex.build").
my_app-*.tar

# Ignore assets that are produced by build tools.
/priv/static/assets/

# Ignore digested assets cache.
/priv/static/cache_manifest.json

# In case you use Node.js/npm, you want to ignore these.
npm-debug.log
/assets/node_modules/

# Database files
*.db
*.db-*

Permutation: (javascript or css): true, sqlite3: false (Output changed by commit)

Unified Output Diff
--- Before
+++ After
@@ -34,4 +34,3 @@
 # In case you use Node.js/npm, you want to ignore these.
 npm-debug.log
 /assets/node_modules/
-
Full Rendered Outputs (Before & After)
Before Commit
# The directory Mix will write compiled artifacts to.
/_build/

# If you run "mix test --cover", coverage assets end up here.
/cover/

# The directory Mix downloads your dependencies sources to.
/deps/

# Where 3rd-party dependencies like ExDoc output generated docs.
/doc/

# Ignore .fetch files in case you like to edit your project deps locally.
/.fetch

# If the VM crashes, it generates a dump, let's ignore it too.
erl_crash.dump

# Also ignore archive artifacts (built via "mix archive.build").
*.ez

# Temporary files, for example, from tests.
/tmp/

# Ignore package tarball (built via "mix hex.build").
my_app-*.tar

# Ignore assets that are produced by build tools.
/priv/static/assets/

# Ignore digested assets cache.
/priv/static/cache_manifest.json

# In case you use Node.js/npm, you want to ignore these.
npm-debug.log
/assets/node_modules/

After Commit
# The directory Mix will write compiled artifacts to.
/_build/

# If you run "mix test --cover", coverage assets end up here.
/cover/

# The directory Mix downloads your dependencies sources to.
/deps/

# Where 3rd-party dependencies like ExDoc output generated docs.
/doc/

# Ignore .fetch files in case you like to edit your project deps locally.
/.fetch

# If the VM crashes, it generates a dump, let's ignore it too.
erl_crash.dump

# Also ignore archive artifacts (built via "mix archive.build").
*.ez

# Temporary files, for example, from tests.
/tmp/

# Ignore package tarball (built via "mix hex.build").
my_app-*.tar

# Ignore assets that are produced by build tools.
/priv/static/assets/

# Ignore digested assets cache.
/priv/static/cache_manifest.json

# In case you use Node.js/npm, you want to ignore these.
npm-debug.log
/assets/node_modules/

Permutation: (javascript or css): false, sqlite3: true (Output changed by commit)

Unified Output Diff
--- Before
+++ After
@@ -28,4 +28,3 @@
 # Database files
 *.db
 *.db-*
-
Full Rendered Outputs (Before & After)
Before Commit
# The directory Mix will write compiled artifacts to.
/_build/

# If you run "mix test --cover", coverage assets end up here.
/cover/

# The directory Mix downloads your dependencies sources to.
/deps/

# Where 3rd-party dependencies like ExDoc output generated docs.
/doc/

# Ignore .fetch files in case you like to edit your project deps locally.
/.fetch

# If the VM crashes, it generates a dump, let's ignore it too.
erl_crash.dump

# Also ignore archive artifacts (built via "mix archive.build").
*.ez

# Temporary files, for example, from tests.
/tmp/

# Ignore package tarball (built via "mix hex.build").
my_app-*.tar

# Database files
*.db
*.db-*

After Commit
# The directory Mix will write compiled artifacts to.
/_build/

# If you run "mix test --cover", coverage assets end up here.
/cover/

# The directory Mix downloads your dependencies sources to.
/deps/

# Where 3rd-party dependencies like ExDoc output generated docs.
/doc/

# Ignore .fetch files in case you like to edit your project deps locally.
/.fetch

# If the VM crashes, it generates a dump, let's ignore it too.
erl_crash.dump

# Also ignore archive artifacts (built via "mix archive.build").
*.ez

# Temporary files, for example, from tests.
/tmp/

# Ignore package tarball (built via "mix hex.build").
my_app-*.tar

# Database files
*.db
*.db-*

Permutation: (javascript or css): false, sqlite3: false (Output changed by commit)

Unified Output Diff
--- Before
+++ After
@@ -24,4 +24,3 @@
 
 # Ignore package tarball (built via "mix hex.build").
 my_app-*.tar
-
Full Rendered Outputs (Before & After)
Before Commit
# The directory Mix will write compiled artifacts to.
/_build/

# If you run "mix test --cover", coverage assets end up here.
/cover/

# The directory Mix downloads your dependencies sources to.
/deps/

# Where 3rd-party dependencies like ExDoc output generated docs.
/doc/

# Ignore .fetch files in case you like to edit your project deps locally.
/.fetch

# If the VM crashes, it generates a dump, let's ignore it too.
erl_crash.dump

# Also ignore archive artifacts (built via "mix archive.build").
*.ez

# Temporary files, for example, from tests.
/tmp/

# Ignore package tarball (built via "mix hex.build").
my_app-*.tar

After Commit
# The directory Mix will write compiled artifacts to.
/_build/

# If you run "mix test --cover", coverage assets end up here.
/cover/

# The directory Mix downloads your dependencies sources to.
/deps/

# Where 3rd-party dependencies like ExDoc output generated docs.
/doc/

# Ignore .fetch files in case you like to edit your project deps locally.
/.fetch

# If the VM crashes, it generates a dump, let's ignore it too.
erl_crash.dump

# Also ignore archive artifacts (built via "mix archive.build").
*.ez

# Temporary files, for example, from tests.
/tmp/

# Ignore package tarball (built via "mix hex.build").
my_app-*.tar

Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ erl_crash.dump
/tmp/

# Ignore package tarball (built via "mix hex.build").
<%= @app_name %>-*.tar
<%= if @javascript or @css do %>
<%= @app_name %>-*.tar<%= if @javascript or @css do %>

# Ignore assets that are produced by build tools.
/priv/static/assets/

Expand All @@ -33,9 +33,8 @@ erl_crash.dump

# In case you use Node.js/npm, you want to ignore these.
npm-debug.log
/assets/node_modules/
<% end %><%= if @adapter_app == :ecto_sqlite3 do %>
/assets/node_modules/<% end %><%= if @adapter_app == :ecto_sqlite3 do %>

# Database files
*.db
*.db-*
<% end %>
*.db-*<% end %>
1 change: 0 additions & 1 deletion installer/templates/phx_static/default.css
Original file line number Diff line number Diff line change
Expand Up @@ -2587,4 +2587,3 @@
transform: rotate(360deg);
}
}

11 changes: 5 additions & 6 deletions installer/templates/phx_umbrella/apps/app_name_web/gitignore.eex

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Computed Outputs Across Conditional Permutations

Permutation: (javascript or css): true, sqlite3: true (Output changed by commit)

Unified Output Diff
--- Before
+++ After
@@ -38,4 +38,3 @@
 # Database files
 *.db
 *.db-*
-
Full Rendered Outputs (Before & After)
Before Commit
# The directory Mix will write compiled artifacts to.
/_build/

# If you run "mix test --cover", coverage assets end up here.
/cover/

# The directory Mix downloads your dependencies sources to.
/deps/

# Where 3rd-party dependencies like ExDoc output generated docs.
/doc/

# Ignore .fetch files in case you like to edit your project deps locally.
/.fetch

# If the VM crashes, it generates a dump, let's ignore it too.
erl_crash.dump

# Also ignore archive artifacts (built via "mix archive.build").
*.ez

# Temporary files, for example, from tests.
/tmp/

# Ignore package tarball (built via "mix hex.build").
my_app_web-*.tar

# Ignore assets that are produced by build tools.
/priv/static/assets/

# Ignore digested assets cache.
/priv/static/cache_manifest.json

# In case you use Node.js/npm, you want to ignore these.
npm-debug.log
/assets/node_modules/

# Database files
*.db
*.db-*

After Commit
# The directory Mix will write compiled artifacts to.
/_build/

# If you run "mix test --cover", coverage assets end up here.
/cover/

# The directory Mix downloads your dependencies sources to.
/deps/

# Where 3rd-party dependencies like ExDoc output generated docs.
/doc/

# Ignore .fetch files in case you like to edit your project deps locally.
/.fetch

# If the VM crashes, it generates a dump, let's ignore it too.
erl_crash.dump

# Also ignore archive artifacts (built via "mix archive.build").
*.ez

# Temporary files, for example, from tests.
/tmp/

# Ignore package tarball (built via "mix hex.build").
my_app_web-*.tar

# Ignore assets that are produced by build tools.
/priv/static/assets/

# Ignore digested assets cache.
/priv/static/cache_manifest.json

# In case you use Node.js/npm, you want to ignore these.
npm-debug.log
/assets/node_modules/

# Database files
*.db
*.db-*

Permutation: (javascript or css): true, sqlite3: false (Output changed by commit)

Unified Output Diff
--- Before
+++ After
@@ -34,4 +34,3 @@
 # In case you use Node.js/npm, you want to ignore these.
 npm-debug.log
 /assets/node_modules/
-
Full Rendered Outputs (Before & After)
Before Commit
# The directory Mix will write compiled artifacts to.
/_build/

# If you run "mix test --cover", coverage assets end up here.
/cover/

# The directory Mix downloads your dependencies sources to.
/deps/

# Where 3rd-party dependencies like ExDoc output generated docs.
/doc/

# Ignore .fetch files in case you like to edit your project deps locally.
/.fetch

# If the VM crashes, it generates a dump, let's ignore it too.
erl_crash.dump

# Also ignore archive artifacts (built via "mix archive.build").
*.ez

# Temporary files, for example, from tests.
/tmp/

# Ignore package tarball (built via "mix hex.build").
my_app_web-*.tar

# Ignore assets that are produced by build tools.
/priv/static/assets/

# Ignore digested assets cache.
/priv/static/cache_manifest.json

# In case you use Node.js/npm, you want to ignore these.
npm-debug.log
/assets/node_modules/

After Commit
# The directory Mix will write compiled artifacts to.
/_build/

# If you run "mix test --cover", coverage assets end up here.
/cover/

# The directory Mix downloads your dependencies sources to.
/deps/

# Where 3rd-party dependencies like ExDoc output generated docs.
/doc/

# Ignore .fetch files in case you like to edit your project deps locally.
/.fetch

# If the VM crashes, it generates a dump, let's ignore it too.
erl_crash.dump

# Also ignore archive artifacts (built via "mix archive.build").
*.ez

# Temporary files, for example, from tests.
/tmp/

# Ignore package tarball (built via "mix hex.build").
my_app_web-*.tar

# Ignore assets that are produced by build tools.
/priv/static/assets/

# Ignore digested assets cache.
/priv/static/cache_manifest.json

# In case you use Node.js/npm, you want to ignore these.
npm-debug.log
/assets/node_modules/

Permutation: (javascript or css): false, sqlite3: true (Output changed by commit)

Unified Output Diff
--- Before
+++ After
@@ -28,4 +28,3 @@
 # Database files
 *.db
 *.db-*
-
Full Rendered Outputs (Before & After)
Before Commit
# The directory Mix will write compiled artifacts to.
/_build/

# If you run "mix test --cover", coverage assets end up here.
/cover/

# The directory Mix downloads your dependencies sources to.
/deps/

# Where 3rd-party dependencies like ExDoc output generated docs.
/doc/

# Ignore .fetch files in case you like to edit your project deps locally.
/.fetch

# If the VM crashes, it generates a dump, let's ignore it too.
erl_crash.dump

# Also ignore archive artifacts (built via "mix archive.build").
*.ez

# Temporary files, for example, from tests.
/tmp/

# Ignore package tarball (built via "mix hex.build").
my_app_web-*.tar

# Database files
*.db
*.db-*

After Commit
# The directory Mix will write compiled artifacts to.
/_build/

# If you run "mix test --cover", coverage assets end up here.
/cover/

# The directory Mix downloads your dependencies sources to.
/deps/

# Where 3rd-party dependencies like ExDoc output generated docs.
/doc/

# Ignore .fetch files in case you like to edit your project deps locally.
/.fetch

# If the VM crashes, it generates a dump, let's ignore it too.
erl_crash.dump

# Also ignore archive artifacts (built via "mix archive.build").
*.ez

# Temporary files, for example, from tests.
/tmp/

# Ignore package tarball (built via "mix hex.build").
my_app_web-*.tar

# Database files
*.db
*.db-*

Permutation: (javascript or css): false, sqlite3: false (Output changed by commit)

Unified Output Diff
--- Before
+++ After
@@ -24,4 +24,3 @@
 
 # Ignore package tarball (built via "mix hex.build").
 my_app_web-*.tar
-
Full Rendered Outputs (Before & After)
Before Commit
# The directory Mix will write compiled artifacts to.
/_build/

# If you run "mix test --cover", coverage assets end up here.
/cover/

# The directory Mix downloads your dependencies sources to.
/deps/

# Where 3rd-party dependencies like ExDoc output generated docs.
/doc/

# Ignore .fetch files in case you like to edit your project deps locally.
/.fetch

# If the VM crashes, it generates a dump, let's ignore it too.
erl_crash.dump

# Also ignore archive artifacts (built via "mix archive.build").
*.ez

# Temporary files, for example, from tests.
/tmp/

# Ignore package tarball (built via "mix hex.build").
my_app_web-*.tar

After Commit
# The directory Mix will write compiled artifacts to.
/_build/

# If you run "mix test --cover", coverage assets end up here.
/cover/

# The directory Mix downloads your dependencies sources to.
/deps/

# Where 3rd-party dependencies like ExDoc output generated docs.
/doc/

# Ignore .fetch files in case you like to edit your project deps locally.
/.fetch

# If the VM crashes, it generates a dump, let's ignore it too.
erl_crash.dump

# Also ignore archive artifacts (built via "mix archive.build").
*.ez

# Temporary files, for example, from tests.
/tmp/

# Ignore package tarball (built via "mix hex.build").
my_app_web-*.tar

Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ erl_crash.dump
/tmp/

# Ignore package tarball (built via "mix hex.build").
<%= @web_app_name %>-*.tar
<%= if @javascript or @css do %>
<%= @web_app_name %>-*.tar<%= if @javascript or @css do %>

# Ignore assets that are produced by build tools.
/priv/static/assets/

Expand All @@ -33,9 +33,8 @@ erl_crash.dump

# In case you use Node.js/npm, you want to ignore these.
npm-debug.log
/assets/node_modules/
<% end %><%= if @adapter_app == :ecto_sqlite3 do %>
/assets/node_modules/<% end %><%= if @adapter_app == :ecto_sqlite3 do %>

# Database files
*.db
*.db-*
<% end %>
*.db-*<% end %>
4 changes: 2 additions & 2 deletions installer/templates/phx_umbrella/config/test.exs.eex

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Computed Outputs Across Conditional Permutations

Permutation: mailer: true, html: true (Output changed by commit)

Unified Output Diff
--- Before
+++ After
@@ -16,7 +16,7 @@
 # Enable helpful, but potentially expensive runtime checks
 config :phoenix_live_view,
   enable_expensive_runtime_checks: true
-  
+
 # Sort query params output of verified routes for robust url comparisons
 config :phoenix,
-  sort_verified_routes_query_params: true
\ No newline at end of file
+  sort_verified_routes_query_params: true
Full Rendered Outputs (Before & After)
Before Commit
import Config

# Print only warnings and errors during test
config :logger, level: :warning

# In test we don't send emails
config :my_app, MyApp.Mailer,
  adapter: Swoosh.Adapters.Test

# Disable swoosh api client as it is only required for production adapters
config :swoosh, :api_client, false

# Initialize plugs at runtime for faster test compilation
config :phoenix, :plug_init_mode, :runtime

# Enable helpful, but potentially expensive runtime checks
config :phoenix_live_view,
  enable_expensive_runtime_checks: true
  
# Sort query params output of verified routes for robust url comparisons
config :phoenix,
  sort_verified_routes_query_params: true```

##### After Commit
```elixir
import Config

# Print only warnings and errors during test
config :logger, level: :warning

# In test we don't send emails
config :my_app, MyApp.Mailer,
  adapter: Swoosh.Adapters.Test

# Disable swoosh api client as it is only required for production adapters
config :swoosh, :api_client, false

# Initialize plugs at runtime for faster test compilation
config :phoenix, :plug_init_mode, :runtime

# Enable helpful, but potentially expensive runtime checks
config :phoenix_live_view,
  enable_expensive_runtime_checks: true

# Sort query params output of verified routes for robust url comparisons
config :phoenix,
  sort_verified_routes_query_params: true

Permutation: mailer: true, html: false (Output changed by commit)

Unified Output Diff
--- Before
+++ After
@@ -12,7 +12,7 @@
 
 # Initialize plugs at runtime for faster test compilation
 config :phoenix, :plug_init_mode, :runtime
-  
+
 # Sort query params output of verified routes for robust url comparisons
 config :phoenix,
-  sort_verified_routes_query_params: true
\ No newline at end of file
+  sort_verified_routes_query_params: true
Full Rendered Outputs (Before & After)
Before Commit
import Config

# Print only warnings and errors during test
config :logger, level: :warning

# In test we don't send emails
config :my_app, MyApp.Mailer,
  adapter: Swoosh.Adapters.Test

# Disable swoosh api client as it is only required for production adapters
config :swoosh, :api_client, false

# Initialize plugs at runtime for faster test compilation
config :phoenix, :plug_init_mode, :runtime
  
# Sort query params output of verified routes for robust url comparisons
config :phoenix,
  sort_verified_routes_query_params: true```

##### After Commit
```elixir
import Config

# Print only warnings and errors during test
config :logger, level: :warning

# In test we don't send emails
config :my_app, MyApp.Mailer,
  adapter: Swoosh.Adapters.Test

# Disable swoosh api client as it is only required for production adapters
config :swoosh, :api_client, false

# Initialize plugs at runtime for faster test compilation
config :phoenix, :plug_init_mode, :runtime

# Sort query params output of verified routes for robust url comparisons
config :phoenix,
  sort_verified_routes_query_params: true

Permutation: mailer: false, html: true (Output changed by commit)

Unified Output Diff
--- Before
+++ After
@@ -9,7 +9,7 @@
 # Enable helpful, but potentially expensive runtime checks
 config :phoenix_live_view,
   enable_expensive_runtime_checks: true
-  
+
 # Sort query params output of verified routes for robust url comparisons
 config :phoenix,
-  sort_verified_routes_query_params: true
\ No newline at end of file
+  sort_verified_routes_query_params: true
Full Rendered Outputs (Before & After)
Before Commit
import Config

# Print only warnings and errors during test
config :logger, level: :warning

# Initialize plugs at runtime for faster test compilation
config :phoenix, :plug_init_mode, :runtime

# Enable helpful, but potentially expensive runtime checks
config :phoenix_live_view,
  enable_expensive_runtime_checks: true
  
# Sort query params output of verified routes for robust url comparisons
config :phoenix,
  sort_verified_routes_query_params: true```

##### After Commit
```elixir
import Config

# Print only warnings and errors during test
config :logger, level: :warning

# Initialize plugs at runtime for faster test compilation
config :phoenix, :plug_init_mode, :runtime

# Enable helpful, but potentially expensive runtime checks
config :phoenix_live_view,
  enable_expensive_runtime_checks: true

# Sort query params output of verified routes for robust url comparisons
config :phoenix,
  sort_verified_routes_query_params: true

Permutation: mailer: false, html: false (Output changed by commit)

Unified Output Diff
--- Before
+++ After
@@ -5,7 +5,7 @@
 
 # Initialize plugs at runtime for faster test compilation
 config :phoenix, :plug_init_mode, :runtime
-  
+
 # Sort query params output of verified routes for robust url comparisons
 config :phoenix,
-  sort_verified_routes_query_params: true
\ No newline at end of file
+  sort_verified_routes_query_params: true
Full Rendered Outputs (Before & After)
Before Commit
import Config

# Print only warnings and errors during test
config :logger, level: :warning

# Initialize plugs at runtime for faster test compilation
config :phoenix, :plug_init_mode, :runtime
  
# Sort query params output of verified routes for robust url comparisons
config :phoenix,
  sort_verified_routes_query_params: true```

##### After Commit
```elixir
import Config

# Print only warnings and errors during test
config :logger, level: :warning

# Initialize plugs at runtime for faster test compilation
config :phoenix, :plug_init_mode, :runtime

# Sort query params output of verified routes for robust url comparisons
config :phoenix,
  sort_verified_routes_query_params: true

Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ config :phoenix, :plug_init_mode, :runtime<%= if @html do %>
# Enable helpful, but potentially expensive runtime checks
config :phoenix_live_view,
enable_expensive_runtime_checks: true<% end %>

# Sort query params output of verified routes for robust url comparisons
config :phoenix,
sort_verified_routes_query_params: true
sort_verified_routes_query_params: true
6 changes: 2 additions & 4 deletions installer/templates/phx_umbrella/gitignore.eex

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Computed Outputs Across Conditional Permutations

Permutation: sqlite3: true (Output changed by commit)

Unified Output Diff
--- Before
+++ After
@@ -22,8 +22,6 @@
 # Temporary files, for example, from tests.
 /tmp/
 
-
 # Database files
 *.db
 *.db-*
-
Full Rendered Outputs (Before & After)
Before Commit
# The directory Mix will write compiled artifacts to.
/_build/

# If you run "mix test --cover", coverage assets end up here.
/cover/

# The directory Mix downloads your dependencies sources to.
/deps/

# Where 3rd-party dependencies like ExDoc output generated docs.
/doc/

# Ignore .fetch files in case you like to edit your project deps locally.
/.fetch

# If the VM crashes, it generates a dump, let's ignore it too.
erl_crash.dump

# Also ignore archive artifacts (built via "mix archive.build").
*.ez

# Temporary files, for example, from tests.
/tmp/


# Database files
*.db
*.db-*

After Commit
# The directory Mix will write compiled artifacts to.
/_build/

# If you run "mix test --cover", coverage assets end up here.
/cover/

# The directory Mix downloads your dependencies sources to.
/deps/

# Where 3rd-party dependencies like ExDoc output generated docs.
/doc/

# Ignore .fetch files in case you like to edit your project deps locally.
/.fetch

# If the VM crashes, it generates a dump, let's ignore it too.
erl_crash.dump

# Also ignore archive artifacts (built via "mix archive.build").
*.ez

# Temporary files, for example, from tests.
/tmp/

# Database files
*.db
*.db-*

Permutation: sqlite3: false (Output changed by commit)

Unified Output Diff
--- Before
+++ After
@@ -21,5 +21,3 @@
 
 # Temporary files, for example, from tests.
 /tmp/
-
-
Full Rendered Outputs (Before & After)
Before Commit
# The directory Mix will write compiled artifacts to.
/_build/

# If you run "mix test --cover", coverage assets end up here.
/cover/

# The directory Mix downloads your dependencies sources to.
/deps/

# Where 3rd-party dependencies like ExDoc output generated docs.
/doc/

# Ignore .fetch files in case you like to edit your project deps locally.
/.fetch

# If the VM crashes, it generates a dump, let's ignore it too.
erl_crash.dump

# Also ignore archive artifacts (built via "mix archive.build").
*.ez

# Temporary files, for example, from tests.
/tmp/


After Commit
# The directory Mix will write compiled artifacts to.
/_build/

# If you run "mix test --cover", coverage assets end up here.
/cover/

# The directory Mix downloads your dependencies sources to.
/deps/

# Where 3rd-party dependencies like ExDoc output generated docs.
/doc/

# Ignore .fetch files in case you like to edit your project deps locally.
/.fetch

# If the VM crashes, it generates a dump, let's ignore it too.
erl_crash.dump

# Also ignore archive artifacts (built via "mix archive.build").
*.ez

# Temporary files, for example, from tests.
/tmp/

Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,8 @@ erl_crash.dump
*.ez

# Temporary files, for example, from tests.
/tmp/
/tmp/<%= if @adapter_app == :ecto_sqlite3 do %>

<%= if @adapter_app == :ecto_sqlite3 do %>
# Database files
*.db
*.db-*
<% end %>
*.db-*<% end %>
17 changes: 15 additions & 2 deletions installer/test/mix_helper.exs
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,21 @@ defmodule MixHelper do

def assert_file(file) do
assert File.regular?(file), "Expected #{file} to exist, but does not"
content = File.read!(file)

if not binary_file?(file) do
# \S\n\z matches non-whitespace followed by a single newline at EOF
assert content == "" or content =~ ~r/\S\n\z/,
"Expected #{file} to end with a single trailing newline"

refute content =~ "\n\n\n", "Expected #{file} to not contain consecutive blank lines"
end

content
Comment on lines +99 to +109

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This is similar to elixir-lang/elixir#15711, but skipping the additional checks on some files by extension.

end

defp binary_file?(file), do: Path.extname(file) in ~w(.ico .pem .png)

def refute_file(file) do
refute File.regular?(file), "Expected #{file} to not exist, but it does"
end
Expand All @@ -111,8 +124,8 @@ defmodule MixHelper do
assert_file(file, &assert(&1 =~ match))

is_function(match, 1) ->
assert_file(file)
match.(File.read!(file))
content = assert_file(file)
match.(content)

true ->
raise inspect({file, match})
Expand Down
5 changes: 0 additions & 5 deletions installer/test/phx_new_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,6 @@ defmodule Mix.Tasks.Phx.NewTest do
assert_file("phx_blog/.gitignore", fn file ->
assert file =~ "/priv/static/assets/"
assert file =~ "phx_blog-*.tar"
assert file =~ ~r/\n$/
end)

assert_file("phx_blog/config/dev.exs", fn file ->
Expand Down Expand Up @@ -324,7 +323,6 @@ defmodule Mix.Tasks.Phx.NewTest do
# No assets
assert_file("phx_blog/.gitignore", fn file ->
refute file =~ "/priv/static/assets/"
assert file =~ ~r/\n$/
end)

refute File.exists?("phx_blog/priv/static/images/logo.svg")
Expand Down Expand Up @@ -531,8 +529,6 @@ defmodule Mix.Tasks.Phx.NewTest do
refute file =~ "/priv/static/assets/"
end)

assert_file("phx_blog/.gitignore")
assert_file("phx_blog/.gitignore", ~r/\n$/)
assert_file("phx_blog/priv/static/assets/css/app.css")
assert_file("phx_blog/priv/static/assets/js/app.js")
assert_file("phx_blog/priv/static/favicon.ico")
Expand Down Expand Up @@ -592,7 +588,6 @@ defmodule Mix.Tasks.Phx.NewTest do
Mix.Tasks.Phx.New.run([project_path, "--app", @app_name, "--module", "PhoteuxBlog"])

assert_file("custom_path/.gitignore")
assert_file("custom_path/.gitignore", ~r/\n$/)
assert_file("custom_path/mix.exs", ~r/app: :phx_blog/)
assert_file("custom_path/lib/phx_blog_web/endpoint.ex", ~r/app: :phx_blog/)
assert_file("custom_path/config/config.exs", ~r/namespace: PhoteuxBlog/)
Expand Down
16 changes: 9 additions & 7 deletions installer/test/phx_new_umbrella_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -194,9 +194,10 @@ defmodule Mix.Tasks.Phx.New.UmbrellaTest do
end)

# assets
assert_file(web_path(@app, ".gitignore"), "/priv/static/assets/")
assert_file(web_path(@app, ".gitignore"), "#{@app}_web-*.tar")
assert_file(web_path(@app, ".gitignore"), ~r/\n$/)
assert_file(web_path(@app, ".gitignore"), fn file ->
assert file =~ "/priv/static/assets/"
assert file =~ "#{@app}_web-*.tar"
end)

assert_file(web_path(@app, "assets/css/app.css"), fn file ->
assert file =~ "lib/phx_umb_web"
Expand Down Expand Up @@ -353,7 +354,6 @@ defmodule Mix.Tasks.Phx.New.UmbrellaTest do

# No assets
assert_file(web_path(@app, ".gitignore"), fn file ->
assert file =~ ~r/\n$/
refute file =~ "/priv/static/assets/"
end)

Expand Down Expand Up @@ -516,8 +516,10 @@ defmodule Mix.Tasks.Phx.New.UmbrellaTest do
in_tmp("new with no_assets", fn ->
Mix.Tasks.Phx.New.run([@app, "--umbrella", "--no-assets"])

refute File.read!(web_path(@app, ".gitignore")) |> String.contains?("/priv/static/assets/")
assert_file(web_path(@app, ".gitignore"), ~r/\n$/)
assert_file(web_path(@app, ".gitignore"), fn file ->
refute file =~ "/priv/static/assets/"
end)

assert_file(web_path(@app, "priv/static/assets/js/app.js"))
assert_file(web_path(@app, "priv/static/assets/css/app.css"))
assert_file(web_path(@app, "priv/static/favicon.ico"))
Expand Down Expand Up @@ -883,7 +885,7 @@ defmodule Mix.Tasks.Phx.New.UmbrellaTest do
assert_file("another/lib/another/components/layouts/root.html.heex")

# assets
assert_file("another/.gitignore", ~r/\n$/)
assert_file("another/.gitignore")
assert_file("another/priv/static/favicon.ico")
assert_file("another/assets/css/app.css")

Expand Down
39 changes: 39 additions & 0 deletions lib/mix/phoenix/schema.ex
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,45 @@ defmodule Mix.Phoenix.Schema do
end)
end

def format_schema_body(schema, scope \\ nil) do
fields = format_fields_for_schema(schema)

assocs =
Enum.map_join(schema.assocs, "\n", fn {_, k, _, _} ->
type = if schema.binary_id, do: ":binary_id", else: ":id"
" field #{inspect(k)}, #{type}"
end)

scope_field =
if scope do
" field :#{scope.schema_key}, #{inspect(scope.schema_type)}"
else
""
end

timestamp_opts =
if schema.timestamp_type != :naive_datetime do
"type: #{inspect(schema.timestamp_type)}"
else
""
end

timestamps = " timestamps(#{timestamp_opts})"

schema_fields =
[fields, assocs, scope_field]
|> join_non_empty("\n")

[schema_fields, timestamps]
|> join_non_empty("\n\n")
end

defp join_non_empty(list, joiner) do
list
|> Enum.reject(&(&1 == ""))
|> Enum.join(joiner)
end

@doc """
Returns the required fields in the schema. Anything not in the `optionals` list
is considered required.
Expand Down
6 changes: 1 addition & 5 deletions priv/templates/phx.gen.schema/schema.ex.eex

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Computed Outputs Across Conditional Permutations

Permutation: With fields (title:string), no assocs (Output unchanged)

Unified Output Diff
(No output changes)
Full Rendered Outputs (Before & After)
Before Commit
defmodule Phoenix.Blog.Post do
  use Ecto.Schema
  import Ecto.Changeset

  schema "posts" do
    field :title, :string

    timestamps()
  end

  @doc false
  def changeset(post, attrs) do
    post
    |> cast(attrs, [:title])
    |> validate_required([:title])
  end
end
After Commit
defmodule Phoenix.Blog.Post do
  use Ecto.Schema
  import Ecto.Changeset

  schema "posts" do
    field :title, :string

    timestamps()
  end

  @doc false
  def changeset(post, attrs) do
    post
    |> cast(attrs, [:title])
    |> validate_required([:title])
  end
end

Permutation: No fields, no assocs (Output changed by commit)

Unified Output Diff
--- Before
+++ After
@@ -3,8 +3,6 @@
   import Ecto.Changeset
 
   schema "posts" do
-
-
     timestamps()
   end
 
Full Rendered Outputs (Before & After)
Before Commit
defmodule Phoenix.Blog.Post do
  use Ecto.Schema
  import Ecto.Changeset

  schema "posts" do


    timestamps()
  end

  @doc false
  def changeset(post, attrs) do
    post
    |> cast(attrs, [])
    |> validate_required([])
  end
end
After Commit
defmodule Phoenix.Blog.Post do
  use Ecto.Schema
  import Ecto.Changeset

  schema "posts" do
    timestamps()
  end

  @doc false
  def changeset(post, attrs) do
    post
    |> cast(attrs, [])
    |> validate_required([])
  end
end

Permutation: No fields, with assoc (post_id:references) (Output changed by commit)

Unified Output Diff
--- Before
+++ After
@@ -3,7 +3,6 @@
   import Ecto.Changeset
 
   schema "comments" do
-
     field :post_id, :id
 
     timestamps()
Full Rendered Outputs (Before & After)
Before Commit
defmodule Phoenix.Blog.Comment do
  use Ecto.Schema
  import Ecto.Changeset

  schema "comments" do

    field :post_id, :id

    timestamps()
  end

  @doc false
  def changeset(comment, attrs) do
    comment
    |> cast(attrs, [])
    |> validate_required([])
  end
end
After Commit
defmodule Phoenix.Blog.Comment do
  use Ecto.Schema
  import Ecto.Changeset

  schema "comments" do
    field :post_id, :id

    timestamps()
  end

  @doc false
  def changeset(comment, attrs) do
    comment
    |> cast(attrs, [])
    |> validate_required([])
  end
end

Permutation: With fields (title:string) and assoc (Output changed by commit)

Unified Output Diff
--- Before
+++ After
@@ -3,7 +3,6 @@
   import Ecto.Changeset
 
   schema "comments" do
-
     field :post_id, :id
 
     timestamps()
Full Rendered Outputs (Before & After)
Before Commit
defmodule Phoenix.Blog.Comment do
  use Ecto.Schema
  import Ecto.Changeset

  schema "comments" do

    field :post_id, :id

    timestamps()
  end

  @doc false
  def changeset(comment, attrs) do
    comment
    |> cast(attrs, [])
    |> validate_required([])
  end
end
After Commit
defmodule Phoenix.Blog.Comment do
  use Ecto.Schema
  import Ecto.Changeset

  schema "comments" do
    field :post_id, :id

    timestamps()
  end

  @doc false
  def changeset(comment, attrs) do
    comment
    |> cast(attrs, [])
    |> validate_required([])
  end
end

Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,7 @@ defmodule <%= inspect schema.module %> do
@foreign_key_type :binary_id<% else %><%= if schema.opts[:primary_key] do %>
@primary_key {:<%= schema.opts[:primary_key] %>, :id, autogenerate: true}<% end %><% end %>
schema <%= inspect schema.table %> do
<%= Mix.Phoenix.Schema.format_fields_for_schema(schema) %>
<%= for {_, k, _, _} <- schema.assocs do %> field <%= inspect k %>, <%= if schema.binary_id do %>:binary_id<% else %>:id<% end %>
<% end %><%= if scope do %> field :<%= scope.schema_key %>, <%= inspect scope.schema_type %>
<% end %>
timestamps(<%= if schema.timestamp_type != :naive_datetime, do: "type: #{inspect schema.timestamp_type}" %>)
<%= Mix.Phoenix.Schema.format_schema_body(schema, scope) %>
end

@doc false
Expand Down
10 changes: 3 additions & 7 deletions priv/templates/phx.gen.socket/socket.ex.eex

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Computed Outputs Across Conditional Permutations

Permutation: existing_channel present (Output changed by commit)

Unified Output Diff
--- Before
+++ After
@@ -6,8 +6,6 @@
   # It's possible to control the websocket connection and
   # assign values that can be accessed by your channel topics.
 
-  ## Channels
-
   channel "user:*", UserChannel
 
   # Socket params are passed from the client and can
Full Rendered Outputs (Before & After)
Before Commit
defmodule UserSocket do
  use Phoenix.Socket

  # A Socket handler
  #
  # It's possible to control the websocket connection and
  # assign values that can be accessed by your channel topics.

  ## Channels

  channel "user:*", UserChannel

  # Socket params are passed from the client and can
  # be used to verify and authenticate a user. After
  # verification, you can put default assigns into
  # the socket that will be set for all channels, ie
  #
  #     {:ok, assign(socket, :user_id, verified_user_id)}
  #
  # To deny connection, return `:error` or `{:error, term}`. To control the
  # response the client receives in that case, [define an error handler in the
  # websocket
  # configuration](https://phoenix.hexdocs.pm/Phoenix.Endpoint.html#socket/3-websocket-configuration).
  #
  # See `Phoenix.Token` documentation for examples in
  # performing token verification on connect.
  @impl true
  def connect(_params, socket, _connect_info) do
    {:ok, socket}
  end

  # Socket IDs are topics that allow you to identify all sockets for a given user:
  #
  #     def id(socket), do: "user_socket:#{socket.assigns.user_id}"
  #
  # Would allow you to broadcast a "disconnect" event and terminate
  # all active sockets and channels for a given user:
  #
  #     UserWeb.Endpoint.broadcast("user_socket:#{user.id}", "disconnect", %{})
  #
  # Returning `nil` makes this socket anonymous.
  @impl true
  def id(_socket), do: nil
end
After Commit
defmodule UserSocket do
  use Phoenix.Socket

  # A Socket handler
  #
  # It's possible to control the websocket connection and
  # assign values that can be accessed by your channel topics.

  channel "user:*", UserChannel

  # Socket params are passed from the client and can
  # be used to verify and authenticate a user. After
  # verification, you can put default assigns into
  # the socket that will be set for all channels, ie
  #
  #     {:ok, assign(socket, :user_id, verified_user_id)}
  #
  # To deny connection, return `:error` or `{:error, term}`. To control the
  # response the client receives in that case, [define an error handler in the
  # websocket
  # configuration](https://phoenix.hexdocs.pm/Phoenix.Endpoint.html#socket/3-websocket-configuration).
  #
  # See `Phoenix.Token` documentation for examples in
  # performing token verification on connect.
  @impl true
  def connect(_params, socket, _connect_info) do
    {:ok, socket}
  end

  # Socket IDs are topics that allow you to identify all sockets for a given user:
  #
  #     def id(socket), do: "user_socket:#{socket.assigns.user_id}"
  #
  # Would allow you to broadcast a "disconnect" event and terminate
  # all active sockets and channels for a given user:
  #
  #     UserWeb.Endpoint.broadcast("user_socket:#{user.id}", "disconnect", %{})
  #
  # Returning `nil` makes this socket anonymous.
  @impl true
  def id(_socket), do: nil
end

Permutation: existing_channel nil (Output changed by commit)

Unified Output Diff
--- Before
+++ After
@@ -6,7 +6,6 @@
   # It's possible to control the websocket connection and
   # assign values that can be accessed by your channel topics.
 
-  ## Channels
   # Uncomment the following line to define a "room:*" topic
   # pointing to the `UserWeb.RoomChannel`:
   #
@@ -19,7 +18,6 @@
   # See the [`Channels guide`](https://phoenix.hexdocs.pm/channels.html)
   # for further details.
 
-
   # Socket params are passed from the client and can
   # be used to verify and authenticate a user. After
   # verification, you can put default assigns into
Full Rendered Outputs (Before & After)
Before Commit
defmodule UserSocket do
  use Phoenix.Socket

  # A Socket handler
  #
  # It's possible to control the websocket connection and
  # assign values that can be accessed by your channel topics.

  ## Channels
  # Uncomment the following line to define a "room:*" topic
  # pointing to the `UserWeb.RoomChannel`:
  #
  # channel "room:*", UserWeb.RoomChannel
  #
  # To create a channel file, use the mix task:
  #
  #     mix phx.gen.channel Room
  #
  # See the [`Channels guide`](https://phoenix.hexdocs.pm/channels.html)
  # for further details.


  # Socket params are passed from the client and can
  # be used to verify and authenticate a user. After
  # verification, you can put default assigns into
  # the socket that will be set for all channels, ie
  #
  #     {:ok, assign(socket, :user_id, verified_user_id)}
  #
  # To deny connection, return `:error` or `{:error, term}`. To control the
  # response the client receives in that case, [define an error handler in the
  # websocket
  # configuration](https://phoenix.hexdocs.pm/Phoenix.Endpoint.html#socket/3-websocket-configuration).
  #
  # See `Phoenix.Token` documentation for examples in
  # performing token verification on connect.
  @impl true
  def connect(_params, socket, _connect_info) do
    {:ok, socket}
  end

  # Socket IDs are topics that allow you to identify all sockets for a given user:
  #
  #     def id(socket), do: "user_socket:#{socket.assigns.user_id}"
  #
  # Would allow you to broadcast a "disconnect" event and terminate
  # all active sockets and channels for a given user:
  #
  #     UserWeb.Endpoint.broadcast("user_socket:#{user.id}", "disconnect", %{})
  #
  # Returning `nil` makes this socket anonymous.
  @impl true
  def id(_socket), do: nil
end
After Commit
defmodule UserSocket do
  use Phoenix.Socket

  # A Socket handler
  #
  # It's possible to control the websocket connection and
  # assign values that can be accessed by your channel topics.

  # Uncomment the following line to define a "room:*" topic
  # pointing to the `UserWeb.RoomChannel`:
  #
  # channel "room:*", UserWeb.RoomChannel
  #
  # To create a channel file, use the mix task:
  #
  #     mix phx.gen.channel Room
  #
  # See the [`Channels guide`](https://phoenix.hexdocs.pm/channels.html)
  # for further details.

  # Socket params are passed from the client and can
  # be used to verify and authenticate a user. After
  # verification, you can put default assigns into
  # the socket that will be set for all channels, ie
  #
  #     {:ok, assign(socket, :user_id, verified_user_id)}
  #
  # To deny connection, return `:error` or `{:error, term}`. To control the
  # response the client receives in that case, [define an error handler in the
  # websocket
  # configuration](https://phoenix.hexdocs.pm/Phoenix.Endpoint.html#socket/3-websocket-configuration).
  #
  # See `Phoenix.Token` documentation for examples in
  # performing token verification on connect.
  @impl true
  def connect(_params, socket, _connect_info) do
    {:ok, socket}
  end

  # Socket IDs are topics that allow you to identify all sockets for a given user:
  #
  #     def id(socket), do: "user_socket:#{socket.assigns.user_id}"
  #
  # Would allow you to broadcast a "disconnect" event and terminate
  # all active sockets and channels for a given user:
  #
  #     UserWeb.Endpoint.broadcast("user_socket:#{user.id}", "disconnect", %{})
  #
  # Returning `nil` makes this socket anonymous.
  @impl true
  def id(_socket), do: nil
end

Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,8 @@ defmodule <%= module %>Socket do
#
# It's possible to control the websocket connection and
# assign values that can be accessed by your channel topics.

## Channels<%= if existing_channel do %>

channel "<%= existing_channel[:singular] %>:*", <%= existing_channel[:module] %>Channel
<% else %>
<%= if existing_channel do %>
channel "<%= existing_channel[:singular] %>:*", <%= existing_channel[:module] %>Channel<% else %>
# Uncomment the following line to define a "room:*" topic
# pointing to the `<%= web_module %>.RoomChannel`:
#
Expand All @@ -20,9 +17,8 @@ defmodule <%= module %>Socket do
# mix phx.gen.channel Room
#
# See the [`Channels guide`](https://phoenix.hexdocs.pm/channels.html)
# for further details.
# for further details.<% end %>

<% end %>
# Socket params are passed from the client and can
# be used to verify and authenticate a user. After
# verification, you can put default assigns into
Expand Down
2 changes: 1 addition & 1 deletion test/mix/tasks/phx.gen.auth_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -1442,7 +1442,7 @@ defmodule Mix.Tasks.Phx.Gen.AuthTest do
test "allows templates to be overridden", config do
in_tmp_phx_project(config.test, fn ->
File.mkdir_p!("priv/templates/phx.gen.auth")
File.write!("priv/templates/phx.gen.auth/auth.ex.eex", "#it works!")
File.write!("priv/templates/phx.gen.auth/auth.ex.eex", "#it works!\n")

send(self(), {:mix_shell_input, :yes?, false})

Expand Down
47 changes: 47 additions & 0 deletions test/mix/tasks/phx.gen.schema_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -726,4 +726,51 @@ defmodule Mix.Tasks.Phx.Gen.SchemaTest do
)
end)
end

describe "format_schema_body/2" do
setup do
scope = %{schema_key: :user_id, schema_type: :id}
{:ok, scope: scope}
end

test "no fields, no assocs, no scope" do
schema = Schema.new("Blog.Post", "posts", [], [])
assert Schema.format_schema_body(schema) == " timestamps()"
end

test "with fields, no assocs, no scope" do
schema = Schema.new("Blog.Post", "posts", ["title:string"], [])
assert Schema.format_schema_body(schema) == " field :title, :string\n\n timestamps()"
end

test "no fields, with assocs, no scope" do
schema = Schema.new("Blog.Comment", "comments", ["post_id:references:posts"], [])
assert Schema.format_schema_body(schema) == " field :post_id, :id\n\n timestamps()"
end

test "no fields, no assocs, with scope", %{scope: scope} do
schema = Schema.new("Blog.Post", "posts", [], [])
assert Schema.format_schema_body(schema, scope) == " field :user_id, :id\n\n timestamps()"
end

test "with fields, with assocs, no scope" do
schema = Schema.new("Blog.Comment", "comments", ["title:string", "post_id:references:posts"], [])
assert Schema.format_schema_body(schema) == " field :title, :string\n field :post_id, :id\n\n timestamps()"
end

test "with fields, no assocs, with scope", %{scope: scope} do
schema = Schema.new("Blog.Post", "posts", ["title:string"], [])
assert Schema.format_schema_body(schema, scope) == " field :title, :string\n field :user_id, :id\n\n timestamps()"
end

test "no fields, with assocs, with scope", %{scope: scope} do
schema = Schema.new("Blog.Comment", "comments", ["post_id:references:posts"], [])
assert Schema.format_schema_body(schema, scope) == " field :post_id, :id\n field :user_id, :id\n\n timestamps()"
end

test "with fields, with assocs, with scope", %{scope: scope} do
schema = Schema.new("Blog.Comment", "comments", ["title:string", "post_id:references:posts"], [])
assert Schema.format_schema_body(schema, scope) == " field :title, :string\n field :post_id, :id\n field :user_id, :id\n\n timestamps()"
end
end
end
1 change: 0 additions & 1 deletion usage-rules/elixir.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,3 @@
assert_receive {:DOWN, ^ref, :process, ^pid, :normal}

- Instead of sleeping to synchronize before the next call, **always** use `_ = :sys.get_state/1` to ensure the process has handled prior messages

Loading