Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
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
23 changes: 5 additions & 18 deletions .ameba.yml
Original file line number Diff line number Diff line change
@@ -1,24 +1,11 @@
# This configuration file was generated by `ameba --gen-config`
# on 2026-04-02 23:47:16 UTC using Ameba version 1.6.4.
# The point is for the user to remove these configuration records
# one by one as the reported problems are removed from the code base.

# Problems found: 92
# Run `ameba --only Lint/UselessAssign` for details
Lint/UselessAssign:
Description: Disallows useless variable assignments
ExcludeTypeDeclarations: true
Enabled: true
Severity: Warning

# Problems found: 9
# Run `ameba --only Lint/Typos` for details
Lint/Typos:
Description: Reports typos found in source files
Enabled: true
FailOnError: false
Excluded:
- spec/lucky/text_helpers/truncate_spec.cr
- spec/lucky/text_helpers/excerpts_spec.cr
- spec/lucky/secure_headers_spec.cr
Enabled: true
Severity: Warning

Lint/AssignmentInCallArgument:
Excluded:
- spec/lucky/memoize_spec.cr
19 changes: 19 additions & 0 deletions .github/workflows/ameba.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
name: Ameba

on:
push:
pull_request:

permissions:
contents: read

jobs:
lint:
runs-on: ubuntu-latest

steps:
- name: Download source
uses: actions/checkout@v7

- name: Run Ameba Linter
uses: crystal-ameba/github-action@master
18 changes: 1 addition & 17 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,9 @@ on:
push:
branches: [main]
pull_request:
branches: "*"
branches: '*'

jobs:
check_format:
strategy:
fail-fast: false
runs-on: ubuntu-latest
continue-on-error: false
steps:
- uses: actions/checkout@v6
- uses: crystal-lang/install-crystal@v1
with:
crystal: latest
- name: Install shards
run: shards install
- name: Format
run: crystal tool format --check
Comment thread
Sija marked this conversation as resolved.
- name: Lint
run: ./bin/ameba
specs:
strategy:
fail-fast: false
Expand Down
12 changes: 6 additions & 6 deletions bin/lucky.gen.action.cr
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
require "colorize"

puts <<-ERROR
Missing 'browser' or 'api' after 'gen.action'
Missing 'browser' or 'api' after 'gen.action'

For actions used in a browser (HTML, redirects)...
For actions used in a browser (HTML, redirects)...

#{"lucky gen.action.browser".colorize.green.bold}
#{"lucky gen.action.browser".colorize.green.bold}

For an API endpoint (JSON, XML, GraphQL)...
For an API endpoint (JSON, XML, GraphQL)...

#{"lucky gen.action.api".colorize.green.bold}
#{"lucky gen.action.api".colorize.green.bold}


ERROR
ERROR
2 changes: 1 addition & 1 deletion shard.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,6 @@ development_dependencies:
version: ~> 0.3.0
ameba:
github: crystal-ameba/ameba
version: ~> 1.6.4
branch: master

license: MIT
8 changes: 4 additions & 4 deletions spec/lucky/action_pipes_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -235,9 +235,9 @@ describe Lucky::Action do
end
Pipes::HaltedBefore.new(build_context, params).call
halted_pipe = events.find! { |e| e.name == "redirect_me" }
halted_pipe.continued.should eq false
halted_pipe.continued.should be_false
halted_pipe.position.to_s.should eq "Before"
halted_pipe.before?.should eq true
halted_pipe.before?.should be_true
end

it "publishes an event on after when halted" do
Expand All @@ -247,9 +247,9 @@ describe Lucky::Action do
end
Pipes::HaltedAfter.new(build_context, params).call
halted_pipe = events.find! { |e| e.name == "redirect_me" }
halted_pipe.continued.should eq false
halted_pipe.continued.should be_false
halted_pipe.position.to_s.should eq "After"
halted_pipe.after?.should eq true
halted_pipe.after?.should be_true
end
end
end
2 changes: 1 addition & 1 deletion spec/lucky/action_redirect_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ describe Lucky::Action do
response = action.redirect to: "/somewhere", status: 302
should_redirect(action, to: "/somewhere", status: 200)
action.context.response.headers.has_key?("Turbolinks-Location").should be_false
response.body.should eq %[Turbolinks.clearCache();\nTurbolinks.visit("/somewhere", {"action": "replace"})]
response.body.should eq %(Turbolinks.clearCache();\nTurbolinks.visit("/somewhere", {"action": "replace"}))
end

