diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000..7e38bf9 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,26 @@ +name: Lint + +on: + push: + branches: [master, main] + pull_request: + branches: [master, main] + +jobs: + lint: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: '3.0.6' + bundler-cache: true + + - name: Run RuboCop + run: bundle exec rubocop + + - name: Check for files missing newlines + run: bundle exec rake check_newlines diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml index b48f1ce..29a83bd 100644 --- a/.github/workflows/ruby.yml +++ b/.github/workflows/ruby.yml @@ -15,7 +15,7 @@ jobs: - name: Set up Ruby uses: ruby/setup-ruby@v1 with: - ruby-version: 2.7.6 + ruby-version: 3.0.6 bundler-cache: true - name: Run tests run: bundle exec rake diff --git a/.rubocop.yml b/.rubocop.yml new file mode 100644 index 0000000..d34b4ca --- /dev/null +++ b/.rubocop.yml @@ -0,0 +1,64 @@ +inherit_from: .rubocop_todo.yml + +plugins: + - rubocop-rake + - rubocop-rspec + +AllCops: + TargetRubyVersion: 3.0 + NewCops: enable + Exclude: + - 'vendor/**/*' + - 'spec/fixtures/**/*' + - 'tmp/**/*' + - 'pkg/**/*' + - 'node_modules/**/*' + - 'specs_e2e/**/*' + - 'e2e/**/*' + +# Ensure all files end with a newline +Layout/TrailingEmptyLines: + Enabled: true + EnforcedStyle: final_newline + +# Ensure no trailing whitespace +Layout/TrailingWhitespace: + Enabled: true + +# Line length is configured in .rubocop_todo.yml for existing violations + +# Allow longer blocks in specs and rake tasks +Metrics/BlockLength: + Exclude: + - 'spec/**/*' + - '**/*.rake' + - 'Rakefile' + - '*.gemspec' + +# Allow longer methods in rake tasks +Metrics/MethodLength: + Exclude: + - '**/*.rake' + - 'Rakefile' + +# String literals - configured in .rubocop_todo.yml for gradual adoption + +# Frozen string literal pragma - configured in .rubocop_todo.yml for gradual adoption + +# Documentation +Style/Documentation: + Enabled: false + +# Allow compact module/class definitions +Style/ClassAndModuleChildren: + Enabled: false + +# RSpec specific +RSpec/ExampleLength: + Max: 20 + +RSpec/MultipleExpectations: + Max: 5 + +RSpec/NestedGroups: + Max: 4 diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml new file mode 100644 index 0000000..bcb157e --- /dev/null +++ b/.rubocop_todo.yml @@ -0,0 +1,582 @@ +# This configuration was generated by +# `rubocop --auto-gen-config --no-offense-counts --no-auto-gen-timestamp` +# using RuboCop version 1.81.1. +# The point is for the user to remove these configuration records +# one by one as the offenses are removed from the code base. +# Note that changes in the inspected code, or installation of new +# versions of RuboCop, may require this file to be generated again. + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: Severity. +Gemspec/DeprecatedAttributeAssignment: + Exclude: + - 'cypress-on-rails.gemspec' + +# Configuration parameters: EnforcedStyle, AllowedGems. +# SupportedStyles: Gemfile, gems.rb, gemspec +Gemspec/DevelopmentDependencies: + Exclude: + - 'cypress-on-rails.gemspec' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: TreatCommentsAsGroupSeparators, ConsiderPunctuation. +Gemspec/OrderedDependencies: + Exclude: + - 'cypress-on-rails.gemspec' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: Severity. +Gemspec/RequireMFA: + Exclude: + - 'cypress-on-rails.gemspec' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: leading, trailing +Layout/DotPosition: + Exclude: + - 'spec/cypress_on_rails/simple_rails_factory_spec.rb' + +# This cop supports safe autocorrection (--autocorrect). +Layout/ElseAlignment: + Exclude: + - 'lib/cypress_on_rails/server.rb' + +# This cop supports safe autocorrection (--autocorrect). +Layout/EmptyLineAfterGuardClause: + Exclude: + - 'lib/cypress_on_rails/server.rb' + - 'lib/cypress_on_rails/smart_factory_wrapper.rb' + - 'lib/cypress_on_rails/state_reset_middleware.rb' + +# This cop supports safe autocorrection (--autocorrect). +Layout/EmptyLineAfterMagicComment: + Exclude: + - 'cypress-on-rails.gemspec' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EmptyLineBetweenMethodDefs, EmptyLineBetweenClassDefs, EmptyLineBetweenModuleDefs, DefLikeMacros, AllowAdjacentOneLineDefs, NumberOfEmptyLines. +Layout/EmptyLineBetweenDefs: + Exclude: + - 'lib/cypress_on_rails/configuration.rb' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyleAlignWith, Severity. +# SupportedStylesAlignWith: keyword, variable, start_of_line +Layout/EndAlignment: + Exclude: + - 'lib/cypress_on_rails/server.rb' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: IndentationWidth. +# SupportedStyles: special_inside_parentheses, consistent, align_braces +Layout/FirstHashElementIndentation: + EnforcedStyle: consistent + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: AllowMultipleStyles, EnforcedHashRocketStyle, EnforcedColonStyle, EnforcedLastArgumentHashStyle. +# SupportedHashRocketStyles: key, separator, table +# SupportedColonStyles: key, separator, table +# SupportedLastArgumentHashStyles: always_inspect, always_ignore, ignore_implicit, ignore_explicit +Layout/HashAlignment: + Exclude: + - 'cypress-on-rails.gemspec' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: Width, AllowedPatterns. +Layout/IndentationWidth: + Exclude: + - 'lib/cypress_on_rails/server.rb' + +# This cop supports safe autocorrection (--autocorrect). +Layout/SpaceAfterComma: + Exclude: + - 'lib/cypress_on_rails/command_executor.rb' + - 'lib/cypress_on_rails/simple_rails_factory.rb' + - 'lib/cypress_on_rails/smart_factory_wrapper.rb' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: AllowForAlignment, EnforcedStyleForExponentOperator, EnforcedStyleForRationalLiterals. +# SupportedStylesForExponentOperator: space, no_space +# SupportedStylesForRationalLiterals: space, no_space +Layout/SpaceAroundOperators: + Exclude: + - 'spec/cypress_on_rails/middleware_spec.rb' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBraces. +# SupportedStyles: space, no_space +# SupportedStylesForEmptyBraces: space, no_space +Layout/SpaceBeforeBlockBraces: + Exclude: + - 'lib/cypress_on_rails/smart_factory_wrapper.rb' + - 'spec/cypress_on_rails/simple_rails_factory_spec.rb' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: require_no_space, require_space +Layout/SpaceInLambdaLiteral: + Exclude: + - 'lib/cypress_on_rails/configuration.rb' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBraces, SpaceBeforeBlockParameters. +# SupportedStyles: space, no_space +# SupportedStylesForEmptyBraces: space, no_space +Layout/SpaceInsideBlockBraces: + Exclude: + - 'lib/cypress_on_rails/middleware.rb' + - 'lib/cypress_on_rails/smart_factory_wrapper.rb' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBraces. +# SupportedStyles: space, no_space, compact +# SupportedStylesForEmptyBraces: space, no_space +Layout/SpaceInsideHashLiteralBraces: + Exclude: + - 'lib/cypress_on_rails/middleware.rb' + - 'spec/cypress_on_rails/middleware_spec.rb' + - 'spec/cypress_on_rails/simple_rails_factory_spec.rb' + - 'spec/cypress_on_rails/smart_factory_wrapper_spec.rb' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: space, compact, no_space +Layout/SpaceInsideParens: + Exclude: + - 'spec/cypress_on_rails/simple_rails_factory_spec.rb' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: final_newline, final_blank_line +Layout/TrailingEmptyLines: + Exclude: + - 'Gemfile' + - 'lib/cypress/smart_factory_wrapper.rb' + - 'lib/cypress_on_rails/server.rb' + - 'lib/cypress_on_rails/state_reset_middleware.rb' + - 'lib/tasks/cypress.rake' + - 'rakelib/task_helpers.rb' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: AllowInHeredoc. +Layout/TrailingWhitespace: + Exclude: + - 'lib/cypress_on_rails/configuration.rb' + - 'lib/cypress_on_rails/railtie.rb' + - 'lib/cypress_on_rails/server.rb' + - 'lib/cypress_on_rails/smart_factory_wrapper.rb' + - 'lib/cypress_on_rails/state_reset_middleware.rb' + +# Configuration parameters: AllowedMethods. +# AllowedMethods: enums +Lint/ConstantDefinitionInBlock: + Exclude: + - 'spec/cypress_on_rails/simple_rails_factory_spec.rb' + - 'spec/cypress_on_rails/smart_factory_wrapper_spec.rb' + +# This cop supports unsafe autocorrection (--autocorrect-all). +Lint/InterpolationCheck: + Exclude: + - 'spec/generators/install_generator_spec.rb' + +# Configuration parameters: AllowComments, AllowNil. +Lint/SuppressedException: + Exclude: + - 'lib/generators/cypress_on_rails/templates/spec/e2e/app_commands/log_fail.rb' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: strict, consistent +Lint/SymbolConversion: + Exclude: + - 'lib/cypress_on_rails/vcr/insert_eject_middleware.rb' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: AllowUnusedKeywordArguments, IgnoreEmptyMethods, IgnoreNotImplementedMethods, NotImplementedExceptions. +# NotImplementedExceptions: NotImplementedError +Lint/UnusedMethodArgument: + Exclude: + - 'lib/cypress_on_rails/server.rb' + +# This cop supports safe autocorrection (--autocorrect). +Lint/UselessAssignment: + Exclude: + - 'lib/generators/cypress_on_rails/install_generator.rb' + +Lint/UselessConstantScoping: + Exclude: + - 'lib/cypress_on_rails/middleware.rb' + +# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes. +Metrics/AbcSize: + Max: 51 + +# Configuration parameters: CountComments, CountAsOne. +Metrics/ClassLength: + Max: 200 + +# Configuration parameters: AllowedMethods, AllowedPatterns. +Metrics/CyclomaticComplexity: + Max: 13 + +# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns. +Metrics/MethodLength: + Max: 28 + +# Configuration parameters: CountComments, CountAsOne. +Metrics/ModuleLength: + Max: 138 + +# Configuration parameters: CountKeywordArgs, MaxOptionalParameters. +Metrics/ParameterLists: + Max: 6 + +# Configuration parameters: AllowedMethods, AllowedPatterns. +Metrics/PerceivedComplexity: + Max: 15 + +# Configuration parameters: ExpectMatchingDefinition, CheckDefinitionPathHierarchy, CheckDefinitionPathHierarchyRoots, Regex, IgnoreExecutableScripts, AllowedAcronyms. +# CheckDefinitionPathHierarchyRoots: lib, spec, test, src +# AllowedAcronyms: CLI, DSL, ACL, API, ASCII, CPU, CSS, DNS, EOF, GUID, HTML, HTTP, HTTPS, ID, IP, JSON, LHS, QPS, RAM, RHS, RPC, SLA, SMTP, SQL, SSH, TCP, TLS, TTL, UDP, UI, UID, UUID, URI, URL, UTF8, VM, XML, XMPP, XSRF, XSS +Naming/FileName: + Exclude: + - 'Rakefile.rb' + - 'lib/cypress-on-rails.rb' + +# Configuration parameters: MinNameLength, AllowNamesEndingInNumbers, AllowedNames, ForbiddenNames. +# AllowedNames: as, at, by, cc, db, id, if, in, io, ip, of, on, os, pp, to +Naming/MethodParameterName: + Exclude: + - 'lib/cypress_on_rails/configuration.rb' + +RSpec/AnyInstance: + Exclude: + - 'spec/generators/install_generator_spec.rb' + +# This cop supports unsafe autocorrection (--autocorrect-all). +RSpec/BeEq: + Exclude: + - 'spec/cypress_on_rails/configuration_spec.rb' + +# Configuration parameters: Prefixes, AllowedPatterns. +# Prefixes: when, with, without +RSpec/ContextWording: + Exclude: + - 'spec/cypress_on_rails/middleware_spec.rb' + - 'spec/cypress_on_rails/smart_factory_wrapper_spec.rb' + +# This cop supports unsafe autocorrection (--autocorrect-all). +# Configuration parameters: SkipBlocks, EnforcedStyle, OnlyStaticConstants. +# SupportedStyles: described_class, explicit +RSpec/DescribedClass: + Exclude: + - 'spec/cypress_on_rails/railtie_spec.rb' + - 'spec/cypress_on_rails/simple_rails_factory_spec.rb' + - 'spec/generators/install_generator_spec.rb' + +# This cop supports safe autocorrection (--autocorrect). +RSpec/EmptyLineAfterFinalLet: + Exclude: + - 'spec/cypress_on_rails/command_executor_spec.rb' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: CustomTransform, IgnoredWords, DisallowedExamples. +# DisallowedExamples: works +RSpec/ExampleWording: + Exclude: + - 'spec/cypress_on_rails/smart_factory_wrapper_spec.rb' + +# This cop supports safe autocorrection (--autocorrect). +RSpec/ExcessiveDocstringSpacing: + Exclude: + - 'spec/cypress_on_rails/smart_factory_wrapper_spec.rb' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: implicit, each, example +RSpec/HookArgument: + Exclude: + - 'spec/spec_helper.rb' + +# This cop supports safe autocorrection (--autocorrect). +RSpec/LeadingSubject: + Exclude: + - 'spec/cypress_on_rails/command_executor_spec.rb' + - 'spec/cypress_on_rails/middleware_spec.rb' + - 'spec/cypress_on_rails/smart_factory_wrapper_spec.rb' + +RSpec/LeakyConstantDeclaration: + Exclude: + - 'spec/cypress_on_rails/simple_rails_factory_spec.rb' + - 'spec/cypress_on_rails/smart_factory_wrapper_spec.rb' + +# Configuration parameters: Max. +RSpec/MultipleExpectations: + Exclude: + - 'spec/cypress_on_rails/configuration_spec.rb' + - 'spec/generators/install_generator_spec.rb' + +# Configuration parameters: AllowSubject. +RSpec/MultipleMemoizedHelpers: + Max: 7 + +# Configuration parameters: EnforcedStyle, IgnoreSharedExamples. +# SupportedStyles: always, named_only +RSpec/NamedSubject: + Exclude: + - 'spec/cypress_on_rails/middleware_spec.rb' + - 'spec/cypress_on_rails/simple_rails_factory_spec.rb' + - 'spec/cypress_on_rails/smart_factory_wrapper_spec.rb' + - 'spec/cypress_on_rails/vcr/insert_eject_middleware_spec.rb' + - 'spec/cypress_on_rails/vcr/use_cassette_middleware_spec.rb' + +# Configuration parameters: AllowedPatterns. +# AllowedPatterns: ^expect_, ^assert_ +RSpec/NoExpectationExample: + Exclude: + - 'spec/cypress_on_rails/railtie_spec.rb' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: not_to, to_not +RSpec/NotToNot: + Exclude: + - 'spec/cypress_on_rails/configuration_spec.rb' + - 'spec/cypress_on_rails/middleware_spec.rb' + +# This cop supports safe autocorrection (--autocorrect). +RSpec/ScatteredLet: + Exclude: + - 'spec/cypress_on_rails/middleware_spec.rb' + - 'spec/cypress_on_rails/vcr/insert_eject_middleware_spec.rb' + - 'spec/cypress_on_rails/vcr/use_cassette_middleware_spec.rb' + +# Configuration parameters: CustomTransform, IgnoreMethods, IgnoreMetadata. +RSpec/SpecFilePathFormat: + Exclude: + - '**/spec/routing/**/*' + - 'spec/generators/install_generator_spec.rb' + +# Configuration parameters: IgnoreNameless, IgnoreSymbolicNames. +RSpec/VerifiedDoubles: + Exclude: + - 'spec/cypress_on_rails/railtie_spec.rb' + - 'spec/cypress_on_rails/vcr/use_cassette_middleware_spec.rb' + +Security/Eval: + Exclude: + - 'lib/cypress_on_rails/command_executor.rb' + - 'lib/generators/cypress_on_rails/templates/spec/e2e/app_commands/eval.rb' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: separated, grouped +Style/AccessorGrouping: + Exclude: + - 'lib/cypress_on_rails/configuration.rb' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: prefer_alias, prefer_alias_method +Style/Alias: + Exclude: + - 'lib/cypress_on_rails/configuration.rb' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle, SingleLineConditionsOnly, IncludeTernaryExpressions. +# SupportedStyles: assign_to_condition, assign_inside_condition +Style/ConditionalAssignment: + Exclude: + - 'lib/cypress_on_rails/middleware.rb' + - 'lib/cypress_on_rails/smart_factory_wrapper.rb' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: compact, expanded +Style/EmptyMethod: + Exclude: + - 'spec/cypress_on_rails/railtie_spec.rb' + - 'spec/cypress_on_rails/simple_rails_factory_spec.rb' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: trailing_conditional, ternary +Style/EmptyStringInsideInterpolation: + Exclude: + - 'rakelib/release.rake' + +# This cop supports safe autocorrection (--autocorrect). +Style/Encoding: + Exclude: + - 'cypress-on-rails.gemspec' + +# This cop supports safe autocorrection (--autocorrect). +Style/ExpandPathArguments: + Exclude: + - 'cypress-on-rails.gemspec' + - 'lib/generators/cypress_on_rails/install_generator.rb' + +# This cop supports safe autocorrection (--autocorrect). +Style/ExplicitBlockArgument: + Exclude: + - 'lib/cypress_on_rails/configuration.rb' + +# This cop supports unsafe autocorrection (--autocorrect-all). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: always, always_true, never +Style/FrozenStringLiteralComment: + Enabled: false + +# This cop supports unsafe autocorrection (--autocorrect-all). +Style/GlobalStdStream: + Exclude: + - 'lib/cypress_on_rails/configuration.rb' + - 'spec/cypress_on_rails/configuration_spec.rb' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: MinBodyLength, AllowConsecutiveConditionals. +Style/GuardClause: + Exclude: + - 'lib/cypress_on_rails/server.rb' + - 'lib/generators/cypress_on_rails/install_generator.rb' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle, EnforcedShorthandSyntax, UseHashRocketsWithSymbolValues, PreferHashRocketsForNonAlnumEndingSymbols. +# SupportedStyles: ruby19, hash_rockets, no_mixed_keys, ruby19_no_mixed_keys +# SupportedShorthandSyntax: always, never, either, consistent, either_consistent +Style/HashSyntax: + Exclude: + - 'lib/tasks/cypress.rake' + +# This cop supports safe autocorrection (--autocorrect). +Style/IfUnlessModifier: + Exclude: + - 'lib/cypress_on_rails/server.rb' + - 'rakelib/release.rake' + +# This cop supports unsafe autocorrection (--autocorrect-all). +Style/MapIntoArray: + Exclude: + - 'spec/generators/install_generator_spec.rb' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: AllowMethodComparison, ComparisonsThreshold. +Style/MultipleComparison: + Exclude: + - 'lib/cypress_on_rails/state_reset_middleware.rb' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: PreferredDelimiters. +Style/PercentLiteralDelimiters: + Exclude: + - 'spec/cypress_on_rails/command_executor_spec.rb' + - 'spec/cypress_on_rails/middleware_spec.rb' + - 'spec/cypress_on_rails/smart_factory_wrapper_spec.rb' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: same_as_string_literals, single_quotes, double_quotes +Style/QuotedSymbols: + Exclude: + - 'spec/cypress_on_rails/smart_factory_wrapper_spec.rb' + +# This cop supports safe autocorrection (--autocorrect). +Style/RedundantBegin: + Exclude: + - 'lib/generators/cypress_on_rails/templates/spec/e2e/app_commands/log_fail.rb' + +# This cop supports safe autocorrection (--autocorrect). +Style/RedundantCurrentDirectoryInPath: + Exclude: + - 'lib/cypress-on-rails.rb' + +# This cop supports unsafe autocorrection (--autocorrect-all). +Style/RedundantInterpolation: + Exclude: + - 'lib/generators/cypress_on_rails/templates/spec/e2e/app_commands/factory_bot.rb' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: AllowMultipleReturnValues. +Style/RedundantReturn: + Exclude: + - 'spec/cypress_on_rails/configuration_spec.rb' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle, AllowInnerSlashes. +# SupportedStyles: slashes, percent_r, mixed +Style/RegexpLiteral: + Exclude: + - 'rakelib/update_changelog.rake' + +# This cop supports safe autocorrection (--autocorrect). +Style/RescueModifier: + Exclude: + - 'lib/cypress_on_rails/server.rb' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: implicit, explicit +Style/RescueStandardError: + Exclude: + - 'lib/cypress_on_rails/command_executor.rb' + - 'lib/cypress_on_rails/middleware.rb' + - 'lib/generators/cypress_on_rails/templates/spec/e2e/app_commands/factory_bot.rb' + - 'lib/generators/cypress_on_rails/templates/spec/e2e/app_commands/log_fail.rb' + +# This cop supports unsafe autocorrection (--autocorrect-all). +# Configuration parameters: ConvertCodeThatCanStartToReturnNil, AllowedMethods, MaxChainLength. +# AllowedMethods: present?, blank?, presence, try, try! +Style/SafeNavigation: + Exclude: + - 'lib/cypress_on_rails/server.rb' + - 'lib/cypress_on_rails/state_reset_middleware.rb' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: only_raise, only_fail, semantic +Style/SignalException: + Exclude: + - 'lib/generators/cypress_on_rails/install_generator.rb' + +# This cop supports unsafe autocorrection (--autocorrect-all). +Style/SlicingWithRange: + Exclude: + - 'rakelib/update_changelog.rake' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: AllowModifier. +Style/SoleNestedConditional: + Exclude: + - 'lib/cypress_on_rails/server.rb' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle, ConsistentQuotesInMultiline. +# SupportedStyles: single_quotes, double_quotes +Style/StringLiterals: + Enabled: false + +# This cop supports unsafe autocorrection (--autocorrect-all). +# Configuration parameters: AllowMethodsWithArguments, AllowedMethods, AllowedPatterns, AllowComments. +# AllowedMethods: define_method +Style/SymbolProc: + Exclude: + - 'spec/cypress_on_rails/configuration_spec.rb' + +# This cop supports safe autocorrection (--autocorrect). +Style/UnlessElse: + Exclude: + - 'rakelib/release.rake' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: WordRegex. +# SupportedStyles: percent, brackets +Style/WordArray: + EnforcedStyle: percent + MinSize: 4 + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: AllowHeredoc, AllowURI, AllowQualifiedName, URISchemes, IgnoreCopDirectives, AllowedPatterns, SplitStrings. +# URISchemes: http, https +Layout/LineLength: + Max: 147 diff --git a/Rakefile b/Rakefile index 00e60ee..c3581f3 100644 --- a/Rakefile +++ b/Rakefile @@ -3,4 +3,7 @@ RSpec::Core::RakeTask.new(:spec) do |t| t.pattern = 'spec/cypress_on_rails/*_spec.rb' end -task default: :spec \ No newline at end of file +desc 'Run all CI checks (specs, linting, newlines)' +task ci: %i[spec lint check_newlines] + +task default: :spec diff --git a/bin/install-hooks b/bin/install-hooks new file mode 100755 index 0000000..8ad78a3 --- /dev/null +++ b/bin/install-hooks @@ -0,0 +1,94 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +require 'fileutils' + +# Find the git directory (could be .git file in worktree or .git directory) +git_dir = nil +current = File.expand_path('..', __dir__) + +while current != '/' + git_path = File.join(current, '.git') + if File.exist?(git_path) + if File.file?(git_path) + # It's a worktree, read the actual git dir + git_dir_line = File.read(git_path).lines.find { |l| l.start_with?('gitdir:') } + if git_dir_line + relative_path = git_dir_line.sub('gitdir:', '').strip + git_dir = File.expand_path(relative_path, current) + break + end + else + git_dir = git_path + break + end + end + current = File.dirname(current) +end + +unless git_dir && File.exist?(git_dir) + puts '❌ Error: Not in a git repository. Please run this from the project root.' + exit 1 +end + +hooks_dir = File.join(git_dir, 'hooks') +pre_commit_hook = File.join(hooks_dir, 'pre-commit') + +# Create pre-commit hook content +hook_content = <<~HOOK + #!/usr/bin/env bash + # Pre-commit hook to run linters and check for newlines + + # Check for files missing newlines + echo "Checking for files missing newlines..." + bundle exec rake check_newlines + if [ $? -ne 0 ]; then + echo "❌ Some files are missing final newlines. Run 'bundle exec rake fix_newlines' to fix." + exit 1 + fi + + # Run RuboCop on staged Ruby files + echo "Running RuboCop on staged files..." + files=$(git diff --cached --name-only --diff-filter=ACM | grep -E '\\.(rb|rake)$' || true) + if [ -n "$files" ]; then + # Use printf to handle filenames with spaces and special characters safely + printf '%s\\n' "$files" | xargs bundle exec rubocop + if [ $? -ne 0 ]; then + echo "❌ RuboCop failed. Fix issues or run 'bundle exec rake lint:fix'" + exit 1 + fi + fi + + echo "✅ All checks passed!" +HOOK + +# Create hooks directory if it doesn't exist +begin + FileUtils.mkdir_p(hooks_dir) +rescue SystemCallError => e + puts "❌ Error: Failed to create hooks directory: #{e.message}" + exit 1 +end + +# Write the pre-commit hook +begin + File.write(pre_commit_hook, hook_content) +rescue SystemCallError => e + puts "❌ Error: Failed to write pre-commit hook: #{e.message}" + exit 1 +end + +# Make it executable +begin + File.chmod(0o755, pre_commit_hook) +rescue SystemCallError => e + puts "❌ Error: Failed to make hook executable: #{e.message}" + exit 1 +end + +puts '✅ Pre-commit hook installed successfully!' +puts 'The hook will:' +puts ' - Check that all files end with a newline' +puts ' - Run RuboCop on staged Ruby files' +puts '' +puts 'To skip the hook temporarily, use: git commit --no-verify' diff --git a/cypress-on-rails.gemspec b/cypress-on-rails.gemspec index 472b296..a66770e 100644 --- a/cypress-on-rails.gemspec +++ b/cypress-on-rails.gemspec @@ -22,11 +22,17 @@ Gem::Specification.new do |s| s.add_development_dependency 'factory_bot', '!= 6.4.5' s.add_development_dependency 'vcr' s.add_development_dependency 'gem-release' + s.add_development_dependency 'rubocop', '~> 1.81' + s.add_development_dependency 'rubocop-rake', '~> 0.7' + s.add_development_dependency 'rubocop-rspec', '~> 3.7' + + s.required_ruby_version = '>= 3.0.0' + s.metadata = { "bug_tracker_uri" => "https://github.com/shakacode/cypress-on-rails/issues", "changelog_uri" => "https://github.com/shakacode/cypress-on-rails/blob/master/CHANGELOG.md", "documentation_uri" => "https://github.com/shakacode/cypress-on-rails/blob/master/README.md", "homepage_uri" => "http://github.com/shakacode/cypress-on-rails", "source_code_uri" => "http://github.com/shakacode/cypress-on-rails" -} + } end diff --git a/rakelib/lint.rake b/rakelib/lint.rake new file mode 100644 index 0000000..193dda1 --- /dev/null +++ b/rakelib/lint.rake @@ -0,0 +1,96 @@ +# frozen_string_literal: true + +desc 'Run RuboCop' +task :rubocop do + sh 'bundle exec rubocop' +end + +desc 'Run RuboCop with autocorrect' +task 'rubocop:autocorrect' do + sh 'bundle exec rubocop -A' +end + +desc 'Run all linters' +task lint: :rubocop + +desc 'Auto-fix all linting issues' +task 'lint:fix' => 'rubocop:autocorrect' + +# Helper method to check if file is likely binary +def binary_file?(filepath) + return false unless File.exist?(filepath) + + # Read first 8192 bytes to check for binary content + File.open(filepath, 'rb') do |file| + chunk = file.read(8192) || '' + # File is binary if it contains null bytes or has high ratio of non-printable chars + return true if chunk.include?("\x00") + + # Check for high ratio of non-printable characters + non_printable = chunk.count("\x01-\x08\x0B\x0C\x0E-\x1F\x7F-\xFF") + non_printable.to_f / chunk.size > 0.3 + end +rescue StandardError + # If we can't read the file, assume it's not something we should check + true +end + +# Maximum file size to check (10MB) +MAX_FILE_SIZE = 10 * 1024 * 1024 + +desc 'Ensure all files end with newline' +task :check_newlines do + files_without_newline = [] + + # Define excluded directories (matching RuboCop config) + excluded_dirs = %w[vendor/ node_modules/ .git/ pkg/ tmp/ coverage/ specs_e2e/ e2e/ spec/fixtures/] + + # Get all relevant files and filter out excluded directories more efficiently + Dir.glob('**/*.{rb,rake,yml,yaml,md,gemspec,ru,erb,js,json}') + .reject { |f| excluded_dirs.any? { |dir| f.start_with?(dir) } } + .select { |f| File.file?(f) && File.size(f) < MAX_FILE_SIZE && !binary_file?(f) } + .each do |file| + # Read only the last few bytes to check for newline + File.open(file, 'rb') do |f| + f.seek([f.size - 2, 0].max) + tail = f.read + files_without_newline << file unless tail.nil? || tail.empty? || tail.end_with?("\n") + end + end + + if files_without_newline.any? + puts 'Files missing final newline:' + files_without_newline.each { |f| puts " #{f}" } + exit 1 + else + puts '✓ All files end with newline' + end +end + +desc 'Fix files missing final newline' +task :fix_newlines do + fixed_files = [] + + # Define excluded directories (matching RuboCop config) + excluded_dirs = %w[vendor/ node_modules/ .git/ pkg/ tmp/ coverage/ specs_e2e/ e2e/ spec/fixtures/] + + # Get all relevant files and filter out excluded directories more efficiently + Dir.glob('**/*.{rb,rake,yml,yaml,md,gemspec,ru,erb,js,json}') + .reject { |f| excluded_dirs.any? { |dir| f.start_with?(dir) } } + .select { |f| File.file?(f) && File.size(f) < MAX_FILE_SIZE && !binary_file?(f) } + .each do |file| + # Read file to check if it needs a newline + content = File.read(file) + unless content.empty? || content.end_with?("\n") + File.write(file, "#{content}\n") + fixed_files << file + end + end + + if fixed_files.any? + puts "Fixed #{fixed_files.length} files:" + fixed_files.each { |f| puts " #{f}" } + else + puts '✓ All files already end with newline' + end +end