summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Quigley <tsimonq2@debian.org>2026-06-20 15:03:32 -0500
committergit-ubuntu importer <ubuntu-devel-discuss@lists.ubuntu.com>2026-06-21 04:47:02 +0000
commit3b425eb05cb5f651a0306d0845127149e077b1f2 (patch)
treed65c01ef1573d42397d4a97cd88fcd1225a2eb62
parentc44f69d65bf92434ca9d4fee83fcc48f55be6efa (diff)
Imported using git-ubuntu import.
Notes
Notes: * Team upload. [ Lucas Nussbaum ] * debian/gbp.conf: Add for DEP-14 * debian/.gitattributes: remove * debian/salsa-ci.yml: use team-specific include [ Simon Quigley ] * Upgrade the watch file to version 5. * New upstream release. * Use --gem-install layout in rules. * Refresh the upstream metadata. * Update Standards-Version to 4.7.4. * Drop {XS,XB}-Ruby-Versions from control. * Bump debhelper-compat to 14, dropping ${misc:Depends}, ${shlibs:Depends}, and ${ruby:Depends} from runtime dependencies. * Drop Files-Excluded, it's no longer applicable.
-rw-r--r--.github/workflows/coverage.yml21
-rw-r--r--.github/workflows/danger.yml22
-rw-r--r--.github/workflows/lint.yml16
-rw-r--r--.github/workflows/test.yml33
-rw-r--r--.gitignore3
-rw-r--r--.rspec2
-rw-r--r--.rubocop.yml30
-rw-r--r--.rubocop_todo.yml72
-rw-r--r--CHANGELOG.md8
-rw-r--r--Gemfile4
-rw-r--r--Gemfile.lock136
-rw-r--r--README.md59
-rw-r--r--Rakefile7
-rw-r--r--benchmarks/case.rb45
-rw-r--r--debian/changelog22
-rw-r--r--debian/control12
-rw-r--r--debian/copyright1
-rw-r--r--debian/gbp.conf4
-rw-r--r--debian/patches/0001-Do-not-require-simplecov-to-run-tests.patch4
-rwxr-xr-xdebian/rules1
-rw-r--r--debian/salsa-ci.yml3
-rw-r--r--debian/upstream/metadata3
-rw-r--r--debian/watch7
-rw-r--r--lib/ruby-enum.rb18
-rw-r--r--lib/ruby-enum/enum.rb9
-rw-r--r--lib/ruby-enum/enum/case.rb84
-rw-r--r--lib/ruby-enum/enum/i18n_mock.rb19
-rw-r--r--lib/ruby-enum/errors/base.rb6
-rw-r--r--lib/ruby-enum/version.rb2
-rw-r--r--pkg/ruby-enum-0.8.0.gembin13824 -> 0 bytes
-rw-r--r--ruby-enum.gemspec3
-rw-r--r--spec/ruby-enum/enum/case_spec.rb118
-rw-r--r--spec/ruby-enum/enum_spec.rb140
-rw-r--r--spec_i18n/Gemfile9
-rw-r--r--spec_i18n/Rakefile12
-rw-r--r--spec_i18n/spec/i18n_spec.rb48
-rw-r--r--spec_i18n/spec/spec_helper.rb8
37 files changed, 791 insertions, 200 deletions
diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml
new file mode 100644
index 0000000..f8fab3c
--- /dev/null
+++ b/.github/workflows/coverage.yml
@@ -0,0 +1,21 @@
+---
+name: coverage
+on: [push]
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v3
+ - name: Install Ruby (3.2)
+ uses: ruby/setup-ruby@v1
+ with:
+ ruby-version: 3.2
+ - uses: amancevice/setup-code-climate@v0
+ with:
+ cc_test_reporter_id: ${{ secrets.CC_TEST_REPORTER_ID }}
+ - run: cc-test-reporter before-build
+ - name: Build and test with RSpec
+ run: |
+ bundle install --jobs 4 --retry 3
+ bundle exec rspec
+ - run: cc-test-reporter after-build
diff --git a/.github/workflows/danger.yml b/.github/workflows/danger.yml
new file mode 100644
index 0000000..c643c4b
--- /dev/null
+++ b/.github/workflows/danger.yml
@@ -0,0 +1,22 @@
+---
+name: danger
+on:
+ pull_request:
+ types: [opened, reopened, edited, synchronize]
+jobs:
+ danger:
+ runs-on: ubuntu-20.04
+ steps:
+ - uses: actions/checkout@v3
+ with:
+ fetch-depth: 0
+ - name: Set up Ruby
+ uses: ruby/setup-ruby@v1
+ with:
+ ruby-version: 2.7
+ bundler-cache: true
+ - name: Run Danger
+ run: |
+ # the personal token is public, this is ok, base64 encode to avoid tripping Github
+ TOKEN=$(echo -n Z2hwX0xNQ3VmanBFeTBvYkZVTWh6NVNqVFFBOEUxU25abzBqRUVuaAo= | base64 --decode)
+ DANGER_GITHUB_API_TOKEN=$TOKEN bundle exec danger --verbose
diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
new file mode 100644
index 0000000..9ffe62f
--- /dev/null
+++ b/.github/workflows/lint.yml
@@ -0,0 +1,16 @@
+name: Lint
+on: [push, pull_request]
+jobs:
+ rubocop:
+ name: RuboCop
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v3
+ - name: Set up Ruby
+ uses: ruby/setup-ruby@v1
+ with:
+ ruby-version: 2.7
+ bundler-cache: true
+ - run: bundle exec rubocop
+
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
new file mode 100644
index 0000000..cdbde68
--- /dev/null
+++ b/.github/workflows/test.yml
@@ -0,0 +1,33 @@
+---
+name: test
+on: [push, pull_request]
+jobs:
+ test:
+ runs-on: ubuntu-latest
+ strategy:
+ fail-fast: false
+ matrix:
+ entry:
+ - { ruby: '2.7', allowed-failure: false }
+ - { ruby: '3.0', allowed-failure: false }
+ - { ruby: '3.1', allowed-failure: false }
+ - { ruby: '3.2', allowed-failure: false }
+ - { ruby: 'ruby-head', allowed-failure: true }
+ - { ruby: 'truffleruby-head', allowed-failure: true }
+ - { ruby: 'jruby-head', allowed-failure: true }
+ name: test (${{ matrix.entry.ruby }})
+ steps:
+ - uses: actions/checkout@v3
+ - uses: ruby/setup-ruby@v1
+ with:
+ ruby-version: ${{ matrix.entry.ruby }}
+ - run: bundle install --jobs=3 --retry=3 --path=vendor/bundle
+ - run: bundle exec rake spec
+ continue-on-error: ${{ matrix.entry.allowed-failure }}
+ - name: Specs for when the i18n gem is not available
+ run: |
+ cd spec_i18n
+ bundle install --jobs=3 --retry=3
+ pwd
+ bundle exec rake spec
+ continue-on-error: ${{ matrix.entry.allowed-failure }}
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..70c558c
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+Gemfile.lock
+pkg
+coverage
diff --git a/.rspec b/.rspec
new file mode 100644
index 0000000..8c18f1a
--- /dev/null
+++ b/.rspec
@@ -0,0 +1,2 @@
+--format documentation
+--color
diff --git a/.rubocop.yml b/.rubocop.yml
new file mode 100644
index 0000000..1f7eac4
--- /dev/null
+++ b/.rubocop.yml
@@ -0,0 +1,30 @@
+require:
+ - rubocop-rake
+ - rubocop-rspec
+
+AllCops:
+ TargetRubyVersion: 2.7
+ NewCops: enable
+ Exclude:
+ - vendor/**/*
+
+Metrics/BlockLength:
+ Exclude:
+ - 'spec/**/*_spec.rb'
+
+RSpec/SpecFilePathFormat:
+ Enabled: false
+
+RSpec/FilePath:
+ Enabled: false
+
+Style/HashEachMethods:
+ Enabled: true
+
+Style/HashTransformKeys:
+ Enabled: true
+
+Style/HashTransformValues:
+ Enabled: true
+
+inherit_from: .rubocop_todo.yml
diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml
new file mode 100644
index 0000000..9039cdc
--- /dev/null
+++ b/.rubocop_todo.yml
@@ -0,0 +1,72 @@
+# This configuration was generated by
+# `rubocop --auto-gen-config`
+# on 2023-02-14 01:34:25 UTC using RuboCop version 1.45.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.
+
+# Offense count: 4
+# Configuration parameters: AllowedMethods.
+# AllowedMethods: enums
+Lint/ConstantDefinitionInBlock:
+ Exclude:
+ - 'spec/ruby-enum/enum_spec.rb'
+
+# Offense count: 1
+# 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:
+ - 'lib/ruby-enum.rb'
+
+# Offense count: 6
+# 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/ruby-enum/enum.rb'
+
+# Offense count: 3
+# Configuration parameters: CountAsOne.
+RSpec/ExampleLength:
+ Max: 11
+
+# Offense count: 4
+RSpec/LeakyConstantDeclaration:
+ Exclude:
+ - 'spec/ruby-enum/enum_spec.rb'
+
+# Offense count: 6
+RSpec/MultipleExpectations:
+ Max: 11
+
+# Offense count: 18
+# Configuration parameters: EnforcedStyle, IgnoreSharedExamples.
+# SupportedStyles: always, named_only
+RSpec/NamedSubject:
+ Exclude:
+ - 'spec/ruby-enum/enum_spec.rb'
+
+# Offense count: 1
+# Configuration parameters: AllowedGroups.
+RSpec/NestedGroups:
+ Max: 4
+
+# Offense count: 4
+# Configuration parameters: AllowedConstants.
+Style/Documentation:
+ Exclude:
+ - 'spec/**/*'
+ - 'test/**/*'
+ - 'lib/ruby-enum/enum.rb'
+ - 'lib/ruby-enum/errors/base.rb'
+ - 'lib/ruby-enum/errors/uninitialized_constant_error.rb'
+
+# Offense count: 1
+# This cop supports safe autocorrection (--autocorrect).
+# Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, AllowedPatterns.
+# URISchemes: http, https
+Layout/LineLength:
+ Max: 148
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6566fe7..4145b7f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,11 @@
+### 1.0.0 (2023/01/10)
+
+* [#41](https://github.com/dblock/ruby-enum/pull/41): Make i18n dependency optional - [@peterfication](https://github.com/peterfication).
+* [#43](https://github.com/dblock/ruby-enum/pull/43): Add exhaustive case matcher - [@peterfication](https://github.com/peterfication).
+* [#40](https://github.com/dblock/ruby-enum/pull/39): Enable new Rubocop cops and address/allowlist lints - [@petergoldstein](https://github.com/petergoldstein).
+* [#39](https://github.com/dblock/ruby-enum/pull/39): Require Ruby >= 2.7 - [@petergoldstein](https://github.com/petergoldstein).
+* [#38](https://github.com/dblock/ruby-enum/pull/38): Ensure Ruby >= 2.3 - [@ojab](https://github.com/ojab).
+
### 0.9.0 (2021/01/21)
* [#34](https://github.com/dblock/ruby-enum/pull/34): Added support for Ruby 3.0 - [@dblock](https://github.com/dblock).
diff --git a/Gemfile b/Gemfile
index 56badd5..dc4319a 100644
--- a/Gemfile
+++ b/Gemfile
@@ -11,7 +11,9 @@ group :development, :test do
gem 'danger-changelog', '0.6.1'
gem 'danger-toc', '0.2.0'
gem 'rspec', '~> 3.0'
- gem 'rubocop', '0.80.1'
+ gem 'rubocop', '~> 1.0'
+ gem 'rubocop-rake'
+ gem 'rubocop-rspec'
end
group :test do
diff --git a/Gemfile.lock b/Gemfile.lock
deleted file mode 100644
index f2954cd..0000000
--- a/Gemfile.lock
+++ /dev/null
@@ -1,136 +0,0 @@
-PATH
- remote: .
- specs:
- ruby-enum (0.9.0)
- i18n
-
-GEM
- remote: http://rubygems.org/
- specs:
- activesupport (6.1.0)
- concurrent-ruby (~> 1.0, >= 1.0.2)
- i18n (>= 1.6, < 2)
- minitest (>= 5.1)
- tzinfo (~> 2.0)
- zeitwerk (~> 2.3)
- addressable (2.7.0)
- public_suffix (>= 2.0.2, < 5.0)
- ast (2.4.2)
- claide (1.0.3)
- claide-plugins (0.9.2)
- cork
- nap
- open4 (~> 1.3)
- colored2 (3.1.2)
- concurrent-ruby (1.1.7)
- cork (0.3.0)
- colored2 (~> 3.1)
- danger (8.2.1)
- claide (~> 1.0)
- claide-plugins (>= 0.9.2)
- colored2 (~> 3.1)
- cork (~> 0.1)
- faraday (>= 0.9.0, < 2.0)
- faraday-http-cache (~> 2.0)
- git (~> 1.7)
- kramdown (~> 2.3)
- kramdown-parser-gfm (~> 1.0)
- no_proxy_fix
- octokit (~> 4.7)
- terminal-table (~> 1)
- danger-changelog (0.6.1)
- danger-plugin-api (~> 1.0)
- danger-plugin-api (1.0.0)
- danger (> 2.0)
- danger-toc (0.2.0)
- activesupport
- danger-plugin-api (~> 1.0)
- kramdown
- diff-lcs (1.3)
- docile (1.3.5)
- faraday (1.3.0)
- faraday-net_http (~> 1.0)
- multipart-post (>= 1.2, < 3)
- ruby2_keywords
- faraday-http-cache (2.2.0)
- faraday (>= 0.8)
- faraday-net_http (1.0.0)
- git (1.8.1)
- rchardet (~> 1.8)
- i18n (1.8.7)
- concurrent-ruby (~> 1.0)
- jaro_winkler (1.5.4)
- kramdown (2.3.0)
- rexml
- kramdown-parser-gfm (1.1.0)
- kramdown (~> 2.0)
- minitest (5.14.3)
- multipart-post (2.1.1)
- nap (1.1.0)
- no_proxy_fix (0.1.2)
- octokit (4.20.0)
- faraday (>= 0.9)
- sawyer (~> 0.8.0, >= 0.5.3)
- open4 (1.3.4)
- parallel (1.20.1)
- parser (3.0.0.0)
- ast (~> 2.4.1)
- public_suffix (4.0.6)
- rainbow (3.0.0)
- rake (13.0.1)
- rchardet (1.8.0)
- rexml (3.2.4)
- rspec (3.9.0)
- rspec-core (~> 3.9.0)
- rspec-expectations (~> 3.9.0)
- rspec-mocks (~> 3.9.0)
- rspec-core (3.9.1)
- rspec-support (~> 3.9.1)
- rspec-expectations (3.9.1)
- diff-lcs (>= 1.2.0, < 2.0)
- rspec-support (~> 3.9.0)
- rspec-mocks (3.9.1)
- diff-lcs (>= 1.2.0, < 2.0)
- rspec-support (~> 3.9.0)
- rspec-support (3.9.2)
- rubocop (0.80.1)
- jaro_winkler (~> 1.5.1)
- parallel (~> 1.10)
- parser (>= 2.7.0.1)
- rainbow (>= 2.2.2, < 4.0)
- rexml
- ruby-progressbar (~> 1.7)
- unicode-display_width (>= 1.4.0, < 1.7)
- ruby-progressbar (1.11.0)
- ruby2_keywords (0.0.2)
- sawyer (0.8.2)
- addressable (>= 2.3.5)
- faraday (> 0.8, < 2.0)
- simplecov (0.21.2)
- docile (~> 1.1)
- simplecov-html (~> 0.11)
- simplecov_json_formatter (~> 0.1)
- simplecov-html (0.12.3)
- simplecov_json_formatter (0.1.2)
- terminal-table (1.8.0)
- unicode-display_width (~> 1.1, >= 1.1.1)
- tzinfo (2.0.4)
- concurrent-ruby (~> 1.0)
- unicode-display_width (1.6.1)
- zeitwerk (2.4.2)
-
-PLATFORMS
- ruby
-
-DEPENDENCIES
- danger
- danger-changelog (= 0.6.1)
- danger-toc (= 0.2.0)
- rake
- rspec (~> 3.0)
- rubocop (= 0.80.1)
- ruby-enum!
- simplecov
-
-BUNDLED WITH
- 2.1.4
diff --git a/README.md b/README.md
index 1e6e66d..49ab445 100644
--- a/README.md
+++ b/README.md
@@ -24,6 +24,9 @@ Enum-like behavior for Ruby, heavily inspired by [this](http://www.rubyfleebie.c
- [Mapping values to keys](#mapping-values-to-keys)
- [Duplicate enumerator keys or duplicate values](#duplicate-enumerator-keys-or-duplicate-values)
- [Inheritance](#inheritance)
+ - [Exhaustive case matcher](#exhaustive-case-matcher)
+ - [I18n support](#i18n-support)
+- [Benchmarks](#benchmarks)
- [Contributing](#contributing)
- [Copyright and License](#copyright-and-license)
- [Related Projects](#related-projects)
@@ -259,6 +262,62 @@ OrderState.values # ['CREATED', 'PAID']
ShippedOrderState.values # ['CREATED', 'PAID', 'PREPARED', SHIPPED']
```
+### Exhaustive case matcher
+
+If you want to make sure that you cover all cases in a case stament, you can use the exhaustive case matcher: `Ruby::Enum::Case`. It will raise an error if a case/enum value is not handled, or if a value is specified that's not part of the enum. This is inspired by the [Rust Pattern Syntax](https://doc.rust-lang.org/book/ch18-03-pattern-syntax.html). If multiple cases match, all matches are being executed. The return value is the value from the matched case, or an array of return values if multiple cases matched.
+
+> NOTE: This will add checks at runtime which might lead to worse performance. See [benchmarks](#benchmarks).
+
+> NOTE: `:else` is a reserved keyword if you want to use `Ruby::Enum::Case`.
+
+```ruby
+class Color < OrderState
+ include Ruby::Enum
+ include Ruby::Enum::Case
+
+ define :RED, :red
+ define :GREEN, :green
+ define :BLUE, :blue
+ define :YELLOW, :yellow
+end
+```
+
+```ruby
+color = Color::RED
+Color.Case(color, {
+ [Color::GREEN, Color::BLUE] => -> { "order is green or blue" },
+ Color::YELLOW => -> { "order is yellow" },
+ Color::RED => -> { "order is red" },
+})
+```
+
+It also supports default/else:
+
+```ruby
+color = Color::RED
+Color.Case(color, {
+ [Color::GREEN, Color::BLUE] => -> { "order is green or blue" },
+ else: -> { "order is yellow or red" },
+})
+```
+
+### I18n support
+
+This gem has an optional dependency to `i18n`. If it's available, the error messages will have a nice description and can be translated. If it's not available, the errors will only contain the message keys.
+
+```ruby
+# Add this to your Gemfile if you want to have a nice error description instead of just a message key.
+gem "i18n"
+```
+
+## Benchmarks
+
+Benchmark scripts are defined in the [`benchmarks`](benchmarks) folder and can be run with Rake:
+
+```console
+rake benchmarks:case
+```
+
## Contributing
You're encouraged to contribute to ruby-enum. See [CONTRIBUTING](CONTRIBUTING.md) for details.
diff --git a/Rakefile b/Rakefile
index dd0ed12..2557ba4 100644
--- a/Rakefile
+++ b/Rakefile
@@ -16,3 +16,10 @@ require 'rubocop/rake_task'
RuboCop::RakeTask.new(:rubocop)
task default: %i[rubocop spec]
+
+namespace :benchmark do
+ desc 'Run benchmark for the Ruby::Enum::Case'
+ task :case do
+ require_relative 'benchmarks/case'
+ end
+end
diff --git a/benchmarks/case.rb b/benchmarks/case.rb
new file mode 100644
index 0000000..2c51d0f
--- /dev/null
+++ b/benchmarks/case.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
+
+require 'benchmark'
+require 'ruby-enum'
+
+##
+# Test enum
+class Color
+ include Ruby::Enum
+ include Ruby::Enum::Case
+
+ define :RED, :red
+ define :GREEN, :green
+ define :BLUE, :blue
+end
+
+puts 'Running 1.000.000 normal case statements'
+case_statement_time = Benchmark.realtime do
+ 1_000_000.times do
+ case Color::RED
+ when Color::RED, Color::GREEN
+ 'red or green'
+ when Color::BLUE
+ 'blue'
+ end
+ end
+end
+
+puts 'Running 1.000.000 ruby-enum case statements'
+ruby_enum_time = Benchmark.realtime do
+ 1_000_000.times do
+ Color.case(Color::RED,
+ {
+ [Color::RED, Color::GREEN] => -> { 'red or green' },
+ Color::BLUE => -> { 'blue' }
+ })
+ end
+end
+
+puts "ruby-enum case: #{ruby_enum_time.round(4)}"
+puts "case statement: #{case_statement_time.round(4)}"
+
+puts "ruby-enum case is #{(ruby_enum_time / case_statement_time).round(2)} times slower"
diff --git a/debian/changelog b/debian/changelog
index 5aba022..fd1f256 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,25 @@
+ruby-enum (1.0.0-1) unstable; urgency=medium
+
+ * Team upload.
+
+ [ Lucas Nussbaum ]
+ * debian/gbp.conf: Add for DEP-14
+ * debian/.gitattributes: remove
+ * debian/salsa-ci.yml: use team-specific include
+
+ [ Simon Quigley ]
+ * Upgrade the watch file to version 5.
+ * New upstream release.
+ * Use --gem-install layout in rules.
+ * Refresh the upstream metadata.
+ * Update Standards-Version to 4.7.4.
+ * Drop {XS,XB}-Ruby-Versions from control.
+ * Bump debhelper-compat to 14, dropping ${misc:Depends},
+ ${shlibs:Depends}, and ${ruby:Depends} from runtime dependencies.
+ * Drop Files-Excluded, it's no longer applicable.
+
+ -- Simon Quigley <tsimonq2@debian.org> Sat, 20 Jun 2026 15:03:32 -0500
+
ruby-enum (0.9.0+ds-1) unstable; urgency=medium
* Team upload.
diff --git a/debian/control b/debian/control
index f6df20f..87a4c7b 100644
--- a/debian/control
+++ b/debian/control
@@ -1,27 +1,21 @@
Source: ruby-enum
Section: ruby
-Priority: optional
Maintainer: Debian Ruby Team <pkg-ruby-extras-maintainers@lists.alioth.debian.org>
Uploaders: Pirate Praveen <praveen@debian.org>
-Build-Depends: debhelper-compat (= 13),
+Build-Depends: debhelper-compat (= 14),
gem2deb,
rake,
ruby-i18n,
ruby-rspec
-Standards-Version: 4.6.0
+Standards-Version: 4.7.4
Vcs-Git: https://salsa.debian.org/ruby-team/ruby-enum.git
Vcs-Browser: https://salsa.debian.org/ruby-team/ruby-enum
Homepage: https://github.com/dblock/ruby-enum
Testsuite: autopkgtest-pkg-ruby
-XS-Ruby-Versions: all
-Rules-Requires-Root: no
Package: ruby-enum
Architecture: all
-XB-Ruby-Versions: ${ruby:Versions}
-Depends: ruby-i18n,
- ${misc:Depends},
- ${shlibs:Depends}
+Depends: ruby-i18n
Description: Enum-like behavior for Ruby
Enums can be defined and accessed either as constants or class methods.
.
diff --git a/debian/copyright b/debian/copyright
index d606b34..446a6e3 100644
--- a/debian/copyright
+++ b/debian/copyright
@@ -1,7 +1,6 @@
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: ruby-enum
Source: http://github.com/dblock/ruby-enum
-Files-Excluded: coverage/*
Files: *
Copyright: 2013-2016, Daniel Doubrovkine.
diff --git a/debian/gbp.conf b/debian/gbp.conf
new file mode 100644
index 0000000..6b65fe0
--- /dev/null
+++ b/debian/gbp.conf
@@ -0,0 +1,4 @@
+[DEFAULT]
+debian-branch = debian/latest
+upstream-branch = upstream/latest
+pristine-tar = True
diff --git a/debian/patches/0001-Do-not-require-simplecov-to-run-tests.patch b/debian/patches/0001-Do-not-require-simplecov-to-run-tests.patch
index ab3334e..70b6d32 100644
--- a/debian/patches/0001-Do-not-require-simplecov-to-run-tests.patch
+++ b/debian/patches/0001-Do-not-require-simplecov-to-run-tests.patch
@@ -7,11 +7,9 @@ Forwarded: not-needed
spec/spec_helper.rb | 3 ---
1 file changed, 3 deletions(-)
-diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
-index 38a174f..ba7dfec 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
-@@ -4,9 +4,6 @@ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
+@@ -4,9 +4,6 @@ $LOAD_PATH.unshift(File.join(File.dirnam
require 'rubygems'
diff --git a/debian/rules b/debian/rules
index 3454d59..4e91465 100755
--- a/debian/rules
+++ b/debian/rules
@@ -1,6 +1,7 @@
#!/usr/bin/make -f
export GEM2DEB_TEST_RUNNER = --check-dependencies
+export DH_RUBY = --gem-install
%:
dh $@ --buildsystem=ruby --with ruby
diff --git a/debian/salsa-ci.yml b/debian/salsa-ci.yml
index 33c3a64..7b5d2f7 100644
--- a/debian/salsa-ci.yml
+++ b/debian/salsa-ci.yml
@@ -1,4 +1,3 @@
---
include:
- - https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/salsa-ci.yml
- - https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/pipeline-jobs.yml
+ - https://salsa.debian.org/ruby-team/meta/raw/master/salsa-ci.yml
diff --git a/debian/upstream/metadata b/debian/upstream/metadata
index 964b078..943a2fc 100644
--- a/debian/upstream/metadata
+++ b/debian/upstream/metadata
@@ -1,4 +1,7 @@
+---
+Archive: GitHub
Bug-Database: https://github.com/dblock/ruby-enum/issues
Bug-Submit: https://github.com/dblock/ruby-enum/issues/new
+Changelog: https://github.com/dblock/ruby-enum/blob/master/CHANGELOG.md
Repository: https://github.com/dblock/ruby-enum.git
Repository-Browse: https://github.com/dblock/ruby-enum
diff --git a/debian/watch b/debian/watch
index 48f0adf..7aadb01 100644
--- a/debian/watch
+++ b/debian/watch
@@ -1,3 +1,4 @@
-version=4
-opts=dversionmangle=s/\.ds// \
-https://gemwatch.debian.net/ruby-enum .*/ruby-enum-(.*).tar.gz
+Version: 5
+Template: GitHub
+Owner: dblock
+Project: ruby-enum
diff --git a/lib/ruby-enum.rb b/lib/ruby-enum.rb
index 855c8ee..4d9b921 100644
--- a/lib/ruby-enum.rb
+++ b/lib/ruby-enum.rb
@@ -1,11 +1,23 @@
# frozen_string_literal: true
-require 'i18n'
-
require 'ruby-enum/version'
require 'ruby-enum/enum'
+require 'ruby-enum/enum/case'
+require 'ruby-enum/enum/i18n_mock'
+
+# Try to load the I18n gem and provide a mock if it is not available.
+begin
+ require 'i18n'
+ Ruby::Enum.i18n = I18n
+rescue LoadError
+ # I18n is not available
+ # :nocov:
+ # Tests for this loading are in the spec_i18n folder
+ Ruby::Enum.i18n = Ruby::Enum::I18nMock
+ # :nocov:
+end
-I18n.load_path << File.join(File.dirname(__FILE__), 'config', 'locales', 'en.yml')
+Ruby::Enum.i18n.load_path << File.join(File.dirname(__FILE__), 'config', 'locales', 'en.yml')
require 'ruby-enum/errors/base'
require 'ruby-enum/errors/uninitialized_constant_error'
diff --git a/lib/ruby-enum/enum.rb b/lib/ruby-enum/enum.rb
index f7abb4c..0930e86 100644
--- a/lib/ruby-enum/enum.rb
+++ b/lib/ruby-enum/enum.rb
@@ -2,6 +2,11 @@
module Ruby
module Enum
+ class << self
+ # Needed for I18n mock
+ attr_accessor :i18n
+ end
+
attr_reader :key, :value
def initialize(key, value)
@@ -144,9 +149,7 @@ module Ruby
end
def to_h
- Hash[@_enum_hash.map do |key, enum|
- [key, enum.value]
- end]
+ @_enum_hash.transform_values(&:value)
end
private
diff --git a/lib/ruby-enum/enum/case.rb b/lib/ruby-enum/enum/case.rb
new file mode 100644
index 0000000..79e1cab
--- /dev/null
+++ b/lib/ruby-enum/enum/case.rb
@@ -0,0 +1,84 @@
+# frozen_string_literal: true
+
+module Ruby
+ module Enum
+ ##
+ # Adds a method to an enum class that allows for exhaustive matching on a value.
+ #
+ # @example
+ # class Color
+ # include Ruby::Enum
+ # include Ruby::Enum::Case
+ #
+ # define :RED, :red
+ # define :GREEN, :green
+ # define :BLUE, :blue
+ # define :YELLOW, :yellow
+ # end
+ #
+ # Color.case(Color::RED, {
+ # [Color::RED, Color::GREEN] => -> { "red or green" },
+ # Color::BLUE => -> { "blue" },
+ # Color::YELLOW => -> { "yellow" },
+ # })
+ #
+ # Reserves the :else key for a default case:
+ # Color.case(Color::RED, {
+ # [Color::RED, Color::GREEN] => -> { "red or green" },
+ # else: -> { "blue or yellow" },
+ # })
+ module Case
+ def self.included(klass)
+ klass.extend(ClassMethods)
+ end
+
+ ##
+ # @see Ruby::Enum::Case
+ module ClassMethods
+ class ValuesNotDefinedError < StandardError
+ end
+
+ class NotAllCasesHandledError < StandardError
+ end
+
+ def case(value, cases)
+ validate_cases(cases)
+
+ filtered_cases = cases.select do |values, _proc|
+ values = [values] unless values.is_a?(Array)
+ values.include?(value)
+ end
+
+ return call_proc(cases[:else], value) if filtered_cases.none?
+
+ results = filtered_cases.map { |_values, proc| call_proc(proc, value) }
+
+ # Return the first result if there is only one result
+ results.size == 1 ? results.first : results
+ end
+
+ private
+
+ def call_proc(proc, value)
+ return if proc.nil?
+
+ if proc.arity == 1
+ proc.call(value)
+ else
+ proc.call
+ end
+ end
+
+ def validate_cases(cases)
+ all_values = cases.keys.flatten - [:else]
+ else_defined = cases.key?(:else)
+ superfluous_values = all_values - values
+ missing_values = values - all_values
+
+ raise ValuesNotDefinedError, "Value(s) not defined: #{superfluous_values.join(', ')}" if superfluous_values.any?
+ raise NotAllCasesHandledError, "Not all cases handled: #{missing_values.join(', ')}" if missing_values.any? && !else_defined
+ end
+ end
+ end
+ end
+end
diff --git a/lib/ruby-enum/enum/i18n_mock.rb b/lib/ruby-enum/enum/i18n_mock.rb
new file mode 100644
index 0000000..b9adbb9
--- /dev/null
+++ b/lib/ruby-enum/enum/i18n_mock.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+# :nocov:
+module Ruby
+ module Enum
+ ##
+ # Mock I18n module in case the i18n gem is not available.
+ module I18nMock
+ def self.load_path
+ []
+ end
+
+ def self.translate(key, _options = {})
+ key
+ end
+ end
+ end
+end
+# :nocov:
diff --git a/lib/ruby-enum/errors/base.rb b/lib/ruby-enum/errors/base.rb
index c4a726c..5ab2ee1 100644
--- a/lib/ruby-enum/errors/base.rb
+++ b/lib/ruby-enum/errors/base.rb
@@ -22,13 +22,13 @@ module Ruby
@summary = create_summary(key, attributes)
@resolution = create_resolution(key, attributes)
- "\nProblem:\n #{@problem}"\
+ "\nProblem:\n #{@problem}" \
"\nSummary:\n #{@summary}" + "\nResolution:\n #{@resolution}"
end
private
- BASE_KEY = 'ruby.enum.errors.messages' #:nodoc:
+ BASE_KEY = 'ruby.enum.errors.messages' # :nodoc:
# Given the key of the specific error and the options hash, translate the
# message.
@@ -39,7 +39,7 @@ module Ruby
#
# Returns a localized error message string.
def translate(key, options)
- ::I18n.translate("#{BASE_KEY}.#{key}", **{ locale: :en }.merge(options)).strip
+ Ruby::Enum.i18n.translate("#{BASE_KEY}.#{key}", locale: :en, **options).strip
end
# Create the problem.
diff --git a/lib/ruby-enum/version.rb b/lib/ruby-enum/version.rb
index 1a3c94b..a329355 100644
--- a/lib/ruby-enum/version.rb
+++ b/lib/ruby-enum/version.rb
@@ -2,6 +2,6 @@
module Ruby
module Enum
- VERSION = '0.9.0'
+ VERSION = '1.0.0'
end
end
diff --git a/pkg/ruby-enum-0.8.0.gem b/pkg/ruby-enum-0.8.0.gem
deleted file mode 100644
index 1949d89..0000000
--- a/pkg/ruby-enum-0.8.0.gem
+++ /dev/null
Binary files differ
diff --git a/ruby-enum.gemspec b/ruby-enum.gemspec
index 9eee0bd..50da6a9 100644
--- a/ruby-enum.gemspec
+++ b/ruby-enum.gemspec
@@ -10,10 +10,11 @@ Gem::Specification.new do |s|
s.email = 'dblock@dblock.org'
s.platform = Gem::Platform::RUBY
s.required_rubygems_version = '>= 1.3.6'
+ s.required_ruby_version = '>= 2.7'
s.files = Dir['**/*']
s.require_paths = ['lib']
s.homepage = 'http://github.com/dblock/ruby-enum'
s.licenses = ['MIT']
s.summary = 'Enum-like behavior for Ruby.'
- s.add_dependency 'i18n'
+ s.metadata['rubygems_mfa_required'] = 'true'
end
diff --git a/spec/ruby-enum/enum/case_spec.rb b/spec/ruby-enum/enum/case_spec.rb
new file mode 100644
index 0000000..8e7c588
--- /dev/null
+++ b/spec/ruby-enum/enum/case_spec.rb
@@ -0,0 +1,118 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ruby::Enum::Case do
+ test_enum =
+ Class.new do
+ include Ruby::Enum
+ include Ruby::Enum::Case
+
+ define :RED, :red
+ define :GREEN, :green
+ define :BLUE, :blue
+ end
+
+ describe '.case' do
+ context 'when all cases are defined' do
+ subject { test_enum.case(test_enum::RED, cases) }
+
+ let(:cases) do
+ {
+ [test_enum::RED, test_enum::GREEN] => -> { 'red or green' },
+ test_enum::BLUE => -> { 'blue' }
+ }
+ end
+
+ it { is_expected.to eq('red or green') }
+
+ context 'when the value is nil' do
+ subject { test_enum.case(nil, cases) }
+
+ it { is_expected.to be_nil }
+ end
+
+ context 'when the value is empty' do
+ subject { test_enum.case('', cases) }
+
+ it { is_expected.to be_nil }
+ end
+
+ context 'when the value is the value of the enum' do
+ subject { test_enum.case(:red, cases) }
+
+ it { is_expected.to eq('red or green') }
+ end
+
+ context 'when the value is used inside the lambda' do
+ subject { test_enum.case(test_enum::RED, cases) }
+
+ let(:cases) do
+ {
+ [test_enum::RED, test_enum::GREEN] => ->(color) { "is #{color}" },
+ test_enum::BLUE => -> { 'blue' }
+ }
+ end
+
+ it { is_expected.to eq('is red') }
+ end
+ end
+
+ context 'when there are mutliple matches' do
+ subject do
+ test_enum.case(
+ test_enum::RED,
+ {
+ [test_enum::RED, test_enum::GREEN] => -> { 'red or green' },
+ test_enum::RED => -> { 'red' },
+ test_enum::BLUE => -> { 'blue' }
+ }
+ )
+ end
+
+ it { is_expected.to eq(['red or green', 'red']) }
+ end
+
+ context 'when not all cases are defined' do
+ it 'raises an error' do
+ expect do
+ test_enum.case(
+ test_enum::RED,
+ { [test_enum::RED, test_enum::GREEN] => -> { 'red or green' } }
+ )
+ end.to raise_error(Ruby::Enum::Case::ClassMethods::NotAllCasesHandledError)
+ end
+ end
+
+ context 'when not all cases are defined but :else is specified (default case)' do
+ it 'does not raise an error' do
+ expect do
+ result = test_enum.case(
+ test_enum::BLUE,
+ {
+ [test_enum::RED, test_enum::GREEN] => -> { 'red or green' },
+ else: -> { 'blue' }
+ }
+ )
+
+ expect(result).to eq('blue')
+ end.not_to raise_error
+ end
+ end
+
+ context 'when a superfluous case is defined' do
+ it 'raises an error' do
+ expect do
+ test_enum.case(
+ test_enum::RED,
+ {
+ [test_enum::RED, test_enum::GREEN] => -> { 'red or green' },
+ test_enum::BLUE => -> { 'blue' },
+ :something => -> { 'green' }
+ }
+ )
+ end.to raise_error(Ruby::Enum::Case::ClassMethods::ValuesNotDefinedError)
+ end
+ end
+ end
+end
diff --git a/spec/ruby-enum/enum_spec.rb b/spec/ruby-enum/enum_spec.rb
index 6a7e560..bd0f1c9 100644
--- a/spec/ruby-enum/enum_spec.rb
+++ b/spec/ruby-enum/enum_spec.rb
@@ -22,10 +22,28 @@ describe Ruby::Enum do
expect(Colors::RED).to eq 'red'
expect(Colors::GREEN).to eq 'green'
end
- it 'raises UninitializedConstantError on an invalid constant' do
- expect { Colors::ANYTHING }.to raise_error Ruby::Enum::Errors::UninitializedConstantError, /The constant Colors::ANYTHING has not been defined./
+
+ context 'when the i18n gem is loaded' do
+ it 'raises UninitializedConstantError on an invalid constant' do
+ expect do
+ Colors::ANYTHING
+ end.to raise_error Ruby::Enum::Errors::UninitializedConstantError, /The constant Colors::ANYTHING has not been defined./
+ end
end
- context '#each' do
+
+ context 'when the i18n gem is not loaded' do
+ before do
+ allow(described_class).to receive(:i18n).and_return(Ruby::Enum::I18nMock)
+ end
+
+ it 'raises UninitializedConstantError on an invalid constant' do
+ expect do
+ Colors::ANYTHING
+ end.to raise_error Ruby::Enum::Errors::UninitializedConstantError, /ruby.enum.errors.messages.uninitialized_constant.summary/
+ end
+ end
+
+ describe '#each' do
it 'iterates over constants' do
keys = []
enum_keys = []
@@ -40,7 +58,8 @@ describe Ruby::Enum do
expect(enum_values).to eq %w[red green]
end
end
- context '#map' do
+
+ describe '#map' do
it 'maps constants' do
key_key_values = Colors.map do |key, enum|
[key, enum.key, enum.value]
@@ -50,103 +69,152 @@ describe Ruby::Enum do
expect(key_key_values[1]).to eq [:GREEN, :GREEN, 'green']
end
end
- context '#parse' do
+
+ describe '#parse' do
it 'parses exact value' do
expect(Colors.parse('red')).to eq(Colors::RED)
end
+
it 'is case-insensitive' do
expect(Colors.parse('ReD')).to eq(Colors::RED)
end
+
it 'returns nil for a null value' do
expect(Colors.parse(nil)).to be_nil
end
+
it 'returns nil for an invalid value' do
expect(Colors.parse('invalid')).to be_nil
end
end
- context '#key?' do
+
+ describe '#key?' do
it 'returns true for valid keys accessed directly' do
Colors.keys.each do |key| # rubocop:disable Style/HashEachMethods
- expect(Colors.key?(key)).to eq(true)
+ expect(Colors.key?(key)).to be(true)
end
end
+
it 'returns true for valid keys accessed via each_keys' do
Colors.each_key do |key|
- expect(Colors.key?(key)).to eq(true)
+ expect(Colors.key?(key)).to be(true)
end
end
+
it 'returns false for invalid keys' do
- expect(Colors.key?(:NOT_A_KEY)).to eq(false)
+ expect(Colors.key?(:NOT_A_KEY)).to be(false)
end
end
- context '#value' do
+
+ describe '#value' do
it 'returns string values for keys' do
Colors.each do |key, enum|
expect(Colors.value(key)).to eq(enum.value)
end
end
+
it 'returns nil for an invalid key' do
expect(Colors.value(:NOT_A_KEY)).to be_nil
end
end
- context '#value?' do
+
+ describe '#value?' do
it 'returns true for valid values accessed directly' do
Colors.values.each do |value| # rubocop:disable Style/HashEachMethods
- expect(Colors.value?(value)).to eq(true)
+ expect(Colors.value?(value)).to be(true)
end
end
+
it 'returns true for valid values accessed via each_value' do
Colors.each_value do |value|
- expect(Colors.value?(value)).to eq(true)
+ expect(Colors.value?(value)).to be(true)
end
end
+
it 'returns false for invalid values' do
- expect(Colors.value?('I am not a value')).to eq(false)
+ expect(Colors.value?('I am not a value')).to be(false)
end
end
- context '#key' do
+
+ describe '#key' do
it 'returns enum instances for values' do
- Colors.each do |_, enum|
+ Colors.each do |_, enum| # rubocop:disable Style/HashEachMethods
expect(Colors.key(enum.value)).to eq(enum.key)
end
end
+
it 'returns nil for an invalid value' do
expect(Colors.key('invalid')).to be_nil
end
end
- context '#keys' do
+
+ describe '#keys' do
it 'returns keys' do
expect(Colors.keys).to eq(%i[RED GREEN])
end
end
- context '#values' do
+
+ describe '#values' do
it 'returns values' do
expect(Colors.values).to eq(%w[red green])
end
end
- context '#to_h' do
+
+ describe '#to_h' do
it 'returns a hash of key:values' do
expect(Colors.to_h).to eq(RED: 'red', GREEN: 'green')
end
end
- context 'on duplicate keys' do
- it 'raises DuplicateKeyError' do
- expect do
- Colors.class_eval do
- define :RED, 'some'
- end
- end.to raise_error Ruby::Enum::Errors::DuplicateKeyError, /The constant Colors::RED has already been defined./
+ context 'when a duplicate key is used' do
+ context 'when the i18n gem is loaded' do
+ it 'raises DuplicateKeyError' do
+ expect do
+ Colors.class_eval do
+ define :RED, 'some'
+ end
+ end.to raise_error Ruby::Enum::Errors::DuplicateKeyError, /The constant Colors::RED has already been defined./
+ end
+ end
+
+ context 'when the i18n gem is not loaded' do
+ before do
+ allow(described_class).to receive(:i18n).and_return(Ruby::Enum::I18nMock)
+ end
+
+ it 'raises DuplicateKeyError' do
+ expect do
+ Colors.class_eval do
+ define :RED, 'some'
+ end
+ end.to raise_error Ruby::Enum::Errors::DuplicateKeyError, /ruby.enum.errors.messages.duplicate_key.message/
+ end
end
end
- context 'on duplicate values' do
- it 'raises a DuplicateValueError' do
- expect do
- Colors.class_eval do
- define :Other, 'red'
- end
- end.to raise_error Ruby::Enum::Errors::DuplicateValueError, /The value red has already been defined./
+ context 'when a duplicate value is used' do
+ context 'when the i18n gem is loaded' do
+ it 'raises a DuplicateValueError' do
+ expect do
+ Colors.class_eval do
+ define :Other, 'red'
+ end
+ end.to raise_error Ruby::Enum::Errors::DuplicateValueError, /The value red has already been defined./
+ end
+ end
+
+ context 'when the i18n gem is not loaded' do
+ before do
+ allow(described_class).to receive(:i18n).and_return(Ruby::Enum::I18nMock)
+ end
+
+ it 'raises a DuplicateValueError' do
+ expect do
+ Colors.class_eval do
+ define :Other, 'red'
+ end
+ end.to raise_error Ruby::Enum::Errors::DuplicateValueError, /ruby.enum.errors.messages.duplicate_value.summary/
+ end
end
end
@@ -176,11 +244,14 @@ describe Ruby::Enum do
it 'contains its own enums' do
expect(FirstSubclass::ORANGE).to eq 'orange'
end
+
it 'parent class should not have enums defined in child classes' do
expect { Colors::ORANGE }.to raise_error Ruby::Enum::Errors::UninitializedConstantError
end
- context 'Given a 2 level depth subclass' do
+
+ context 'when defining a 2 level depth subclass' do
subject { SecondSubclass }
+
it 'contains its own enums and all the enums defined in the parent classes' do
expect(subject::RED).to eq 'red'
expect(subject::GREEN).to eq 'green'
@@ -227,6 +298,7 @@ describe Ruby::Enum do
define :undefined
end
subject { States }
+
it 'behaves like an enum' do
expect(subject.created).to eq 'Created'
expect(subject.published).to eq 'Published'
diff --git a/spec_i18n/Gemfile b/spec_i18n/Gemfile
new file mode 100644
index 0000000..84d9f8e
--- /dev/null
+++ b/spec_i18n/Gemfile
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+source 'http://rubygems.org'
+
+gemspec path: '../', name: 'ruby-enum'
+
+# This Gemfile should not include any gem that has i18n as a dependency.
+gem 'rake'
+gem 'rspec', '~> 3.0'
diff --git a/spec_i18n/Rakefile b/spec_i18n/Rakefile
new file mode 100644
index 0000000..9827cdf
--- /dev/null
+++ b/spec_i18n/Rakefile
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+require 'rubygems'
+
+require 'rspec/core'
+require 'rspec/core/rake_task'
+
+RSpec::Core::RakeTask.new(:spec) do |spec|
+ spec.pattern = FileList['spec/**/*_spec.rb']
+end
+
+task default: %i[spec]
diff --git a/spec_i18n/spec/i18n_spec.rb b/spec_i18n/spec/i18n_spec.rb
new file mode 100644
index 0000000..653b9ed
--- /dev/null
+++ b/spec_i18n/spec/i18n_spec.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+test_class = Class.new do
+ include Ruby::Enum
+
+ define :RED, 'red'
+ define :GREEN, 'green'
+end
+
+describe Ruby::Enum do
+ context 'when the i18n gem is not loaded' do
+ it 'raises UninitializedConstantError on an invalid constant' do
+ expect do
+ test_class::ANYTHING
+ end.to raise_error Ruby::Enum::Errors::UninitializedConstantError, /ruby.enum.errors.messages.uninitialized_constant.summary/
+ end
+
+ context 'when a duplicate key is used' do
+ before do
+ allow(described_class).to receive(:i18n).and_return(Ruby::Enum::I18nMock)
+ end
+
+ it 'raises DuplicateKeyError' do
+ expect do
+ test_class.class_eval do
+ define :RED, 'some'
+ end
+ end.to raise_error Ruby::Enum::Errors::DuplicateKeyError, /ruby.enum.errors.messages.duplicate_key.message/
+ end
+ end
+
+ context 'when a duplicate value is used' do
+ before do
+ allow(described_class).to receive(:i18n).and_return(Ruby::Enum::I18nMock)
+ end
+
+ it 'raises a DuplicateValueError' do
+ expect do
+ test_class.class_eval do
+ define :Other, 'red'
+ end
+ end.to raise_error Ruby::Enum::Errors::DuplicateValueError, /ruby.enum.errors.messages.duplicate_value.summary/
+ end
+ end
+ end
+end
diff --git a/spec_i18n/spec/spec_helper.rb b/spec_i18n/spec/spec_helper.rb
new file mode 100644
index 0000000..cf56090
--- /dev/null
+++ b/spec_i18n/spec/spec_helper.rb
@@ -0,0 +1,8 @@
+# frozen_string_literal: true
+
+$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', '..', 'lib'))
+
+require 'rubygems'
+
+require 'rspec'
+require 'ruby-enum'