it "set a cookie for redirects occurring during a turbolinks GET request" do
Expand Down
2 changes: 1 addition & 1 deletion spec/lucky/action_route_params_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ describe "Automatically generated param helpers" do
action = TestOptionalParamAction.new(build_context, {"required" => "1", "optional_1" => "2"})
action.required.should eq "1"
action.optional_1.should eq "2"
action.optional_2.should eq nil
action.optional_2.should be_nil
typeof(action.optional_1).should eq String?
typeof(action.optional_2).should eq String?
end
Expand Down
6 changes: 3 additions & 3 deletions spec/lucky/action_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -537,7 +537,7 @@ describe Lucky::Action do

it "is initialized to nil" do
action = OptionalParams::Index.new(build_context(path: ""), params)
action.page.should eq nil
action.page.should be_nil
end

it "is fetched if present" do
Expand All @@ -557,7 +557,7 @@ describe Lucky::Action do

it "can specify nil as the default value" do
action = OptionalParams::Index.new(build_context(path: ""), params)
action.nilable_with_explicit_nil.should eq nil
action.nilable_with_explicit_nil.should be_nil
end

it "overrides the default if present" do
Expand Down Expand Up @@ -612,7 +612,7 @@ describe Lucky::Action do

it "returns nil when the key is passed with no value for an optional param" do
action = OptionalParams::Index.new(build_context(path: "/?optional_bool_with_no_default"), params)
action.optional_bool_with_no_default.should eq(nil)
action.optional_bool_with_no_default.should be_nil
end
end
end
8 changes: 4 additions & 4 deletions spec/lucky/base_http_client_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ describe Lucky::BaseHTTPClient do
{ "event_id": "1"}
{ "type": "event"}
{ "event_id": "2", "type": "event", "platform": ""}
JSON
JSON
response = MyClient.new.exec_raw(HelloWorldAction, test_data)

request = TestServer.last_request
Expand All @@ -117,7 +117,7 @@ describe Lucky::BaseHTTPClient do
{ "event_id": "1"}
{ "type": "event"}
{ "event_id": "2", "type": "event", "platform": ""}
JSON
JSON
response = MyClient.new.exec_raw(HelloWorldAction.route, test_data)

