diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6592e6d..66c63e9 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,11 +1,9 @@ name: Release Gem on: - push: - tags: - - 'v*.*.*' - branches: - - main + release: + types: + - created permissions: contents: read @@ -14,9 +12,6 @@ permissions: jobs: tests: uses: ./.github/workflows/ruby-tests.yml - publish: - needs: tests - uses: ./.github/workflows/publish-gem.yml documentation: - needs: publish + needs: tests uses: ./.github/workflows/create-doc-page.yml diff --git a/.github/workflows/version-bump.yml b/.github/workflows/version-bump.yml new file mode 100644 index 0000000..e2d598d --- /dev/null +++ b/.github/workflows/version-bump.yml @@ -0,0 +1,69 @@ +name: Bump Version + +on: + pull_request: + types: + - closed + +jobs: + bump_version: + name: Build + Publish + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + if: > + github.event.pull_request.merged == true && + contains(join(github.event.pull_request.labels.*.name, ','), 'version:major') || + contains(join(github.event.pull_request.labels.*.name, ','), 'version:minor') || + contains(join(github.event.pull_request.labels.*.name, ','), 'version:patch') + + steps: + - name: Check out the repository + uses: actions/checkout@v4 + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: 2.6.10 + + - name: Bump Version + id: bump_version + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + PR_NUMBER=$(jq --raw-output .number "$GITHUB_EVENT_PATH") + LABELS=$(curl -s \ + -H "Authorization: token $GITHUB_TOKEN" \ + -H "Accept: application/vnd.github+json" \ + https://api.github.com/repos/${{ github.repository }}/issues/$PR_NUMBER/labels | jq -r '.[].name') + + echo "PR Labels: $LABELS" + + for LABEL in $LABELS; do + case "$LABEL" in + "version:major") + rake version:major + ;; + "version:minor") + rake version:minor + ;; + "version:patch") + rake version:patch + ;; + *) + echo "No matching version bump task for label $LABEL" + ;; + esac + done + - name: Commit and push changes + run: | + git config --global user.name 'github-actions[bot]' + git config --global user.email 'github-actions[bot]@users.noreply.github.com' + git add lib/version.rb + git commit -m "Bump version to ${{ steps.bump_version.outputs.new_version }}" + git push + - name: Create new tag + run: | + new_version=${{ steps.bump_version.outputs.new_version }} + git tag "v$new_version" + git push origin "v$new_version" diff --git a/.gitignore b/.gitignore index 8be5300..5838b22 100644 --- a/.gitignore +++ b/.gitignore @@ -48,8 +48,8 @@ build-iPhoneSimulator/ /vendor/bundle /lib/bundler/man/ -# Local development script ignored by default since it's only for local development. -/development.rb +# Local development folder ignored by default since it's only for local development. +/development # for a library or gem, you might want to ignore these files since the code is # intended to run in multiple environments; otherwise, check them in: diff --git a/Gemfile b/Gemfile index cc97dec..7b70859 100644 --- a/Gemfile +++ b/Gemfile @@ -5,13 +5,15 @@ source 'https://rubygems.org' # Specify your gem's dependencies in mp_utils.gemspec gemspec -group :test do +group :tests do gem 'rspec', require: false gem 'rubocop-rspec', require: false gem 'simplecov', require: false end -gem 'rake' -gem 'rubocop' -gem 'solargraph' -gem 'yard' +group :development do + gem 'rake' + gem 'rubocop' + gem 'solargraph' + gem 'yard' +end diff --git a/Rakefile b/Rakefile index 58c1486..1511a13 100644 --- a/Rakefile +++ b/Rakefile @@ -1,45 +1,50 @@ # frozen_string_literal: true +require 'rspec/core/rake_task' +require 'rubocop/rake_task' +require 'bundler/gem_tasks' require 'rake/clean' +require 'rake' -CLEAN.include %w[pkg coverage *.gem] - -require 'bundler/gem_tasks' -require 'rspec/core/rake_task' +require_relative 'lib/mp_utils' +require_relative 'lib/version' +CLEAN.include %w[pkg coverage *.gem doc .yardoc] RSpec::Core::RakeTask.new(:spec) - -require 'rubocop/rake_task' - RuboCop::RakeTask.new task default: %i[spec rubocop] -require_relative 'lib/version' -require 'rake' - namespace :version do %i[major minor patch].each do |part| desc "Bump #{part} version" task part do - current_version = MPUtils::VERSION.split('.').map(&:to_i) - new_version = case part - when :major - [current_version[0] + 1, 0, 0] - when :minor - [current_version[0], current_version[1] + 1, 0] - when :patch - current_version[0..1] + [current_version[2] + 1] - end.join('.') - + version = VersionManager.new(MPUtils::VERSION) path = File.join('lib', 'version.rb') + + case part + when :major + version.increment_major + when :minor + version.increment_minor + when :patch + version.increment_pathc + end + content = File.read(path) - puts content - content.gsub!(/VERSION.+'\d+\.\d+\.\d+'/, "VERSION = '#{new_version}'") - puts content + content.gsub!(/VERSION.+'#{MPUtils::VERSION}'/, "VERSION = '#{version}'") File.open(path, 'w') { |file| file << content } - puts "Version bumped to #{new_version}" + system("echo \"::set-output name=new_version::#{version}\"") end end end + +namespace :doc do + desc 'Bump version' + task :test do + system('yard doc') + system('open "http://localhost:8808"') + system('yard server') + end +end diff --git a/lib/mp_utils.rb b/lib/mp_utils.rb index 4f70f36..3b48c0b 100644 --- a/lib/mp_utils.rb +++ b/lib/mp_utils.rb @@ -1,7 +1,10 @@ # frozen_string_literal: true -require 'utils/key' -require 'utils/array' -require 'utils/message' -require 'utils/question' -require 'resources/path_helper' +require_relative 'utils/key' +require_relative 'utils/ansi' +require_relative 'utils/array' +require_relative 'utils/message' +require_relative 'utils/question' +require_relative 'utils/version_manager' +require_relative 'utils/ansi_style_manager' +require_relative 'resources/path_helper' diff --git a/lib/utils/ansi.rb b/lib/utils/ansi.rb new file mode 100644 index 0000000..ea405fa --- /dev/null +++ b/lib/utils/ansi.rb @@ -0,0 +1,125 @@ +# frozen_string_literal: true + +require_relative 'constants' + +# The ANSI class is responsible for generating ANSI codes for text styling in terminals. +# It allows the combination of multiple style and color codes. +# +# @example +# ansi = ANSI.new(:bold) +# puts ansi.to_s # => "\e[1m" +# +# @example +# ansi = ANSI.new([:bold, :red]) +# puts ansi.to_s # => "\e[1;31m" +class ANSI + # Hash that maps style and color names to their respective ANSI codes. + CODES_HASH = { + reset_all: 0, + + # Effects + bold: 1, + faint: 2, + italic: 3, + underlined: 4, + blinking: 5, + inverse: 7, + hidden: 8, + strike: 9, + plain: 21, + + # Remove Effects + remove_bold: 22, + remove_faint: 22, + remove_italic: 23, + remove_underlined: 24, + remove_blinking: 25, + remove_inverse: 27, + remove_hidden: 28, + remove_strike: 29, + remove_plain: 24, + + # Colors + black: 30, + red: 31, + green: 32, + yellow: 33, + blue: 34, + magenta: 35, + cyan: 36, + white: 37, + reset_color: 39, + rgb_format: [38, 2], + numeric_format: [38, 5], + + # Background Colors + background_black: 40, + background_red: 41, + background_green: 42, + background_yellow: 43, + background_blue: 44, + background_magenta: 45, + background_cyan: 46, + background_white: 47, + background_rgb_format: [48, 2], + background_numeric_format: [48, 5], + reset_background: 49 + }.freeze + + # @return [Array] the ANSI codes stored in the instance. + attr_reader :codes + + # Initializes a new instance of the ANSI class. + # + # @param code [Array, Symbol, String] One or more ANSI codes represented as symbols, integers, or strings. + def initialize(code) + @codes = if code.is_a?(Array) + ANSI.normalize_array_codes(code) + elsif code.is_a?(Symbol) + [CODES_HASH[code]] + else + ANSI.normalize_array_codes(code.split(';')) + end + end + + # Adds ANSI codes from another instance of the ANSI class. + # + # @param ansi [ANSI] The instance of the ANSI class whose codes will be added. + # @return [ANSI] A new instance of the ANSI class with the combined codes. + # @raise [RuntimeError] If the argument is not an instance of the ANSI class. + def append(ansi) + raise 'Needs be an instance of ANSI' unless ansi.is_a?(ANSI) + + ANSI.new(@codes.union(ansi.codes)) + end + + # Adds ANSI codes from another instance of the ANSI class and updates the current instance. + # + # @param ansi [ANSI] The instance of the ANSI class whose codes will be added. + # @return [void] + def append!(ansi) + @codes = append(ansi).codes + end + + # Converts the ANSI codes stored in the instance to a formatted string. + # + # @return [String] The formatted string with the ANSI codes. + def to_s + "\e[#{@codes.flatten.join(';')}m" + end + + # Normalizes an array of codes, converting symbols and strings to their respective ANSI codes. + # + # @param array [Array] An array of codes to be normalized. + # @return [Array] The normalized array of ANSI codes. + def self.normalize_array_codes(array) + array.map do |value| + next normalize_array_codes(value) if value.is_a?(Array) + next value if value.is_a?(Integer) + next CODES_HASH[value] if value.is_a?(Symbol) + next value.to_i if value.match?(CONSTANTS::ONLY_DIGITS_REGEX) + + CODES_HASH[value.to_sym] + end + end +end diff --git a/lib/utils/ansi_style_manager.rb b/lib/utils/ansi_style_manager.rb new file mode 100644 index 0000000..1ac19b6 --- /dev/null +++ b/lib/utils/ansi_style_manager.rb @@ -0,0 +1,137 @@ +# frozen_string_literal: true + +require_relative 'constants' +require_relative 'ansi' + +# The ANSIStyleManager class is responsible for managing and applying ANSI styles to a given string. +# It can replace tokens in the string with corresponding ANSI codes for colors and effects. +# +# @example +# manager = ANSIStyleManager.new("Hello World") +# puts manager.to_s # => "Hello \e[31mWorld\e[39m" +class ANSIStyleManager + # @return [String] the string to which ANSI styles will be applied. + attr_reader :string + + # Initializes a new instance of the ANSIStyleManager class. + # + # @param string [String] The string to which ANSI styles will be applied. + # @raise [RuntimeError] If the argument is not a string. + def initialize(string) + raise 'Need initialize with a string' unless string.is_a?(String) + + @string = String.new(string) + end + + # Replaces all color and effect tokens in the string with corresponding ANSI codes. + # + # @return [void] + def replace_all_tokens! + replace_color_tokens! + replace_effect_tokens! + end + + # Replaces all color tokens in the string with corresponding ANSI codes. + # + # @return [void] + def replace_color_tokens! + scan_while_find(CONSTANTS::ANSI::COLORS) do |value| + colors = value.first.split(':') + + replace_tokens_with!( + ansi_token: color_prefix(color: colors[0], background: colors[1]), + ansi_reset_token: ANSI.new(%i[reset_background reset_color]), + to_replace: "#{value.last}", + preserve_reset_token: false, + text: value.last + ) + end + end + + # Replaces all effect tokens in the string with corresponding ANSI codes. + # + # @return [void] + def replace_effect_tokens! + scan_while_find(CONSTANTS::ANSI::EFFECTS) do |value| + replace_tokens_with!( + ansi_reset_token: ANSI.new("remove_#{value.first.downcase}"), + to_replace: "#{value.last}", + ansi_token: ANSI.new(value.first.downcase), + preserve_reset_token: true, + text: value.last + ) + end + end + + # Converts the string with all tokens replaced by corresponding ANSI codes. + # + # @return [String] The string with ANSI codes applied. + def to_s + replace_all_tokens! + @string + end + + private + + # Generates the ANSI prefix for a given color and background. + # + # @param color [String] The color name or code. + # @param background [String, nil] The background color name or code. + # @return [ANSI] The ANSI instance representing the color and background. + def color_prefix(color:, background:) + color_ansi = generate_color_ansi(color, is_background: false) + return color_ansi.to_s if background.nil? + + generate_color_ansi(background, is_background: true).append(color_ansi) + end + + # Generates the ANSI instance for a given color. + # + # @param color [String] The color name or code. + # @param is_background [Boolean] Whether the color is for the background. + # @return [ANSI] The ANSI instance representing the color. + def generate_color_ansi(color, is_background:) + digit_values = color.scan(CONSTANTS::ANSI::COLOR_DIGITS_REGEX).flatten.compact + + if [1, 3].include?(digit_values.count) + format = "#{digit_values.count == 1 ? 'numeric' : 'rgb'}_format" + format = "#{is_background ? 'background_' : ''}#{format}" + + return ANSI.new([format, digit_values]) + elsif color.match?(/^reset$/) + return ANSI.new(is_background ? :reset_background : :reset_color) + end + + ANSI.new(is_background ? "background_#{color}" : color) + end + + # Replaces tokens in the string with corresponding ANSI codes. + # + # @param text [String] The text to be styled. + # @param to_replace [String] The token to be replaced. + # @param ansi_token [ANSI] The ANSI instance representing the style. + # @param ansi_reset_token [ANSI] The ANSI instance representing the reset style. + # @param preserve_reset_token [Boolean] Whether to preserve the reset token in the text. + # @return [void] + def replace_tokens_with!(text:, to_replace:, ansi_token:, ansi_reset_token:, preserve_reset_token:) + colored_text = text.gsub(ansi_reset_token.to_s, "#{ansi_reset_token}#{ansi_token}") if preserve_reset_token + colored_text = text.gsub(ansi_reset_token.to_s, ansi_token.to_s) unless preserve_reset_token + @string.gsub!(to_replace, "#{ansi_token}#{colored_text}#{ansi_reset_token}") + end + + # Scans the string for tokens matching the given regex and processes them with the provided block. + # + # @param scan_regex [Regexp] The regex to scan for tokens. + # @yieldparam value [Array] The matched tokens. + # @return [void] + def scan_while_find(scan_regex, &block) + result = @string.scan(scan_regex) + while result.count.positive? + result.each do |value| + block.call(value) + end + + result = @string.scan(scan_regex) + end + end +end diff --git a/lib/utils/constants.rb b/lib/utils/constants.rb new file mode 100644 index 0000000..a194c2f --- /dev/null +++ b/lib/utils/constants.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +# @!visibility private +module CONSTANTS + ONLY_DIGITS_REGEX = /^\d+$/.freeze + + # @!visibility private + module ANSI + COLOR_DIGITS_REGEX = /^(\d+);(\d+);(\d+)|(\d+)$/.freeze + COLOR_TOKEN_VALUE = '(?:[\w|\d]+|\d+\;\d+\;\d+)(?::[\w|\d]+|:\d+;\d+;\d+)?' + COLORS = %r{((?:(?!|).)*)}m.freeze + EFFECTS = %r{((?:(?!|).)*)}m.freeze + end +end diff --git a/lib/utils/key.rb b/lib/utils/key.rb index 58b1785..7825c89 100644 --- a/lib/utils/key.rb +++ b/lib/utils/key.rb @@ -56,8 +56,8 @@ class Key def self.find_keys_in(value) ep = Regexp.escape(prefix) es = Regexp.escape(suffix) - value.to_s.scan(/#{ep}[^#{ep}#{es}]+#{es}/).map do |key| - Key.new(key.gsub(/(#{ep})|(#{es})/, '')) + value.to_s.scan(/#{ep}([^#{ep}#{es}]+)#{es}/).map do |key| + Key.new(key.first) end end diff --git a/lib/utils/message.rb b/lib/utils/message.rb index 1a4c4bd..e2eaf30 100644 --- a/lib/utils/message.rb +++ b/lib/utils/message.rb @@ -123,11 +123,18 @@ def recover_message_with(file_name) end # Reads and returns the content of a message file located at a specific path. + # If the file name have the suffix ".aas.txt", the ANSIStyleManager will be applied to the file. # # @param path [String] The path where the message file is located. # @param file_name [String] The name of the file to be read. # @return [String, nil] The content of the message file, or nil if the file does not exist. def recover_content_with(path, file_name) + aas_file_path = File.join(path, "#{file_name}.aas.txt") + if File.exist?(aas_file_path) + content = File.read(aas_file_path) + return ANSIStyleManager.new(content).to_s + end + file_path = File.join(path, "#{file_name}.txt") return nil unless File.exist?(file_path) diff --git a/lib/utils/version_manager.rb b/lib/utils/version_manager.rb new file mode 100644 index 0000000..cc37e1a --- /dev/null +++ b/lib/utils/version_manager.rb @@ -0,0 +1,58 @@ +# frozen_string_literal: true + +# Manages software versions with Major, Minor, and Patch components. +class VersionManager + attr_reader :major, :minor, :patch + + # Initializes a new instance of VersionManager. + # + # @param major [Integer, String] The major version or a string in the format "major.minor.patch". + # @param minor [Integer] The minor version (optional if major is a string). + # @param patch [Integer] The patch version (optional if major is a string). + def initialize(major = 0, minor = 0, patch = 0) + if major.is_a?(String) + parse_version_string(major) + else + @major = major + @minor = minor + @patch = patch + end + end + + # Increments the major version and resets minor and patch to 0. + def increment_major + @major += 1 + @minor = 0 + @patch = 0 + end + + # Increments the minor version and resets patch to 0. + def increment_minor + @minor += 1 + @patch = 0 + end + + # Increments the patch version. + def increment_patch + @patch += 1 + end + + # Returns the version as a string in the format "major.minor.patch". + # + # @return [String] The formatted version. + def to_s + "#{@major}.#{@minor}.#{@patch}" + end + + private + + # Parses a version string in the format "major.minor.patch". + # + # @param version_string [String] The version string. + def parse_version_string(version_string) + parts = version_string.split('.') + @major = parts[0].to_i + @minor = parts[1].to_i + @patch = parts[2].to_i + end +end diff --git a/mp-utils.gemspec b/mp-utils.gemspec index f3569d2..7c25ff8 100644 --- a/mp-utils.gemspec +++ b/mp-utils.gemspec @@ -26,10 +26,4 @@ Gem::Specification.new do |spec| spec.files = Dir[File.join('lib', '**', '*')].select do |path| !Dir.exist?(path) && !['version.rb'].include?(File.basename(path)) end - - # Uncomment to register a new dependency of your gem - # spec.add_dependency "example-gem", "~> 1.0" - - # For more information and examples about making a new gem, check out our - # guide at: https://bundler.io/guides/creating_gem.html end diff --git a/spec/resources/messages/teste_ansi.aas.txt b/spec/resources/messages/teste_ansi.aas.txt new file mode 100644 index 0000000..9d90133 --- /dev/null +++ b/spec/resources/messages/teste_ansi.aas.txt @@ -0,0 +1 @@ +This is a colored ansi test! \ No newline at end of file diff --git a/spec/resources/messages/teste_b_ansi.aas.txt b/spec/resources/messages/teste_b_ansi.aas.txt new file mode 100644 index 0000000..31ee876 --- /dev/null +++ b/spec/resources/messages/teste_b_ansi.aas.txt @@ -0,0 +1 @@ +This is other colored ansi test! \ No newline at end of file diff --git a/spec/utils/ansi_spec.rb b/spec/utils/ansi_spec.rb new file mode 100644 index 0000000..0580317 --- /dev/null +++ b/spec/utils/ansi_spec.rb @@ -0,0 +1,74 @@ +# frozen_string_literal: true + +require_relative '../../lib/utils/ansi' + +RSpec.describe ANSI do + describe '#initialize' do + it 'initializes with a symbol' do + ansi = ANSI.new(:bold) + expect(ansi.codes).to eq([1]) + end + + it 'initializes with an array of symbols' do + ansi = ANSI.new(%i[bold red]) + expect(ansi.codes).to eq([1, 31]) + end + + it 'initializes with a string' do + ansi = ANSI.new('bold;red') + expect(ansi.codes).to eq([1, 31]) + end + end + + describe '#append' do + it 'adds codes from another ANSI instance' do + ansi1 = ANSI.new(:bold) + ansi2 = ANSI.new(:red) + combined_ansi = ansi1.append(ansi2) + expect(combined_ansi.codes).to eq([1, 31]) + end + + it 'raises an error if the argument is not an instance of ANSI' do + ansi = ANSI.new(:bold) + expect { ansi.append('not_ansi') }.to raise_error('Needs be an instance of ANSI') + end + end + + describe '#append!' do + it 'adds codes from another ANSI instance and updates the current instance' do + ansi1 = ANSI.new(:bold) + ansi2 = ANSI.new(:red) + ansi1.append!(ansi2) + expect(ansi1.codes).to eq([1, 31]) + end + end + + describe '#to_s' do + it 'converts the ANSI codes to a formatted string' do + ansi = ANSI.new(%i[bold red]) + expect(ansi.to_s).to eq("\e[1;31m") + end + end + + describe '.normalize_array_codes' do + it 'normalizes an array of symbols' do + codes = ANSI.normalize_array_codes(%i[bold red]) + expect(codes).to eq([1, 31]) + end + + it 'normalizes an array of strings' do + codes = ANSI.normalize_array_codes(%w[bold red]) + expect(codes).to eq([1, 31]) + end + + it 'normalizes an array of integers' do + codes = ANSI.normalize_array_codes([1, 31]) + expect(codes).to eq([1, 31]) + end + + it 'normalizes a mixed array of symbols, strings, and integers' do + codes = ANSI.normalize_array_codes([:bold, 'red', 32]) + expect(codes).to eq([1, 31, 32]) + end + end +end diff --git a/spec/utils/ansi_style_manager_spec.rb b/spec/utils/ansi_style_manager_spec.rb new file mode 100644 index 0000000..f76dc92 --- /dev/null +++ b/spec/utils/ansi_style_manager_spec.rb @@ -0,0 +1,119 @@ +# frozen_string_literal: true + +require_relative '../../lib/utils/ansi_style_manager' +require_relative '../../lib/utils/constants' +require_relative '../../lib/utils/ansi' + +RSpec.describe ANSIStyleManager do + describe '#initialize' do + it 'initializes with a string' do + manager = ANSIStyleManager.new('Hello World') + expect(manager.string).to eq('Hello World') + end + + it 'raises an error if initialized with a non-string' do + expect { ANSIStyleManager.new(123) }.to raise_error('Need initialize with a string') + end + end + + describe '#replace_all_tokens!' do + it 'replaces all color and effect tokens in the string' do + manager = ANSIStyleManager.new('Hello World') + manager.replace_all_tokens! + expect(manager.string).to eq("Hello \e[31mWorld\e[49;39m") + end + end + + describe '#replace_color_tokens!' do + it 'replaces color tokens in the string' do + manager = ANSIStyleManager.new('Hello World') + manager.replace_color_tokens! + expect(manager.string).to eq("Hello \e[31mWorld\e[49;39m") + end + end + + describe '#replace_effect_tokens!' do + it 'replaces effect tokens in the string' do + manager = ANSIStyleManager.new('Hello World') + manager.replace_effect_tokens! + expect(manager.string).to eq("Hello \e[1mWorld\e[22m") + end + end + + describe '#color_prefix' do + it 'generates the ANSI prefix for a given color and background' do + manager = ANSIStyleManager.new('') + prefix = manager.send(:color_prefix, color: 'red', background: 'blue') + expect(prefix.to_s).to eq("\e[44;31m") + end + end + + describe '#generate_color_ansi' do + it 'generates the ANSI instance for a given color' do + manager = ANSIStyleManager.new('') + ansi = manager.send(:generate_color_ansi, 'red', is_background: false) + expect(ansi.to_s).to eq("\e[31m") + end + + it 'generates the ANSI instance for a reset color' do + manager = ANSIStyleManager.new('') + ansi = manager.send(:generate_color_ansi, 'reset', is_background: false) + expect(ansi.to_s).to eq("\e[39m") + end + end + + describe '#replace_tokens_with!' do + it 'replaces tokens in the string with corresponding ANSI codes' do + manager = ANSIStyleManager.new('Hello World') + manager.send( + :replace_tokens_with!, + text: 'World', + to_replace: 'World', + + ansi_token: ANSI.new(:red), + ansi_reset_token: ANSI.new(:reset_color), + preserve_reset_token: false + ) + expect(manager.string).to eq("Hello \e[31mWorld\e[39m") + end + end + + # rubocop:disable Layout/LineLength + describe '#to_s' do + it 'Converts the string with all tokens replaced by corresponding ANSI codes' do + manager = ANSIStyleManager.new(' Hello World') + expect(manager.to_s).to eq("\e[3m\e[1m Hello \e[22m \e[31mWorld\e[49;39m\e[23m") + end + + it 'applies ANSI styles correctly for the first input' do + manager = ANSIStyleManager.new('Test color with another color without background!') + expect(manager.to_s).to eq("Test \e[34m color\e[38;5;200m \e[1mwith another color \e[34m without \e[22m\e[49;39mbackground!") + end + + it 'applies ANSI styles correctly for the second input' do + manager = ANSIStyleManager.new('Test color with another color without background!') + expect(manager.to_s).to eq("Test \e[38;2;1;200;3m color\e[33m with another color \e[38;2;1;200;3m without \e[49;39mbackground!") + end + + it 'applies ANSI styles correctly for the third input' do + manager = ANSIStyleManager.new('Test color with another color without background!') + expect(manager.to_s).to eq("Test \e[38;2;1;200;3m color\e[38;5;200m with another color \e[38;2;1;200;3m without \e[49;39mbackground!") + end + + it 'applies ANSI styles correctly for the fourth input' do + manager = ANSIStyleManager.new('Test color with another color without background!') + expect(manager.to_s).to eq("Test \e[34m color\e[38;5;200m with another color \e[34m without \e[49;39mbackground!") + end + + it 'applies ANSI styles correctly for the fifth input' do + manager = ANSIStyleManager.new('Test color with another color with background!') + expect(manager.to_s).to eq("Test \e[47;38;2;1;200;3m color\e[38;5;200m with another color \e[47;38;2;1;200;3m with \e[49;39mbackground!") + end + + it 'applies ANSI styles correctly for the sixth input' do + manager = ANSIStyleManager.new('Test color with another color with background!') + expect(manager.to_s).to eq("Test \e[47;38;5;2m color\e[48;5;10;38;5;5m \e[1mwith another color \e[47;38;5;2m with \e[22m\e[49;39mbackground!") + end + end + # rubocop:enable Layout/LineLength +end diff --git a/spec/utils/message_spec.rb b/spec/utils/message_spec.rb index de5288a..bc94c1f 100644 --- a/spec/utils/message_spec.rb +++ b/spec/utils/message_spec.rb @@ -59,5 +59,17 @@ result = "Hellow World from MPUtils!\nWe hope you are well Alice!" expect(Message.new(message, replaces: replaces).to_s).to eq(result) end + + it 'should apply ANSI Style in .aas.txt files content and replace keys with replaces values.' do + message = "<||teste_ansi||>\n<||hellow_world||>\nWe hope you are well <||username||>!\n<||teste_b_ansi||>" + replaces = { '<||username||>' => 'Alice' } + + Resources.define(custom_path: Resources.library_path.gsub('lib', 'spec')) + + result = "This \e[34mis \e[31ma colored\e[34m ansi test!\e[49;39m\n" + result += "Specs Hellow World!\nWe hope you are well Alice!\n" + result += "This \e[34mis \e[1mother \e[31mcolored\e[34m ansi test!\e[22m\e[49;39m" + expect(Message.new(message, replaces: replaces).to_s).to eq(result) + end end end diff --git a/spec/utils/version_manager_spec.rb b/spec/utils/version_manager_spec.rb new file mode 100644 index 0000000..b80dc20 --- /dev/null +++ b/spec/utils/version_manager_spec.rb @@ -0,0 +1,62 @@ +# frozen_string_literal: true + +require_relative '../../lib/utils/version_manager' + +RSpec.describe VersionManager do + describe '#initialize' do + context 'when initialized with integers' do + it 'sets the major, minor, and patch versions' do + version = VersionManager.new(1, 2, 3) + expect(version.major).to eq(1) + expect(version.minor).to eq(2) + expect(version.patch).to eq(3) + end + end + + context 'when initialized with a version string' do + it 'parses the version string and sets the major, minor, and patch versions' do + version = VersionManager.new('3.4.5') + expect(version.major).to eq(3) + expect(version.minor).to eq(4) + expect(version.patch).to eq(5) + end + end + end + + describe '#increment_major' do + it 'increments the major version and resets minor and patch to 0' do + version = VersionManager.new(1, 2, 3) + version.increment_major + expect(version.major).to eq(2) + expect(version.minor).to eq(0) + expect(version.patch).to eq(0) + end + end + + describe '#increment_minor' do + it 'increments the minor version and resets patch to 0' do + version = VersionManager.new(1, 2, 3) + version.increment_minor + expect(version.major).to eq(1) + expect(version.minor).to eq(3) + expect(version.patch).to eq(0) + end + end + + describe '#increment_patch' do + it 'increments the patch version' do + version = VersionManager.new(1, 2, 3) + version.increment_patch + expect(version.major).to eq(1) + expect(version.minor).to eq(2) + expect(version.patch).to eq(4) + end + end + + describe '#to_s' do + it 'returns the version as a string in the format "major.minor.patch"' do + version = VersionManager.new(1, 2, 3) + expect(version.to_s).to eq('1.2.3') + end + end +end