diff --git a/.github/actions/ci/action.yml b/.github/actions/ci/action.yml index 4293ff7..94ab372 100644 --- a/.github/actions/ci/action.yml +++ b/.github/actions/ci/action.yml @@ -1,8 +1,11 @@ name: CI Workflow -description: 'Shared CI workflow.' +description: "Shared CI workflow." inputs: ruby-version: - description: 'The version of ruby to setup and run' + description: "The version of ruby to setup and run" + required: true + token: + description: "GH token used to fetch the SDK test harness" required: true runs: @@ -11,11 +14,10 @@ runs: - uses: ruby/setup-ruby@v1 with: ruby-version: ${{ inputs.ruby-version }} - bundler: 2.2.10 - name: Install dependencies shell: bash - run: bundle _2.2.10_ install + run: bundle install - name: Skip end to end tests for jruby if: ${{ startsWith(inputs.ruby-version, 'jruby') }} @@ -24,9 +26,28 @@ runs: - name: Run tests shell: bash - run: bundle _2.2.10_ exec rspec spec + run: bundle exec rspec spec + + - name: Run RuboCop + if: ${{ !startsWith(inputs.ruby-version, 'jruby') }} + shell: bash + run: bundle exec rubocop --parallel + + - name: Build contract tests + if: ${{ !startsWith(inputs.ruby-version, 'jruby') }} + shell: bash + run: make build-contract-tests - - name: Run contract tests + - name: Start contract test service if: ${{ !startsWith(inputs.ruby-version, 'jruby') }} shell: bash - run: make contract-tests + run: make start-contract-test-service-bg + + - uses: launchdarkly/gh-actions/actions/contract-tests@contract-tests-v1.1.0 + if: ${{ !startsWith(inputs.ruby-version, 'jruby') }} + with: + test_service_port: 8000 + token: ${{ inputs.token }} + repo: sse-contract-tests + branch: main + version: v1 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0d33d58..80bf00a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,13 +1,13 @@ name: Run CI on: push: - branches: [ main ] + branches: [main] paths-ignore: - - '**.md' # Do not need to run CI for markdown changes. + - "**.md" # Do not need to run CI for markdown changes. pull_request: - branches: [ main ] + branches: [main] paths-ignore: - - '**.md' + - "**.md" jobs: build: @@ -17,14 +17,11 @@ jobs: fail-fast: false matrix: ruby-version: - - '2.5' - - '2.6' - - '2.7' - - '3.0' - - '3.1' - - '3.2' - - jruby-9.3 + - "3.2" + - "3.3" + - "3.4" - jruby-9.4 + - jruby-10.0 steps: - uses: actions/checkout@v4 @@ -34,3 +31,4 @@ jobs: - uses: ./.github/actions/ci with: ruby-version: ${{ matrix.ruby-version }} + token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/manual-publish.yml b/.github/workflows/manual-publish.yml index 770d4c5..9adcc89 100644 --- a/.github/workflows/manual-publish.yml +++ b/.github/workflows/manual-publish.yml @@ -3,7 +3,7 @@ on: workflow_dispatch: inputs: dry_run: - description: 'Is this a dry run. If so no package will be published.' + description: "Is this a dry run. If so no package will be published." type: boolean required: true @@ -18,16 +18,17 @@ jobs: - uses: actions/checkout@v4 - uses: launchdarkly/gh-actions/actions/release-secrets@release-secrets-v1.2.0 - name: 'Get rubygems API key' + name: "Get rubygems API key" with: aws_assume_role: ${{ vars.AWS_ROLE_ARN }} - ssm_parameter_pairs: '/production/common/releasing/rubygems/api_key = GEM_HOST_API_KEY' + ssm_parameter_pairs: "/production/common/releasing/rubygems/api_key = GEM_HOST_API_KEY" - id: build-and-test name: Build and Test uses: ./.github/actions/ci with: - ruby-version: '3.0' + ruby-version: "3.2" + token: ${{ secrets.GITHUB_TOKEN }} - id: publish name: Publish Package diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml index d55f8fa..8aec81b 100644 --- a/.github/workflows/release-please.yml +++ b/.github/workflows/release-please.yml @@ -23,15 +23,16 @@ jobs: - uses: launchdarkly/gh-actions/actions/release-secrets@release-secrets-v1.2.0 if: ${{ steps.release.outputs.releases_created == 'true' }} - name: 'Get rubygems API key' + name: "Get rubygems API key" with: aws_assume_role: ${{ vars.AWS_ROLE_ARN }} - ssm_parameter_pairs: '/production/common/releasing/rubygems/api_key = GEM_HOST_API_KEY' + ssm_parameter_pairs: "/production/common/releasing/rubygems/api_key = GEM_HOST_API_KEY" - uses: ./.github/actions/ci if: ${{ steps.release.outputs.releases_created == 'true' }} with: - ruby-version: '3.0' + ruby-version: "3.2" + token: ${{ secrets.GITHUB_TOKEN }} - uses: ./.github/actions/publish if: ${{ steps.release.outputs.releases_created == 'true' }} diff --git a/.rubocop.yml b/.rubocop.yml new file mode 100644 index 0000000..43d65d5 --- /dev/null +++ b/.rubocop.yml @@ -0,0 +1,889 @@ +require: + - rubocop-performance + +AllCops: + TargetRubyVersion: 3.1 + Include: + - lib/**/*.rb + - spec/**/*.rb + - contract-tests/**/*.rb + NewCops: disable + +Naming/AccessorMethodName: + Description: Check the naming of accessor methods for get_/set_. + Enabled: false + +Style/AccessModifierDeclarations: + Description: "Access modifiers should be declared to apply to a group of methods or inline before each method, depending on configuration." + StyleGuide: "https://github.com/bbatsov/ruby-style-guide#alias-method" + Enabled: false + +Style/Alias: + Description: "Use alias_method instead of alias." + StyleGuide: "https://github.com/bbatsov/ruby-style-guide#alias-method" + Enabled: false + +Style/ArrayJoin: + Description: "Use Array#join instead of Array#*." + StyleGuide: "https://github.com/bbatsov/ruby-style-guide#array-join" + Enabled: false + +Style/AsciiComments: + Description: "Use only ascii symbols in comments." + StyleGuide: "https://github.com/bbatsov/ruby-style-guide#english-comments" + Enabled: false + +Naming/AsciiIdentifiers: + Description: "Use only ascii symbols in identifiers." + StyleGuide: "https://github.com/bbatsov/ruby-style-guide#english-identifiers" + Enabled: false + +Naming/VariableName: + Description: "Makes sure that all variables use the configured style, snake_case or camelCase, for their names." + Enabled: false + +Style/Attr: + Description: "Checks for uses of Module#attr." + StyleGuide: "https://github.com/bbatsov/ruby-style-guide#attr" + Enabled: false + +Metrics/AbcSize: + Description: "Checks that the ABC size of methods is not higher than the configured maximum." + Enabled: false + +Metrics/BlockLength: + Description: "Checks if the length of a block exceeds some maximum value." + Enabled: false + +Metrics/BlockNesting: + Description: "Avoid excessive block nesting" + StyleGuide: "https://github.com/bbatsov/ruby-style-guide#three-is-the-number-thou-shalt-count" + Enabled: false + +Style/CaseEquality: + Description: "Avoid explicit use of the case equality operator(===)." + StyleGuide: "https://github.com/bbatsov/ruby-style-guide#no-case-equality" + Enabled: false + +Style/CharacterLiteral: + Description: "Checks for uses of character literals." + StyleGuide: "https://github.com/bbatsov/ruby-style-guide#no-character-literals" + Enabled: false + +Style/ClassAndModuleChildren: + Description: "Checks style of children classes and modules." + Enabled: true + EnforcedStyle: nested + +Metrics/ClassLength: + Description: "Avoid classes longer than 100 lines of code." + Enabled: false + +Metrics/ModuleLength: + Description: "Avoid modules longer than 100 lines of code." + Enabled: false + +Style/ClassVars: + Description: "Avoid the use of class variables." + StyleGuide: "https://github.com/bbatsov/ruby-style-guide#no-class-vars" + Enabled: false + +Style/CollectionMethods: + Enabled: true + PreferredMethods: + find: detect + inject: reduce + collect: map + find_all: select + +Style/ColonMethodCall: + Description: "Do not use :: for method call." + StyleGuide: "https://github.com/bbatsov/ruby-style-guide#double-colons" + Enabled: false + +Style/CommentAnnotation: + Description: >- + Checks formatting of special comments + (TODO, FIXME, OPTIMIZE, HACK, REVIEW). + StyleGuide: "https://github.com/bbatsov/ruby-style-guide#annotate-keywords" + Enabled: false + +Metrics/CyclomaticComplexity: + Description: >- + A complexity metric that is strongly correlated to the number + of test cases needed to validate a method. + Enabled: false + +Style/PreferredHashMethods: + Description: "Checks for use of deprecated Hash methods." + StyleGuide: "https://github.com/bbatsov/ruby-style-guide#hash-key" + Enabled: false + +Style/Documentation: + Description: "Document classes and non-namespace modules." + Enabled: false + +Style/DoubleNegation: + Description: "Checks for uses of double negation (!!)." + StyleGuide: "https://github.com/bbatsov/ruby-style-guide#no-bang-bang" + Enabled: false + +Style/EachWithObject: + Description: "Prefer `each_with_object` over `inject` or `reduce`." + Enabled: false + +Style/EmptyLiteral: + Description: "Prefer literals to Array.new/Hash.new/String.new." + StyleGuide: "https://github.com/bbatsov/ruby-style-guide#literal-array-hash" + Enabled: false + +# Checks whether the source file has a utf-8 encoding comment or not +# AutoCorrectEncodingComment must match the regex +# /#.*coding\s?[:=]\s?(?:UTF|utf)-8/ +Style/Encoding: + Enabled: false + +Style/EvenOdd: + Description: "Favor the use of Fixnum#even? && Fixnum#odd?" + StyleGuide: "https://github.com/bbatsov/ruby-style-guide#predicate-methods" + Enabled: false + +Naming/FileName: + Description: "Use snake_case for source file names." + StyleGuide: "https://github.com/bbatsov/ruby-style-guide#snake-case-files" + Enabled: false + +Lint/FlipFlop: + Description: "Checks for flip flops" + StyleGuide: "https://github.com/bbatsov/ruby-style-guide#no-flip-flops" + Enabled: false + +Style/FrozenStringLiteralComment: + Description: "Helps you transition from mutable string literals to frozen string literals." + Enabled: false + +Style/FormatString: + Description: "Enforce the use of Kernel#sprintf, Kernel#format or String#%." + StyleGuide: "https://github.com/bbatsov/ruby-style-guide#sprintf" + Enabled: false + +Style/GlobalVars: + Description: "Do not introduce global variables." + StyleGuide: "https://github.com/bbatsov/ruby-style-guide#instance-vars" + Reference: "https://www.zenspider.com/ruby/quickref.html" + Enabled: false + +Style/GuardClause: + Description: "Check for conditionals that can be replaced with guard clauses" + StyleGuide: "https://github.com/bbatsov/ruby-style-guide#no-nested-conditionals" + Enabled: false + +Style/IfUnlessModifier: + Description: >- + Favor modifier if/unless usage when you have a + single-line body. + StyleGuide: "https://github.com/bbatsov/ruby-style-guide#if-as-a-modifier" + Enabled: false + +Style/IfWithSemicolon: + Description: "Do not use if x; .... Use the ternary operator instead." + StyleGuide: "https://github.com/bbatsov/ruby-style-guide#no-semicolon-ifs" + Enabled: false + +Style/InlineComment: + Description: "Avoid inline comments." + Enabled: false + +Style/Lambda: + Description: "Use the new lambda literal syntax for single-line blocks." + StyleGuide: "https://github.com/bbatsov/ruby-style-guide#lambda-multi-line" + Enabled: false + +Style/LambdaCall: + Description: "Use lambda.call(...) instead of lambda.(...)." + StyleGuide: "https://github.com/bbatsov/ruby-style-guide#proc-call" + Enabled: false + +Style/LineEndConcatenation: + Description: >- + Use \ instead of + or << to concatenate two string literals at + line end. + Enabled: false + +Layout/LineLength: + Description: "Limit lines to 150 characters." + StyleGuide: "https://github.com/bbatsov/ruby-style-guide#80-character-limits" + Max: 180 + +Metrics/MethodLength: + Description: "Avoid methods longer than 10 lines of code." + StyleGuide: "https://github.com/bbatsov/ruby-style-guide#short-methods" + Enabled: false + +Style/ModuleFunction: + Description: "Checks for usage of `extend self` in modules." + StyleGuide: "https://github.com/bbatsov/ruby-style-guide#module-function" + Enabled: false + +Style/NegatedIf: + Description: >- + Favor unless over if for negative conditions + (or control flow or). + StyleGuide: "https://github.com/bbatsov/ruby-style-guide#unless-for-negatives" + Enabled: true + +Style/NegatedWhile: + Description: "Favor until over while for negative conditions." + StyleGuide: "https://github.com/bbatsov/ruby-style-guide#until-for-negatives" + Enabled: true + +Style/Next: + Description: "Use `next` to skip iteration instead of a condition at the end." + StyleGuide: "https://github.com/bbatsov/ruby-style-guide#no-nested-conditionals" + Enabled: false + +Style/NilComparison: + Description: "Prefer x.nil? to x == nil." + StyleGuide: "https://github.com/bbatsov/ruby-style-guide#predicate-methods" + Enabled: false + +Style/Not: + Description: "Use ! instead of not." + StyleGuide: "https://github.com/bbatsov/ruby-style-guide#bang-not-not" + Enabled: false + +Style/NumericLiterals: + Description: >- + Add underscores to large numeric literals to improve their + readability. + StyleGuide: "https://github.com/bbatsov/ruby-style-guide#underscores-in-numerics" + Enabled: false + +Style/OneLineConditional: + Description: >- + Favor the ternary operator(?:) over + if/then/else/end constructs. + StyleGuide: "https://github.com/bbatsov/ruby-style-guide#ternary-operator" + Enabled: false + +Naming/BinaryOperatorParameterName: + Description: "When defining binary operators, name the argument other." + StyleGuide: "https://github.com/bbatsov/ruby-style-guide#other-arg" + Enabled: false + +Metrics/ParameterLists: + Description: "Avoid parameter lists longer than three or four parameters." + StyleGuide: "https://github.com/bbatsov/ruby-style-guide#too-many-params" + Enabled: false + +Metrics/PerceivedComplexity: + Enabled: false + +Style/PercentLiteralDelimiters: + Description: "Use `%`-literal delimiters consistently" + StyleGuide: "https://github.com/bbatsov/ruby-style-guide#percent-literal-braces" + Enabled: false + +Style/PerlBackrefs: + Description: "Avoid Perl-style regex back references." + StyleGuide: "https://github.com/bbatsov/ruby-style-guide#no-perl-regexp-last-matchers" + Enabled: false + +Naming/PredicateName: + Description: "Check the names of predicate methods." + StyleGuide: "https://github.com/bbatsov/ruby-style-guide#bool-methods-qmark" + ForbiddenPrefixes: + - is_ + Exclude: + - spec/**/* + +Style/Proc: + Description: "Use proc instead of Proc.new." + StyleGuide: "https://github.com/bbatsov/ruby-style-guide#proc" + Enabled: false + +Style/RaiseArgs: + Description: "Checks the arguments passed to raise/fail." + StyleGuide: "https://github.com/bbatsov/ruby-style-guide#exception-class-messages" + Enabled: false + +Style/RegexpLiteral: + Description: "Use / or %r around regular expressions." + StyleGuide: "https://github.com/bbatsov/ruby-style-guide#percent-r" + Enabled: false + +Style/SelfAssignment: + Description: >- + Checks for places where self-assignment shorthand should have + been used. + StyleGuide: "https://github.com/bbatsov/ruby-style-guide#self-assignment" + Enabled: false + +Style/SingleLineBlockParams: + Description: "Enforces the names of some block params." + StyleGuide: "https://github.com/bbatsov/ruby-style-guide#reduce-blocks" + Enabled: false + +Style/SingleLineMethods: + Description: "Avoid single-line methods." + StyleGuide: "https://github.com/bbatsov/ruby-style-guide#no-single-line-methods" + Enabled: false + +Style/SignalException: + Description: "Checks for proper usage of fail and raise." + StyleGuide: "https://github.com/bbatsov/ruby-style-guide#fail-method" + Enabled: false + +Style/SpecialGlobalVars: + Description: "Avoid Perl-style global variables." + StyleGuide: "https://github.com/bbatsov/ruby-style-guide#no-cryptic-perlisms" + Enabled: false + +Style/StringLiterals: + Description: "Checks if uses of quotes match the configured preference." + StyleGuide: "https://github.com/bbatsov/ruby-style-guide#consistent-string-literals" + EnforcedStyle: double_quotes + Enabled: false + +Style/TrailingCommaInArguments: + Description: "Checks for trailing comma in argument lists." + StyleGuide: "#no-trailing-params-comma" + Enabled: true + +Style/TrailingCommaInArrayLiteral: + Description: "Checks for trailing comma in array and hash literals." + EnforcedStyleForMultiline: comma + +Style/TrailingCommaInHashLiteral: + Description: "Checks for trailing comma in array and hash literals." + EnforcedStyleForMultiline: comma + +Style/TrivialAccessors: + Description: "Prefer attr_* methods to trivial readers/writers." + StyleGuide: "https://github.com/bbatsov/ruby-style-guide#attr_family" + Enabled: false + +Style/VariableInterpolation: + Description: >- + Don't interpolate global, instance and class variables + directly in strings. + StyleGuide: "https://github.com/bbatsov/ruby-style-guide#curlies-interpolate" + Enabled: false + +Style/WhenThen: + Description: "Use when x then ... for one-line cases." + StyleGuide: "https://github.com/bbatsov/ruby-style-guide#one-line-cases" + Enabled: false + +Style/WhileUntilModifier: + Description: >- + Favor modifier while/until usage when you have a + single-line body. + StyleGuide: "https://github.com/bbatsov/ruby-style-guide#while-as-a-modifier" + Enabled: false + +Style/WordArray: + Description: "Use %w or %W for arrays of words." + StyleGuide: "https://github.com/bbatsov/ruby-style-guide#percent-w" + Enabled: false + +# Layout +Layout/DotPosition: + Description: "Checks the position of the dot in multi-line method calls." + StyleGuide: "https://github.com/bbatsov/ruby-style-guide#consistent-multi-line-chains" + EnforcedStyle: leading + +Layout/ExtraSpacing: + Description: "Do not use unnecessary spacing." + Enabled: true + AllowBeforeTrailingComments: true + +Layout/MultilineOperationIndentation: + Description: >- + Checks indentation of binary operations that span more than + one line. + Enabled: true + EnforcedStyle: indented + +Layout/InitialIndentation: + Description: >- + Checks the indentation of the first non-blank non-comment line in a file. + Enabled: false + +Layout/SpaceInsideArrayLiteralBrackets: + Description: "Checks that brackets used for array literals have or don't have surrounding space depending on configuration." + Enabled: false + +Layout/TrailingWhitespace: + Description: "Ensures all trailing whitespace has been removed" + Enabled: true + +# Lint + +Lint/AmbiguousOperator: + Description: >- + Checks for ambiguous operators in the first argument of a + method invocation without parentheses. + StyleGuide: "https://github.com/bbatsov/ruby-style-guide#parens-as-args" + Enabled: false + +Lint/AmbiguousRegexpLiteral: + Description: >- + Checks for ambiguous regexp literals in the first argument of + a method invocation without parenthesis. + Enabled: false + +Lint/AssignmentInCondition: + Description: "Don't use assignment in conditions." + StyleGuide: "https://github.com/bbatsov/ruby-style-guide#safe-assignment-in-condition" + Enabled: false + +Lint/CircularArgumentReference: + Description: "Don't refer to the keyword argument in the default value." + Enabled: false + +Layout/ConditionPosition: + Description: >- + Checks for condition placed in a confusing position relative to + the keyword. + StyleGuide: "https://github.com/bbatsov/ruby-style-guide#same-line-condition" + Enabled: false + +Lint/DeprecatedClassMethods: + Description: "Check for deprecated class method calls." + Enabled: false + +Lint/DuplicateHashKey: + Description: "Check for duplicate keys in hash literals." + Enabled: false + +Lint/EachWithObjectArgument: + Description: "Check for immutable argument given to each_with_object." + Enabled: false + +Lint/ElseLayout: + Description: "Check for odd code arrangement in an else block." + Enabled: false + +Lint/FormatParameterMismatch: + Description: "The number of parameters to format/sprint must match the fields." + Enabled: false + +Lint/SuppressedException: + Description: "Don't suppress exception." + StyleGuide: "https://github.com/bbatsov/ruby-style-guide#dont-hide-exceptions" + Enabled: false + +Lint/LiteralAsCondition: + Description: "Checks of literals used in conditions." + Enabled: false + +Lint/LiteralInInterpolation: + Description: "Checks for literals used in interpolation." + Enabled: false + +Lint/Loop: + Description: >- + Use Kernel#loop with break rather than begin/end/until or + begin/end/while for post-loop tests. + StyleGuide: "https://github.com/bbatsov/ruby-style-guide#loop-with-break" + Enabled: false + +Lint/NestedMethodDefinition: + Description: "Do not use nested method definitions." + StyleGuide: "https://github.com/bbatsov/ruby-style-guide#no-nested-methods" + Enabled: false + +Lint/NonLocalExitFromIterator: + Description: "Do not use return in iterator to cause non-local exit." + Enabled: false + +Lint/ParenthesesAsGroupedExpression: + Description: >- + Checks for method calls with a space before the opening + parenthesis. + StyleGuide: "https://github.com/bbatsov/ruby-style-guide#parens-no-spaces" + Enabled: false + +Lint/RequireParentheses: + Description: >- + Use parentheses in the method call to avoid confusion + about precedence. + Enabled: false + +Lint/UnderscorePrefixedVariableName: + Description: "Do not use prefix `_` for a variable that is used." + Enabled: false + +Lint/RedundantCopDisableDirective: + Description: >- + Checks for rubocop:disable comments that can be removed. + Note: this cop is not disabled when disabling all cops. + It must be explicitly disabled. + Enabled: false + +Lint/Void: + Description: "Possible use of operator/literal/variable in void context." + Enabled: false + +# Performance + +Performance/CaseWhenSplat: + Description: >- + Place `when` conditions that use splat at the end + of the list of `when` branches. + Enabled: false + +Performance/Count: + Description: >- + Use `count` instead of `select...size`, `reject...size`, + `select...count`, `reject...count`, `select...length`, + and `reject...length`. + Enabled: false + +Performance/Detect: + Description: >- + Use `detect` instead of `select.first`, `find_all.first`, + `select.last`, and `find_all.last`. + Reference: "https://github.com/JuanitoFatas/fast-ruby#enumerabledetect-vs-enumerableselectfirst-code" + Enabled: false + +Performance/FlatMap: + Description: >- + Use `Enumerable#flat_map` + instead of `Enumerable#map...Array#flatten(1)` + or `Enumberable#collect..Array#flatten(1)` + Reference: "https://github.com/JuanitoFatas/fast-ruby#enumerablemaparrayflatten-vs-enumerableflat_map-code" + Enabled: false + +Performance/ReverseEach: + Description: "Use `reverse_each` instead of `reverse.each`." + Reference: "https://github.com/JuanitoFatas/fast-ruby#enumerablereverseeach-vs-enumerablereverse_each-code" + Enabled: false + +Style/Sample: + Description: >- + Use `sample` instead of `shuffle.first`, + `shuffle.last`, and `shuffle[Fixnum]`. + Reference: "https://github.com/JuanitoFatas/fast-ruby#arrayshufflefirst-vs-arraysample-code" + Enabled: false + +Performance/Size: + Description: >- + Use `size` instead of `count` for counting + the number of elements in `Array` and `Hash`. + Reference: "https://github.com/JuanitoFatas/fast-ruby#arraycount-vs-arraysize-code" + Enabled: false + +Performance/StringReplacement: + Description: >- + Use `tr` instead of `gsub` when you are replacing the same + number of characters. Use `delete` instead of `gsub` when + you are deleting characters. + Reference: "https://github.com/JuanitoFatas/fast-ruby#stringgsub-vs-stringtr-code" + Enabled: false + +# Disabled temporarily while we bring code base inline +Layout/ArgumentAlignment: + Enabled: false + +Layout/ArrayAlignment: + Enabled: false + +Layout/BlockEndNewline: + Enabled: false + +Layout/CaseIndentation: + Enabled: false + +Layout/ClosingHeredocIndentation: + Enabled: false + +Layout/ClosingParenthesisIndentation: + Enabled: false + +Layout/CommentIndentation: + Enabled: false + +Layout/ElseAlignment: + Enabled: false + +Layout/EmptyLineAfterGuardClause: + Enabled: false + +Layout/EmptyLineBetweenDefs: + Enabled: false + +Layout/EmptyLines: + Enabled: false + +Layout/EmptyLinesAroundBlockBody: + Enabled: false + +Layout/EmptyLinesAroundMethodBody: + Enabled: false + +Layout/EmptyLinesAroundModuleBody: + Enabled: false + +Layout/EndAlignment: + Enabled: false + +Layout/FirstArgumentIndentation: + Enabled: false + +Layout/FirstHashElementIndentation: + Enabled: false + +Layout/HashAlignment: + Enabled: false + +Layout/HeredocIndentation: + Enabled: false + +Layout/IndentationWidth: + Enabled: false + +Layout/LeadingCommentSpace: + Enabled: false + +Layout/LeadingEmptyLines: + Enabled: false + +Layout/MultilineArrayBraceLayout: + Enabled: false + +Layout/MultilineBlockLayout: + Enabled: false + +Layout/MultilineHashBraceLayout: + Enabled: false + +Layout/MultilineMethodCallBraceLayout: + Enabled: false + +Layout/MultilineMethodCallIndentation: + Enabled: false + +Layout/ParameterAlignment: + Enabled: false + +Layout/SpaceAfterComma: + Enabled: false + +Layout/SpaceAroundBlockParameters: + Enabled: false + +Layout/SpaceAroundEqualsInParameterDefault: + Enabled: false + +Layout/SpaceAroundOperators: + Enabled: false + +Layout/SpaceBeforeBlockBraces: + Enabled: false + +Layout/SpaceBeforeComma: + Enabled: false + +Layout/SpaceInsideBlockBraces: + Enabled: false + +Layout/SpaceInsideHashLiteralBraces: + Enabled: false + +Layout/SpaceInsideReferenceBrackets: + Enabled: false + +Layout/TrailingEmptyLines: + Enabled: false + +Lint/ConstantDefinitionInBlock: + Enabled: false + +Lint/IneffectiveAccessModifier: + Enabled: false + +Lint/MissingCopEnableDirective: + Enabled: false + +Lint/RedundantRequireStatement: + Enabled: false + +Lint/StructNewOverride: + Enabled: false + +Lint/UnusedBlockArgument: + Enabled: false + +Lint/UnusedMethodArgument: + Enabled: false + +Lint/UselessAccessModifier: + Enabled: false + +Lint/UselessAssignment: + Enabled: false + +Lint/UselessMethodDefinition: + Enabled: false + +Naming/BlockParameterName: + Enabled: false + +Naming/HeredocDelimiterNaming: + Enabled: false + +Naming/MethodParameterName: + Enabled: false + +Naming/RescuedExceptionsVariableName: + Enabled: false + +Naming/VariableNumber: + Enabled: false + +Style/AccessorGrouping: + Enabled: false + +Style/AndOr: + Enabled: false + +Style/BlockDelimiters: + Enabled: false + +Style/CaseLikeIf: + Enabled: false + +Style/CombinableLoops: + Enabled: false + +Style/CommentedKeyword: + Enabled: false + +Style/ConditionalAssignment: + Enabled: false + +Style/DefWithParentheses: + Enabled: false + +Style/EmptyElse: + Enabled: false + +Style/EmptyMethod: + Enabled: false + +Style/ExplicitBlockArgument: + Enabled: false + +Style/For: + Enabled: false + +Style/FormatStringToken: + Enabled: false + +Style/GlobalStdStream: + Enabled: false + +Style/HashEachMethods: + Enabled: false + +Style/HashSyntax: + Enabled: false + +Style/InfiniteLoop: + Enabled: false + +Style/InverseMethods: + Enabled: false + +Style/MethodCallWithoutArgsParentheses: + Enabled: false + +Style/MissingRespondToMissing: + Enabled: false + +Style/MultilineIfThen: + Enabled: false + +Style/MultilineTernaryOperator: + Enabled: false + +Style/MultipleComparison: + Enabled: false + +Style/MutableConstant: + Enabled: false + +Style/NumericPredicate: + Enabled: false + +Style/OptionalBooleanParameter: + Enabled: false + +Style/ParallelAssignment: + Enabled: false + +Style/RedundantAssignment: + Enabled: false + +Style/RedundantBegin: + Enabled: false + +Style/RedundantCondition: + Enabled: true + +Style/RedundantException: + Enabled: false + +Style/RedundantFileExtensionInRequire: + Enabled: false + +Style/RedundantParentheses: + Enabled: true + +Style/RedundantRegexpEscape: + Enabled: false + +Style/RedundantReturn: + Enabled: true + +Style/RedundantSelf: + Enabled: false + +Style/RescueStandardError: + Enabled: false + +Style/SafeNavigation: + Enabled: false + +Style/Semicolon: + Enabled: true + AllowAsExpressionSeparator: true + +Style/SlicingWithRange: + Enabled: false + +Style/SoleNestedConditional: + Enabled: false + +Style/StringConcatenation: + Enabled: false + +Style/SymbolArray: + Enabled: false + +Style/SymbolProc: + Enabled: false + +Style/TernaryParentheses: + Enabled: false + +Style/TrailingUnderscoreVariable: + Enabled: false + +Style/WhileUntilDo: + Enabled: false + +Style/ZeroLengthPredicate: + Enabled: false diff --git a/Makefile b/Makefile index 34a27c6..27c23d0 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,10 @@ TEMP_TEST_OUTPUT=/tmp/sse-contract-test-service.log build-contract-tests: - @cd contract-tests && bundle _2.2.10_ install + @cd contract-tests && bundle install start-contract-test-service: - @cd contract-tests && bundle _2.2.10_ exec ruby service.rb + @cd contract-tests && bundle exec ruby service.rb start-contract-test-service-bg: @echo "Test service output will be captured in $(TEMP_TEST_OUTPUT)" diff --git a/README.md b/README.md index 2b6e13c..f360d15 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ Parts of this code are based on https://github.com/Tonkpils/celluloid-eventsourc Supported Ruby versions ----------------------- -This gem has a minimum Ruby version of 2.5, or 9.2 for JRuby. +This gem has a minimum Ruby version of 3.1. Quick setup ----------- diff --git a/contract-tests/Gemfile b/contract-tests/Gemfile index 84bdd56..7e4c662 100644 --- a/contract-tests/Gemfile +++ b/contract-tests/Gemfile @@ -2,9 +2,7 @@ source 'https://rubygems.org' gem 'ld-eventsource', path: '..' -gem 'sinatra', '~> 2.1' -# Sinatra can work with several server frameworks. In JRuby, we have to use glassfish (which -# is only available in JRuby). Otherwise we use thin (which is not available in JRuby). -gem 'glassfish', :platforms => :jruby -gem 'thin', :platforms => :ruby gem 'json' +gem 'puma', '~> 6.6' +gem 'rackup', '~> 2.2' +gem 'sinatra', '>= 4.1' diff --git a/contract-tests/service.rb b/contract-tests/service.rb index 839822c..0a1d303 100644 --- a/contract-tests/service.rb +++ b/contract-tests/service.rb @@ -22,8 +22,8 @@ capabilities: [ 'headers', 'last-event-id', - 'read-timeout' - ] + 'read-timeout', + ], }.to_json end @@ -58,8 +58,8 @@ last_event_id: opts[:lastEventId], read_timeout: opts[:readTimeoutMs].nil? ? nil : (opts[:readTimeoutMs].to_f / 1000), reconnect_time: opts[:initialDelayMs].nil? ? nil : (opts[:initialDelayMs].to_f / 1000) - ) do |sse| - entity = StreamEntity.new(sse, tag, callbackUrl) + ) do |client| + entity = StreamEntity.new(client, tag, callbackUrl) end streams[streamId] = entity diff --git a/contract-tests/stream_entity.rb b/contract-tests/stream_entity.rb index 0c62543..078f95a 100644 --- a/contract-tests/stream_entity.rb +++ b/contract-tests/stream_entity.rb @@ -23,8 +23,8 @@ def on_event(event) event: { type: event.type, data: event.data, - id: event.last_event_id - } + id: event.last_event_id, + }, } self.send_message(message) end @@ -33,7 +33,7 @@ def on_error(error) $log.info("#{@tag} Received error from stream: #{error}") message = { kind: 'error', - error: error + error: error, } self.send_message(message) end diff --git a/ld-eventsource.gemspec b/ld-eventsource.gemspec index d671bc4..de59b25 100644 --- a/ld-eventsource.gemspec +++ b/ld-eventsource.gemspec @@ -1,29 +1,31 @@ # coding: utf-8 -lib = File.expand_path("../lib", __FILE__) +lib = File.expand_path('lib', __dir__) $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) -require "ld-eventsource/version" +require 'ld-eventsource/version' -# rubocop:disable Metrics/BlockLength Gem::Specification.new do |spec| - spec.name = "ld-eventsource" + spec.name = 'ld-eventsource' spec.version = SSE::VERSION - spec.authors = ["LaunchDarkly"] - spec.email = ["team@launchdarkly.com"] - spec.summary = "LaunchDarkly SSE client" - spec.description = "LaunchDarkly SSE client for Ruby" - spec.homepage = "https://github.com/launchdarkly/ruby-eventsource" - spec.license = "Apache-2.0" + spec.authors = ['LaunchDarkly'] + spec.email = ['team@launchdarkly.com'] + spec.summary = 'LaunchDarkly SSE client' + spec.description = 'LaunchDarkly SSE client for Ruby' + spec.homepage = 'https://github.com/launchdarkly/ruby-eventsource' + spec.license = 'Apache-2.0' - spec.files = Dir.glob("lib/**/*") + ["README.md", "LICENSE"] + + spec.files = Dir.glob('lib/**/*') + ['README.md', 'LICENSE'] spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } - spec.require_paths = ["lib"] + spec.require_paths = ['lib'] + spec.required_ruby_version = '>= 3.1' - spec.add_development_dependency "bundler", "2.2.10" - spec.add_development_dependency "rspec", "~> 3.2" - spec.add_development_dependency "rspec_junit_formatter", "~> 0.3.0" - spec.add_development_dependency "webrick", "~> 1.7" + spec.add_development_dependency 'rspec', '~> 3.2' + spec.add_development_dependency 'rspec_junit_formatter', '~> 0.3.0' + spec.add_development_dependency "rubocop", "~> 1.37" + spec.add_development_dependency "rubocop-performance", "~> 1.15" + spec.add_development_dependency 'webrick', '~> 1.7' - spec.add_runtime_dependency "concurrent-ruby", "~> 1.0" - spec.add_runtime_dependency "http", ">= 4.4.1", "< 6.0.0" + spec.add_runtime_dependency 'concurrent-ruby', '~> 1.0' + spec.add_runtime_dependency 'http', '>= 4.4.1', '< 6.0.0' end diff --git a/lib/ld-eventsource/client.rb b/lib/ld-eventsource/client.rb index 6355a62..c018151 100644 --- a/lib/ld-eventsource/client.rb +++ b/lib/ld-eventsource/client.rb @@ -120,14 +120,14 @@ def initialize(uri, if @proxy http_client_options["proxy"] = { :proxy_address => @proxy.host, - :proxy_port => @proxy.port + :proxy_port => @proxy.port, } end @http_client = HTTP::Client.new(http_client_options) .timeout({ read: read_timeout, - connect: connect_timeout + connect: connect_timeout, }) @cxn = nil @lock = Mutex.new @@ -202,13 +202,13 @@ def closed? private def reset_http - @http_client.close if !@http_client.nil? + @http_client.close unless @http_client.nil? close_connection end def close_connection @lock.synchronize do - @cxn.connection.close if !@cxn.nil? + @cxn.connection.close unless @cxn.nil? @cxn = nil end end @@ -216,12 +216,12 @@ def close_connection def default_logger log = ::Logger.new($stdout) log.level = ::Logger::WARN - log.progname = 'ld-eventsource' + log.progname = 'ld-eventsource' log end def run_stream - while !@stopped.value + until @stopped.value close_connection begin resp = connect @@ -231,7 +231,7 @@ def run_stream # There's a potential race if close was called in the middle of the previous line, i.e. after we # connected but before @cxn was set. Checking the variable again is a bit clunky but avoids that. return if @stopped.value - read_stream(resp) if !resp.nil? + read_stream(resp) unless resp.nil? rescue => e # When we deliberately close the connection, it will usually trigger an exception. The exact type # of exception depends on the specific Ruby runtime. But @stopped will always be set in this case. @@ -263,7 +263,7 @@ def connect begin @logger.info { "Connecting to event stream at #{@uri}" } cxn = @http_client.request("GET", @uri, { - headers: build_headers + headers: build_headers, }) if cxn.status.code == 200 content_type = cxn.content_type.mime_type @@ -332,7 +332,7 @@ def read_stream(cxn) def dispatch_event(event) @logger.debug { "Received event: #{event}" } - @last_id = event.id if !event.id.nil? + @last_id = event.id unless event.id.nil? # Pass the event to the caller @on[:event].call(event) @@ -353,7 +353,7 @@ def build_headers h = { 'Accept' => 'text/event-stream', 'Cache-Control' => 'no-cache', - 'User-Agent' => 'ruby-eventsource' + 'User-Agent' => 'ruby-eventsource', } h['Last-Event-Id'] = @last_id if !@last_id.nil? && @last_id != "" h.merge(@headers) diff --git a/lib/ld-eventsource/errors.rb b/lib/ld-eventsource/errors.rb index 6625642..6fe05ba 100644 --- a/lib/ld-eventsource/errors.rb +++ b/lib/ld-eventsource/errors.rb @@ -30,7 +30,7 @@ def initialize(status, message) # class HTTPContentTypeError < StandardError def initialize(type) - @content_type = type + @content_type = type super("invalid content type \"#{type}\"") end diff --git a/lib/ld-eventsource/impl/backoff.rb b/lib/ld-eventsource/impl/backoff.rb index 543da63..a540bf3 100644 --- a/lib/ld-eventsource/impl/backoff.rb +++ b/lib/ld-eventsource/impl/backoff.rb @@ -34,12 +34,12 @@ def initialize(base_interval, max_interval, reconnect_reset_interval: 60) # @return [Float] the next interval in seconds # def next_interval - if !@last_good_time.nil? + unless @last_good_time.nil? good_duration = Time.now.to_f - @last_good_time @attempts = 0 if good_duration >= @reconnect_reset_interval end @last_good_time = nil - target = ([@base_interval * (2 ** @attempts), @max_interval].min).to_f + target = [@base_interval * (2 ** @attempts), @max_interval].min.to_f @attempts += 1 if target == 0 0 # in some Ruby versions it's illegal to call rand(0) diff --git a/lib/ld-eventsource/impl/event_parser.rb b/lib/ld-eventsource/impl/event_parser.rb index bb6c8e4..b766aeb 100644 --- a/lib/ld-eventsource/impl/event_parser.rb +++ b/lib/ld-eventsource/impl/event_parser.rb @@ -36,7 +36,7 @@ def items if line.empty? event = maybe_create_event reset_buffers - gen.yield event if !event.nil? + gen.yield event unless event.nil? elsif (pos = line.index(':')) name = line.slice(0...pos) @@ -45,7 +45,7 @@ def items line = line.slice(pos..-1) item = process_field(name, line) - gen.yield item if !item.nil? + gen.yield item unless item.nil? end end end @@ -72,7 +72,7 @@ def process_field(name, value) end @have_data = true when "id" - if !value.include?("\x00") + unless value.include?("\x00") @id = value @last_event_id = value end @@ -85,7 +85,7 @@ def process_field(name, value) end def maybe_create_event - return nil if !@have_data + return nil unless @have_data StreamEvent.new(@type || :message, @data, @id, @last_event_id) end end diff --git a/spec/backoff_spec.rb b/spec/backoff_spec.rb index 6a1f9af..e3b81da 100644 --- a/spec/backoff_spec.rb +++ b/spec/backoff_spec.rb @@ -52,7 +52,7 @@ module Impl initial = 0 max = 60 b = Backoff.new(initial, max) - + for i in 1..6 do interval = b.next_interval expect(interval).to eq(0) diff --git a/spec/buffered_line_reader_spec.rb b/spec/buffered_line_reader_spec.rb index 376a1fa..a57c7eb 100644 --- a/spec/buffered_line_reader_spec.rb +++ b/spec/buffered_line_reader_spec.rb @@ -4,7 +4,7 @@ def make_tests(name, input_line_chunks:, expected_lines:) [{ name: "#{name}: one chunk per line", chunks: input_line_chunks, - expected: expected_lines + expected: expected_lines, }].concat( (1..4).map do |size| # Here we're lumping together all the content into one string and then @@ -13,11 +13,11 @@ def make_tests(name, input_line_chunks:, expected_lines:) # chunks would be ["ab", "cd", "\ne", "fg", "\n"]. This helps to find edge # case problems related to line terminators falling at the start of a chunk # or in the middle, etc. - ({ + { name: "#{name}: #{size}-character chunks", chunks: input_line_chunks.join().chars.each_slice(size).map { |a| a.join }, - expected: expected_lines - }) + expected: expected_lines, + } end ) end @@ -43,7 +43,7 @@ def tests_for_terminator(term, desc) make_tests("multi-line chunks", input_line_chunks: ["first line" + term + "second line" + term + "third", " line" + term + "fourth line" + term], - expected_lines: ["first line", "second line", "third line", "fourth line"]) + expected_lines: ["first line", "second line", "third line", "fourth line"]), ].flatten end @@ -53,7 +53,7 @@ def tests_for_terminator(term, desc) terminators = { "CR": "\r", "LF": "\n", - "CRLF": "\r\n" + "CRLF": "\r\n", } terminators.each do |desc, term| diff --git a/spec/client_spec.rb b/spec/client_spec.rb index 51f516d..ea7b849 100644 --- a/spec/client_spec.rb +++ b/spec/client_spec.rb @@ -6,7 +6,7 @@ # describe SSE::Client do before(:each) do - skip("end-to-end HTTP tests are disabled because they're unreliable on this platform") if !stub_http_server_available? + skip("end-to-end HTTP tests are disabled because they're unreliable on this platform") unless stub_http_server_available? end subject { SSE::Client } @@ -57,7 +57,7 @@ def send_stream_content(res, content, keep_open:) requests << req send_stream_content(res, "", keep_open: true) end - + headers = { "Authorization" => "secret" } with_client(subject.new(server.base_uri, headers: headers)) do |client| @@ -68,7 +68,7 @@ def send_stream_content(res, content, keep_open:) "host" => ["127.0.0.1:" + server.port.to_s], "authorization" => ["secret"], "user-agent" => ["ruby-eventsource"], - "connection" => ["close"] + "connection" => ["close"], }) end end @@ -82,7 +82,7 @@ def send_stream_content(res, content, keep_open:) requests << req send_stream_content(res, "", keep_open: true) end - + headers = { "Authorization" => "secret" } with_client(subject.new(server.base_uri, headers: headers, last_event_id: id)) do |client| @@ -94,7 +94,7 @@ def send_stream_content(res, content, keep_open:) "authorization" => ["secret"], "last-event-id" => [id], "user-agent" => ["ruby-eventsource"], - "connection" => ["close"] + "connection" => ["close"], }) end end @@ -112,7 +112,7 @@ def send_stream_content(res, content, keep_open:) c.on_event { |event| event_sink << event } end - with_client(client) do |client| + with_client(client) do |c| expect(event_sink.pop).to eq(simple_event_1) expect(event_sink.pop).to eq(simple_event_2) end @@ -133,9 +133,9 @@ def send_stream_content(res, content, keep_open:) c.on_error { |error| error_sink << error } end - with_client(client) do |client| + with_client(client) do |c| event_sink.pop # wait till we have definitely started reading the stream - client.close + c.close sleep 0.25 # there's no way to really know when the stream thread has finished expect(error_sink.empty?).to be true end @@ -164,7 +164,7 @@ def send_stream_content(res, content, keep_open:) c.on_error { |error| error_sink << error } end - with_client(client) do |client| + with_client(client) do |c| expect(event_sink.pop).to eq(simple_event_1) expect(error_sink.pop).to eq(SSE::Errors::HTTPStatusError.new(500, "sorry")) expect(attempt).to eq 2 @@ -195,7 +195,7 @@ def send_stream_content(res, content, keep_open:) c.on_error { |error| error_sink << error } end - with_client(client) do |client| + with_client(client) do |c| expect(event_sink.pop).to eq(simple_event_1) expect(error_sink.pop).to eq(SSE::Errors::HTTPContentTypeError.new("text/plain")) expect(attempt).to eq 2 @@ -220,7 +220,7 @@ def send_stream_content(res, content, keep_open:) c.on_event { |event| event_sink << event } end - with_client(client) do |client| + with_client(client) do |c| expect(event_sink.pop).to eq(simple_event_1) expect(attempt).to eq 2 end @@ -241,7 +241,7 @@ def send_stream_content(res, content, keep_open:) c.on_event { |event| event_sink << event } end - with_client(client) do |client| + with_client(client) do |c| expect(event_sink.pop).to eq(simple_event_1) expect(event_sink.pop).to eq(simple_event_2) expect(attempt).to eq 2 @@ -268,7 +268,7 @@ def send_stream_content(res, content, keep_open:) c.on_event { |event| event_sink << event } end - with_client(client) do |client| + with_client(client) do |c| req1 = requests.pop req2 = requests.pop expect(req2.header["last-event-id"]).to eq([ "a" ]) @@ -294,7 +294,7 @@ def send_stream_content(res, content, keep_open:) c.on_event { |event| event_sink << event } end - with_client(client) do |client| + with_client(client) do |c| last_interval = nil max_requests.times do |i| expect(event_sink.pop).to eq(simple_event_1) @@ -334,7 +334,7 @@ def send_stream_content(res, content, keep_open:) c.on_event { |event| event_sink << event } end - with_client(client) do |client| + with_client(client) do |c| last_interval = nil max_requests.times do |i| expect(event_sink.pop).to eq(simple_event_1) @@ -369,7 +369,7 @@ def send_stream_content(res, content, keep_open:) c.on_event { |event| event_sink << event } end - with_client(client) do |client| + with_client(client) do |c| expect(event_sink.pop).to eq(simple_event_1) interval = request_times[1] - request_times[0] expect(interval).to be < 0.5 @@ -389,7 +389,7 @@ def send_stream_content(res, content, keep_open:) c.on_event { |event| event_sink << event } end - with_client(client) do |client| + with_client(client) do |c| expect(event_sink.pop).to eq(simple_event_1) expect(proxy.request_count).to eq(1) end @@ -424,7 +424,7 @@ def send_stream_content(res, content, keep_open:) c.on_event { |event| event_sink << event } end - with_client(client) do |client| + with_client(client) do |c| 4.times { expect(event_sink.pop).to eq(simple_event_1) } @@ -438,7 +438,7 @@ def send_stream_content(res, content, keep_open:) server.setup_response("/") do |req,res| send_stream_content(res, "", keep_open: true) end - + with_client(subject.new(server.base_uri)) do |client| expect(client.closed?).to be(false) diff --git a/spec/event_parser_spec.rb b/spec/event_parser_spec.rb index 264d73d..c77609e 100644 --- a/spec/event_parser_spec.rb +++ b/spec/event_parser_spec.rb @@ -12,10 +12,10 @@ def verify_parsed_events(lines:, expected_events:) it "parses an event with only data" do lines = [ "data: def", - "" + "", ] ep = subject.new(lines) - + expected_event = SSE::StreamEvent.new(:message, "def", nil) output = ep.items.to_a expect(output).to eq([ expected_event ]) @@ -26,10 +26,10 @@ def verify_parsed_events(lines:, expected_events:) "event: abc", "data: def", "id: 1", - "" + "", ] ep = subject.new(lines) - + expected_event = SSE::StreamEvent.new(:abc, "def", "1", "1") output = ep.items.to_a expect(output).to eq([ expected_event ]) @@ -39,10 +39,10 @@ def verify_parsed_events(lines:, expected_events:) lines = [ "event: abc", "data: def", - "" + "", ] ep = subject.new(lines, "1") - + expected_event = SSE::StreamEvent.new(:abc, "def", nil, "1") output = ep.items.to_a expect(output).to eq([ expected_event ]) @@ -53,10 +53,10 @@ def verify_parsed_events(lines:, expected_events:) "event: abc", "data: def", "id:", - "" + "", ] ep = subject.new(lines, "1") - + expected_event = SSE::StreamEvent.new(:abc, "def", "", "") output = ep.items.to_a expect(output).to eq([ expected_event ]) @@ -68,23 +68,23 @@ def verify_parsed_events(lines:, expected_events:) "event: abc", "data: def", "id: 12\x0034", - "" + "", ] ep = subject.new(lines, "1") - + expected_event = SSE::StreamEvent.new(:abc, "def", nil, "1") output = ep.items.to_a expect(output).to eq([ expected_event ]) end - + it "parses an event with multi-line data" do lines = [ "data: def", "data: ghi", - "" + "", ] ep = subject.new(lines) - + expected_event = SSE::StreamEvent.new(:message, "def\nghi", nil) output = ep.items.to_a expect(output).to eq([ expected_event ]) @@ -94,10 +94,10 @@ def verify_parsed_events(lines:, expected_events:) verify_parsed_events( lines: [ "data:", - "" + "", ], expected_events: [ - SSE::StreamEvent.new(:message, "", nil) + SSE::StreamEvent.new(:message, "", nil), ]) end @@ -106,10 +106,10 @@ def verify_parsed_events(lines:, expected_events:) lines: [ "data:", "data: abc", - "" + "", ], expected_events: [ - SSE::StreamEvent.new(:message, "\nabc", nil) + SSE::StreamEvent.new(:message, "\nabc", nil), ]) end @@ -119,10 +119,10 @@ def verify_parsed_events(lines:, expected_events:) "data:", "data:", "data: abc", - "" + "", ], expected_events: [ - SSE::StreamEvent.new(:message, "\n\nabc", nil) + SSE::StreamEvent.new(:message, "\n\nabc", nil), ]) end @@ -132,10 +132,10 @@ def verify_parsed_events(lines:, expected_events:) "data: abc", "data:", "data: def", - "" + "", ], expected_events: [ - SSE::StreamEvent.new(:message, "abc\n\ndef", nil) + SSE::StreamEvent.new(:message, "abc\n\ndef", nil), ]) end @@ -144,10 +144,10 @@ def verify_parsed_events(lines:, expected_events:) lines: [ "data: abc", "data:", - "" + "", ], expected_events: [ - SSE::StreamEvent.new(:message, "abc\n", nil) + SSE::StreamEvent.new(:message, "abc\n", nil), ]) end @@ -156,10 +156,10 @@ def verify_parsed_events(lines:, expected_events:) ":", "data: def", ":", - "" + "", ] ep = subject.new(lines) - + expected_event = SSE::StreamEvent.new(:message, "def", nil) output = ep.items.to_a expect(output).to eq([ expected_event ]) @@ -168,7 +168,7 @@ def verify_parsed_events(lines:, expected_events:) it "parses reconnect interval" do lines = [ "retry: 2500", - "" + "", ] ep = subject.new(lines) @@ -184,10 +184,10 @@ def verify_parsed_events(lines:, expected_events:) "id: 1", "", "data: ghi", - "" + "", ] ep = subject.new(lines) - + expected_event_1 = SSE::StreamEvent.new(:abc, "def", "1", "1") expected_event_2 = SSE::StreamEvent.new(:message, "ghi", nil, "1") output = ep.items.to_a @@ -199,10 +199,10 @@ def verify_parsed_events(lines:, expected_events:) "event: nothing", "", "event: nada", - "" + "", ] ep = subject.new(lines) - + output = ep.items.to_a expect(output).to eq([]) end diff --git a/spec/http_stub.rb b/spec/http_stub.rb index 1fe8da2..3724529 100644 --- a/spec/http_stub.rb +++ b/spec/http_stub.rb @@ -62,7 +62,7 @@ def create_server(port) AccessLog: [], Logger: NullLogger.new, ProxyContentHandler: proc do |req,res| - if !@connect_status.nil? + unless @connect_status.nil? res.status = @connect_status end @request_count += 1