request = TestServer.last_request
Expand All @@ -129,7 +129,7 @@ describe Lucky::BaseHTTPClient do
{% for method in [:put, :patch, :post, :delete, :get, :options] %}
describe "\#{{method.id}}" do
it "sends correct request to correct uri and gives the correct response" do
response = MyClient.new.{{method.id}}(
response = MyClient.new.{{ method.id }}(
path: "hello",
foo: "bar"
)
Expand All @@ -141,7 +141,7 @@ describe Lucky::BaseHTTPClient do
end

it "works without params" do
response = MyClient.new.{{method.id}}(path: "hello")
response = MyClient.new.{{ method.id }}(path: "hello")

request = TestServer.last_request
request.method.should eq({{ method.id.stringify }}.upcase)
Expand Down
10 changes: 5 additions & 5 deletions spec/lucky/base_tags_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -38,24 +38,24 @@ describe Lucky::BaseTags do
page.video(attrs: [:autoplay, :controls, :loop], poster: "https://luckyframework.org/nothing.png") do
page.source(src: "https://luckyframework.org/nothing.mp4", type: "video/mp4")
end
end.should contain %{<video poster="https://luckyframework.org/nothing.png" autoplay controls loop><source src="https://luckyframework.org/nothing.mp4" type="video/mp4"></video>}
end.should contain %(<video poster="https://luckyframework.org/nothing.png" autoplay controls loop><source src="https://luckyframework.org/nothing.mp4" type="video/mp4"></video>)

view(&.video(id: "player", "data-stream": "https://luckyframework.org/demo.mp4")).should eq %{<video id="player" data-stream="https://luckyframework.org/demo.mp4"></video>}
view(&.video(id: "player", "data-stream": "https://luckyframework.org/demo.mp4")).should eq %(<video id="player" data-stream="https://luckyframework.org/demo.mp4"></video>)
end

it "renders a button with a disabled boolean attribute" do
view(&.button("text", attrs: [:disabled])).should contain "<button disabled>text</button>"
end

it "renders an input with autofocus boolean attribute" do
view(&.input(attrs: [:autofocus], type: "text")).to_s.should contain %{<input type="text" autofocus>}
view(&.input(attrs: [:autofocus], type: "text")).to_s.should contain %(<input type="text" autofocus>)
end

describe "#style" do
it "renders a style tag" do
view(&.style("body { font-size: 2em; }")).should contain <<-HTML
<style>body { font-size: 2em; }</style>
HTML
<style>body { font-size: 2em; }</style>
HTML
end
end
end
Expand Down
4 changes: 2 additions & 2 deletions spec/lucky/component_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -171,8 +171,8 @@ describe "components rendering" do
it "uses context from being mounted" do
contents = TestMountPage.new(context_with_csrf).render.to_s
contents.should contain <<-HTML
input type="hidden" name="_csrf"
HTML
input type="hidden" name="_csrf"
HTML
end
end

Expand Down
2 changes: 1 addition & 1 deletion spec/lucky/cookies/cookie_jar_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ describe Lucky::CookieJar do
cookies = HTTP::Cookies.new
cookies[cookie_key] = cookie_value
jar = Lucky::CookieJar.from_request_cookies(cookies)
jar.get?(cookie_key).should eq(nil)
jar.get?(cookie_key).should be_nil
end

describe "#set" do
Expand Down
12 changes: 6 additions & 6 deletions spec/lucky/cookies/flash_store_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ describe Lucky::FlashStore do

it "raises an error when flash JSON is invalid" do
message = <<-MESSAGE
The flash messages (stored as JSON) failed to parse in a JSON parser.
Here's what it tries to parse:
The flash messages (stored as JSON) failed to parse in a JSON parser.
Here's what it tries to parse:

not_valid_json=invalid
MESSAGE
not_valid_json=invalid
MESSAGE

expect_raises(Lucky::InvalidFlashJSONError, message) do
Lucky::FlashStore.from_session(build_invalid_session)
Expand Down Expand Up @@ -92,14 +92,14 @@ describe Lucky::FlashStore do
it "returns true if there are key/value pairs" do
flash_store = build_flash_store({"some_key" => "some_value"})

# ameba:disable Performance/AnyInsteadOfEmpty
# ameba:disable Performance/AnyInsteadOfPresent
flash_store.any?.should be_true
end

it "returns false if there are no key/value pairs" do
flash_store = build_flash_store

# ameba:disable Performance/AnyInsteadOfEmpty
# ameba:disable Performance/AnyInsteadOfPresent
flash_store.any?.should be_false
end
end
Expand Down
12 changes: 6 additions & 6 deletions spec/lucky/forgery_protection_helpers_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ describe Lucky::ForgeryProtectionHelpers do
context.session.set(Lucky::ProtectFromForgery::SESSION_KEY, "my_token")

view(context, &.csrf_hidden_input).should contain <<-HTML
<input type="hidden" name="#{Lucky::ProtectFromForgery::PARAM_KEY}" value="my_token">
HTML
<input type="hidden" name="#{Lucky::ProtectFromForgery::PARAM_KEY}" value="my_token">
HTML
end

it "renders a meta tag for Rails UJS (and other JS that may need it)" do
Expand All @@ -25,11 +25,11 @@ describe Lucky::ForgeryProtectionHelpers do
rendered = view(context, &.csrf_meta_tags)

rendered.should contain <<-HTML
<meta name="csrf-param" content="#{Lucky::ProtectFromForgery::PARAM_KEY}">
HTML
<meta name="csrf-param" content="#{Lucky::ProtectFromForgery::PARAM_KEY}">
HTML
rendered.should contain <<-HTML
<meta name="csrf-token" content="my_token">
HTML
<meta name="csrf-token" content="my_token">
HTML
end
end

Expand Down
Loading