pax_global_header00006660000000000000000000000064151332335060014513gustar00rootroot0000000000000052 comment=3348721eaae2a8da3f0d2c3c072a8ac7a4de4f01 maxitest-7.1.1/000077500000000000000000000000001513323350600133575ustar00rootroot00000000000000maxitest-7.1.1/.github/000077500000000000000000000000001513323350600147175ustar00rootroot00000000000000maxitest-7.1.1/.github/PULL_REQUEST_TEMPLATE.md000066400000000000000000000003131513323350600205150ustar00rootroot00000000000000Thank you for your contribution! ## Checklist - [ ] Added tests - [ ] Updated README.md (if user facing behavior changed) - [ ] Added CHANGELOG.md entry under `# NEXT` (if user facing behavior changed) maxitest-7.1.1/.github/workflows/000077500000000000000000000000001513323350600167545ustar00rootroot00000000000000maxitest-7.1.1/.github/workflows/actions.yml000066400000000000000000000014671513323350600211470ustar00rootroot00000000000000name: CI on: push: branches: [master] pull_request: branches: [master] jobs: test: runs-on: ubuntu-latest strategy: fail-fast: false matrix: # keep in sync with maxitest.gemspec ruby: [ '3.2', '3.3', '3.4', '4.0' ] gemfile: [ '60' ] task: [ 'default' ] include: - ruby: 3.2 # keep in sync with the lowest version task: rubocop env: BUNDLE_GEMFILE: ${{ matrix.gemfile && format('{0}/gemfiles/{1}.gemfile', github.workspace, matrix.gemfile) || 'Gemfile' }} steps: - uses: actions/checkout@v4 - uses: ruby/setup-ruby@v1 with: ruby-version: ${{ matrix.ruby }} bundler-cache: true # runs 'bundle install' and caches installed gems automatically - run: bundle exec rake ${{ matrix.task }} maxitest-7.1.1/.gitignore000066400000000000000000000000431513323350600153440ustar00rootroot00000000000000.ruby-version .tool-versions .idea maxitest-7.1.1/.rubocop.yml000066400000000000000000000037561513323350600156440ustar00rootroot00000000000000plugins: - rubocop-rake AllCops: NewCops: enable TargetRubyVersion: 3.2 # keep in sync with gemspec and .github/workflows/actions.yml SuggestExtensions: false Exclude: - vendor/**/* - gemfiles/vendor/bundle/**/* - lib/maxitest/vendor/**/*.rb Style/StringLiterals: Enabled: false Bundler/OrderedGems: Enabled: false Metrics: Enabled: false Style/Documentation: Enabled: false Layout/EmptyLineAfterMagicComment: Enabled: false Layout/EndAlignment: EnforcedStyleAlignWith: variable Layout/MultilineOperationIndentation: Enabled: false Layout/MultilineMethodCallIndentation: EnforcedStyle: indented Style/NumericPredicate: EnforcedStyle: comparison Layout/EmptyLineAfterGuardClause: Enabled: false Layout/FirstHashElementLineBreak: Enabled: true # Opt-in # Opt-in Layout/FirstMethodArgumentLineBreak: Enabled: true # Opt-in Layout/FirstMethodParameterLineBreak: Enabled: true # Opt-in # https://github.com/rubocop-hq/rubocop/issues/5891 Style/SpecialGlobalVars: Enabled: false Style/WordArray: EnforcedStyle: brackets Style/SymbolArray: EnforcedStyle: brackets Style/GuardClause: Enabled: false Style/EmptyElse: Enabled: false Style/DoubleNegation: Enabled: false Style/CombinableLoops: Enabled: false Lint/Void: Enabled: false Security/MarshalLoad: Enabled: false Lint/EmptyBlock: Enabled: false Naming/MethodParameterName: Exclude: - spec/**/*.rb Style/GlobalVars: Exclude: [spec/**/*.rb] Style/Semicolon: Exclude: - spec/**/*.rb Style/FetchEnvVar: Enabled: false # we use the for multiple gemfiles Gemspec/DevelopmentDependencies: Enabled: false Lint/EmptyClass: Exclude: - spec/**/*.rb Naming/BlockForwarding: EnforcedStyle: explicit Naming/PredicateMethod: Enabled: false Style/ArgumentsForwarding: Enabled: false Style/BlockComments: Enabled: false Style/IfUnlessModifier: Enabled: false Style/StringLiteralsInInterpolation: EnforcedStyle: double_quotes Layout/LineLength: Exclude: - spec/**/*.rb maxitest-7.1.1/CHANGELOG.md000066400000000000000000000022671513323350600151770ustar00rootroot00000000000000# Next # v7.1.0 - update vendored gems # v7.0.0 - only support minitest 6 (which does not work with any released rails version) - removed `mtest` binary, use `minitest` instead - stoped using alias method chaining, so things might break if you have other minitest extensions - use frozen strings everywhere # v6.2.0 - test and unblock ruby 4 # v6.1.0 - test with minitest 5.26 and 5.27 # v6.0.1 - fix unused block warning for `xit` on ruby 3.4 # v6.0.0 - drop support for Ruby <=3.1 and minitest <5.20, test on ruby 3.4 # v5.8.0 - bin/rails test line bug # v5.7.1 - support disabling interrupt handling to avoid minitest-reporters bug with MAXITEST_NO_INTERRUPT=true # v5.7.0 - support minitest 5.25 # v5.6.0 - support minitest 5.24 # v5.5.0 - support minitest 5.23 # v5.4.0 - support minitest 5.20 # v5.3.1 - remove MiniTest usage to make Zeitwerk happy # v5.3.0 - `pending "broken", if: ENV["CI"] do` - `with_env` - `capture_stderr` + `capture_stdout` - hide maxitest backtraces by default # v5.2.0 - support minitest 5.19 # v5.1.0 - support `before :all` - block invalid `after :all` and `around :all` # v5.0.0 - add minitest 5.14 support - drop EOL rubies (<=2.7) and minitest versions maxitest-7.1.1/Gemfile000066400000000000000000000002741513323350600146550ustar00rootroot00000000000000# frozen_string_literal: true source "https://rubygems.org" gemspec gem "debug" gem "bump" gem "rubocop", "~> 1.82.1" # locked to prevent random failures from new cops gem "rubocop-rake" maxitest-7.1.1/Gemfile.lock000066400000000000000000000037611513323350600156100ustar00rootroot00000000000000PATH remote: . specs: maxitest (7.1.1) minitest (>= 6.0.0, < 6.1.0) GEM remote: https://rubygems.org/ specs: ast (2.4.3) bump (0.10.0) date (3.4.1) debug (1.10.0) irb (~> 1.10) reline (>= 0.3.8) diff-lcs (1.6.1) io-console (0.8.0) irb (1.15.1) pp (>= 0.6.0) rdoc (>= 4.0.0) reline (>= 0.4.2) json (2.18.0) language_server-protocol (3.17.0.5) lint_roller (1.1.0) minitest (6.0.0) prism (~> 1.5) parallel (1.27.0) parser (3.3.10.0) ast (~> 2.4.1) racc pp (0.6.2) prettyprint prettyprint (0.2.0) prism (1.7.0) psych (5.2.3) date stringio racc (1.8.1) rainbow (3.1.1) rake (13.2.1) rdoc (6.13.1) psych (>= 4.0.0) regexp_parser (2.11.3) reline (0.6.0) io-console (~> 0.5) rspec (3.13.0) rspec-core (~> 3.13.0) rspec-expectations (~> 3.13.0) rspec-mocks (~> 3.13.0) rspec-core (3.13.3) rspec-support (~> 3.13.0) rspec-expectations (3.13.3) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.13.0) rspec-mocks (3.13.2) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.13.0) rspec-support (3.13.2) rubocop (1.82.1) json (~> 2.3) language_server-protocol (~> 3.17.0.2) lint_roller (~> 1.1.0) parallel (~> 1.10) parser (>= 3.3.0.2) rainbow (>= 2.2.2, < 4.0) regexp_parser (>= 2.9.3, < 3.0) rubocop-ast (>= 1.48.0, < 2.0) ruby-progressbar (~> 1.7) unicode-display_width (>= 2.4.0, < 4.0) rubocop-ast (1.48.0) parser (>= 3.3.7.2) prism (~> 1.4) rubocop-rake (0.7.1) lint_roller (~> 1.1) rubocop (>= 1.72.1) ruby-progressbar (1.13.0) stringio (3.1.6) unicode-display_width (3.2.0) unicode-emoji (~> 4.1) unicode-emoji (4.2.0) PLATFORMS arm64-darwin-23 ruby DEPENDENCIES bump debug maxitest! rake rspec rubocop (~> 1.82.1) rubocop-rake BUNDLED WITH 4.0.3 maxitest-7.1.1/MIT-LICENSE000066400000000000000000000020701513323350600150120ustar00rootroot00000000000000Copyright (C) 2013 Michael Grosser Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. maxitest-7.1.1/README.md000066400000000000000000000063331513323350600146430ustar00rootroot00000000000000Minitest + all the features you always wanted. [![CI](https://github.com/grosser/maxitest/actions/workflows/actions.yml/badge.svg?branch=master)](https://github.com/grosser/maxitest/actions/workflows/actions.yml?query=branch%3Amaster) [![Gem Version](https://badge.fury.io/rb/maxitest.svg)](https://badge.fury.io/rb/maxitest) ![Failure](assets/failure.png?raw=true) Features ======== - **Ctrl+c** stops tests and prints failures - **pastable rerun snippet** for failures (disabled/integrated on rails 5) - multiple before & after blocks - `before :all` blocks - **around** blocks `around { |t| Dir.chdir(...) { t.call } }` - **red-green** output (disabled/integrated on rails 5) - full backtrace for errors and assertions with verbose (`-v`) - `let!` - `let_all` execute once for all tests in a class and it's subclasses - `order_dependent!` to make your tests run in given order - `Maxitest.static_class_order = true` no longer sort tests class/sub-classes in random order - `context` for more expression - `pending { assert false }` is skip when it fails, but fails when it passes - implicit subject via `require 'maxitest/implicit_subject'` - `xit` to skip test (also does not call setup or teardown) - `with_env` to change environment variables during test run - `capture_stdout` and `capture_stderr` to capture stdout or stderr but not both (like `capture_io` does) - `require 'maxitest/timeout'` to make hanging tests fail after `Maxitest.timeout` seconds - `require 'maxitest/threads'` fail tests that leave extra threads running - `require 'maxitest/global_must'` (before autorun) enable global `must_*` methods on all objects Install ======= ```Bash gem install maxitest ``` Usage ===== ```Ruby require "maxitest/autorun" # ... normal minitest tests ... describe MyClass do describe "#my_method" do it "passes" do _(MyClass.new.my_method).must_equal 1 end end end ``` ### pending - `pending "need to fix" do` to show why something is pending - `pending "need to fix", if: ENV["CI"] do` to only skip on CI (if something is supposed to work locally) ### with_env Use during test: `with_env FOO: "bar do ...` Use as `around` block: `with_env FOO: "bar"` ### context Use as alias for `describe` ```ruby describe "#my_method" do context "with bad state" do before { errors += 1 } it "fails" # ... end end ``` ### capture_stdout / capture_stderr ```ruby output = capture_stdout { puts 1 } _(output).must_equal "1\n" ``` ### minitest-reporters If [PR](https://github.com/minitest-reporters/minitest-reporters/pull/357) is not resolved, disable Interrupt handling with `ENV["MAXITEST_NO_INTERRUPT"] = "true"` to avoid "stack level too deep" errors. Development =========== - everything vendored into 1 gem to avoid dependency madness - tested via rspec to avoid messing up our own tests by accident - fixes should go back to the original libraries - restrictive minitest dependency so nothing breaks by accident - ruby >=3.0 - `rake bundle` to update all vendored gems Author ====== - around from [minitest-around](https://github.com/splattael/minitest-around) - red-green from [minitest-rg](https://github.com/blowmage/minitest-rg) [Michael Grosser](http://grosser.it)
michael@grosser.it
License: MIT maxitest-7.1.1/Rakefile000066400000000000000000000032031513323350600150220ustar00rootroot00000000000000# frozen_string_literal: true require "bundler/setup" require "bundler/gem_tasks" require "net/http" require "rspec/core/rake_task" RSpec::Core::RakeTask.new(:spec) begin require "bump/tasks" Bump.replace_in_default = Dir["gemfiles/**.lock"] rescue LoadError # not available in gemfiles/ end module VendorUpdate class << self def all Dir["lib/maxitest/vendor/*"].each { |f| update_file f } end private def update_file(file) # a file has multiple parts, and each part starts with the url where it was copied from do_not_modify = "generated by rake update, do not modify" start = "# BEGIN #{do_not_modify}\n" finish = "# END #{do_not_modify}\n" urls = File.read(file).scan(/#{Regexp.escape start}# (\S+)\n.*?#{Regexp.escape(finish)}/m).flatten(1) urls.map! do |url| code = Net::HTTP.get(URI(url)) code = modify_code code, url "#{start}# #{url}\n#{code}\n#{finish}" end File.write(file, urls.reject(&:empty?).join("\n")) end def modify_code(code, url) code = code.dup code.gsub!(/require .*?\n/, "") # we inline everything code.strip! code = "=begin\n#{code}\n=end" if url.include?("LICENSE") code end end end desc "Run all tests" task default: :spec desc "Update all dependencies" task :update do VendorUpdate.all end desc "bundle all gemfiles/ EXTRA=" task :bundle do extra = ENV["EXTRA"] Bundler.with_original_env do Dir["gemfiles/*.gemfile"].reverse.each { |gemfile| sh "BUNDLE_GEMFILE=#{gemfile} bundle #{extra}" } end end desc "Run rubocop" task :rubocop do sh "rubocop --autocorrect-all" end maxitest-7.1.1/assets/000077500000000000000000000000001513323350600146615ustar00rootroot00000000000000maxitest-7.1.1/assets/failure.png000066400000000000000000001253761513323350600170340ustar00rootroot00000000000000PNG  IHDR DiCCPICC ProfileH WwXSH! #({ނLBHA=J+X*XZEq[GQR*s>}~yι}w~=s4y@XŸg&`} c?˛N4mHţLQ0H@^ @kE w!+GHl%#96I to5@ !_"F~8"e" %q!<2?š]d >a< 5¤Eyʛg@RsԲ$tEyۘ;-,2!) n(;E(CH1T&a!="-N)i CYxj~ ?l8Z+EቈG,iD4]J%I#xc4e<[r) +PW f+we# /BH韰 2@{$) h,+#KL˒e_ZH'Q)΋x $ƞ.'Q<q#G0H38 B(f4i[OC!4ĨF*{dMRdȦhx\W %4u,eorD.1NZ*/himH?^"*](W)<:QdЭ!mj2GvG" &QlUeR%(8s8C*2UQ7?|鑂YӒ8H!N#DD#q8J!d?-A\Te\Qu71_,QN+)fKheQ#.ԚN)jw W Sj9SVKÏop/'eB^2hGR[h/LPL ~0 ` ʺ0@T X` l]#8'4\p Ϡ@?a q1C 1W ±X,K2lL)"6`[Z'0v;cX78 Mp|41x> R|1 _{z~w> GN7JD!'DQC%лJt={NrI>gL Br.@"V*%?4c#͗MH˦MѪh;hhзI{Cyt[69YM}fz;`28Q(cgag\at2ީiEUV;vEZzH}rM;L[?3\\<ż|a1AC1_c~4޳tXP$̺zfmAtv1{}}DsDyjN= 繦fR*̓4{ԵlBZskjhik/ޭ}NKc#YM#.rESN]nnnmz:zz)z3u /[;o/_W[Abr} > s W63"&M7ltʨg#7v0N0eqIIz&=< զL͸ffRf͞<:~+<\aռͼ"b>{LKo,Ֆ-VfVf[Yfnm-^k}M76 6]Ѷuwvvv5v/;jKqcHH5#o:J⍊pTè磭F^9y۝踌uYUZz͍6ϭ텻}-8oyzy=zv{Yyexm'gž|s5vx1-[;t kYv=  <9Dr(mo0",2<-\'<9|C숺HYQQ7MѵѽcÊI0!V47vܪqw[oUqm @?z gSw'I IZt'.Yܒ2)6mjXjejLf&MkLgH*5_uNT6d3&b4%oѩSSf2R3vg| j}љ3{µg jQ_\)~UՕ퟽*[(HC/rr͍ݙ;/_-?#LG+kf:mƴǂB5"hrQc.<_T)V<( (.y7=e3d3.td҈fZf^09[bs3̳x^0.uʅ.jZlxG_G~]W)-ߒJm[dU u ,Zֶs7VU]YZhոUW^3u͹*-kkk;Ůk\o~$WThqƷDlڼwɖ-~kkmm%oO~jwilgǮ]^w/u{&c؏{nW+?)b>g7*g6H:=tQL|xѳ?ع1q']]G#/?i糂g=ej b/2|떾o-gn{g>~x?#O>|;?0P {xV˝4w 9alR?์@{< `3Е~'6\C,7W%Xr5y70I>0пi`vW \8x֣3\ ]1Uic pHYs%%IR$iTXtXML:com.adobe.xmp 744 754 -@IDATx]`T=[+= 6D.DA~Ŏm߮X۷Q=@gw?3fF3f9S̝;S( BKvI*QB@!P($JЪP( .D@ .W%P( %hUP( @"mV(  ( B P UI+ B@ Z B@!Ѕ(Aۅત B@!j B@!B]nMZ$٦$-X-7B@!P}+ k;5nT B@!5VSlx,VC {b/+ B@!]Vly<oVK!P(|Ґ>8*uQ!P(kEkv~r B@!3؋-z`9^F>:v\ fkazO= a,y_P({?{ee<AͧⓦvPn ?igvZUBB@!ػmZuo|ɣ]_Oc(cZ`J@UW<( HRE*Z3`$0SFQ-£ Bh{–b]GQHێ3 <\zWubVB@!Pt=~]Hꂪe65"a< B|VEUB@!Pt m B@!#Ъrȋ E 8\Pe׊PNtT^ >I׃vM-iN8r44Krr髜B@!P(Z\:wҘH#pTpÊj09 H4l `hH#ҧ Lq $. c{]5|U_3H7,6)| I~eCT~&T( *^^lՙnF7"aF7Z6Otzm/s| B@!еY 6 7;DdPg- U B@!,%hERGnHP( ]A݂vW2S B@!!v2 B@!U B@!Q B@!U B@!Q B@!U B@!Q B@!U B@!Qw@P( !VV( @(A"<*P!P(V( @(A"<*P!P(V( @(A"<*P!P(V( @(A"<*P!P(V( @(A"<*P!P(V( @(A"<*P!P(V( @(A"<*P!!a )v:K_SiȣX*k?B@!W@@ Ω_wc#;1]uҹOfM|_KL5qXF{k^ڋh%[I{ 3C>Ġ'\Z[(6*Z0*WDK0aU[lƴmQk 埽·'iB-q\(>:YA/JdXÔ2֪}2r8I ٰNC#Xe(BM f; 9=_)@5#/{1+`@C/(xqXvYКoC[#4c6oļI.qz.UƒCήIv=y4`Pf>eOH"V9rz!@۶!e~DM\+u$vώ:oR"o1uvؤEZԯɇVn?6@Ns&`haqIK#6#-pi|߄wVi >%GQv˶* (O݊rg ::W{Tvf?=j̬o?$6X'ͥ<#-izzhl1H{7.?jJ ο(~Xj{+ڬU :'6|o$c ۖbd#p+a]B 03/kߘdgslVr|/&{]|is>4Mo-҉t[5fDhl!IhqQzޒ15]4̼`Gdfֿ',)&s&hHK`<Ox7X߾[ {q<tSe`.^yg QYڡ'k3>e^#Ax>kni.S Ro Z-5‰?[&ӎRDˍS^?%̺ড5,k,CФ"ED<+(H4x""6X7- 4H㮧HSt=I}vPjCT D&ƊLW3xP#>2 Am1OIEDbOvzv9띈<\U_~02uFԗV28$*sBK:/ ٨ޙzaw (Ϥnft;PHHDg$!t;P|V=I.KZe*KQaP7"Sn -M X#?ϙQss}v`!. ޫbz$H#" 7v:iF5ΟYzClzO:ȱ:nna߰s6j9G75/l9z,4[ʐs)zy29 g u7@#sWGN&*Gv4 ll0^q1|˻U܏z]_:h/`mQTG&~8e6*ꞽ`* |n%%f~%W-4 ^(a;p.x%~6{#1ݏA ce_k~E;o9hh % Z[_v"c)lL%מD΃s:9=e8 ?yoAߥ0c;n *DDX(᪭YUgL,C;TNEy[C#9 G r  a)MUHKҐ1fĦ'm+Eoq?uo2ڧF#{DG /y/ߏw#g1PmꖯebحDxw |ș/@êp'!)a+@H8Kao?SyZK e5/!8TBh[(SvTsF+򷆳Ìz L=5#}-_ K*4T8dt5HA/p"Ņ% y$MW2<_ݯgb kW~w\A`-"2OL~bQKdjmG =_| =#6#gslÎw_C٧а:q7򴫑H,@hkFbZ,ؗ!ɰ;nщa^>Z !6F$퓆\ :yCM[`7`sJ Oe!2U+y\0ˇh!y.D|E7ܣ9QWB݆%#20 ڦ Kd-<_t5rϹ(t?I9h<}֯__jY<琌ѽ=[s?\vb O[E?jI6<Ɯ|V-^g۬)Ht,Y(J>Рq\Gg;a[`mc`qs]CTU)WFObc/sՏV ,̯uM-X!] -pXAFu@L)sZe|z{+9sb@oQB޽o\h19jt"G?#?==? ر(㟰''6SG33Q+T} %l-=i jP\Nzgm̉1T6g.Bh7rX$-7ݏIƤ\R[\/WIl=p<;XTUnrsY#ۋM zn g'.ݎ ̌<ը]nq,ɒ_fH~x`sp N\!^glt%YstƷgPld{ȘDR̝MCć$Hx4'7noڄʙ_&2N.hEBl.Գξ=蜕[|f_7 fipk9 .c oɃP0QlqU bt1 px8*K 5يT?~#:rb$탚U]6TU_+<W?TS Gggt5q >q-9Jg2j/YZ5vUTvzq4sOv;cwlŖD==?Rx=:HWP}z%]U$t@m T.X5 )>'l@'1up[[* j7D+Y)H~e=yTS"nS}'d5q ٱ) \7JTCcP3>;ޤYB5WŎ[i-Uk1j(~{ν+& Rԯ]+_~nFq22EW~|a}\ݨq5_#sTdAjOse3)d1gL@X8' hkx݁OaC0Sm/AO*;>my:*~ZſIAp؄Igoc*xe+efT`tl;fCꚌXdVUIO2 }դL}\ 1yc̝RȊZ܍Ϣ' UeXo:" Aٷ1 ˰p+~e\UjVm˱m>&+T!tY, =}N8kGgh#*Kg/݋ Y{Xz>2L`uDEy4\̛-k%1`DK_P%GGʦ5/Q oދ(x F+υnxlP,8Ɏ$ؗT 0V<ҤbmTp?x3{iTXds"s`ѐ}G, u8Rex:jLLꏔi+\}J[z6G )t8Be>1Ps?'D"VD 5gA1{R`^H'T臏PE!s߭<ٯpH$x>XJ}!$>"X / Yk߉cܮN[e%ڎ O52 u˾˯{D.DGU\BCupF?dI}PeݻSm FK1]wyY~T<6J?}Y~A=5g YHÆ! qB:'+hDlroO|͍Q}7 #vQmX{_!G1c?=VXo@Qp.a\d-&v"ڎ?`eC!EH8qŏO< *Or9#\av&HA(4S Yb1tCt>LNBTOFEyPd:-{!W/uLSd`d}a!o[Uh(u#t H:T]]jvY#t! 8'0thFZgx[v &d"Iw$ wOso zOwo;~>ş~=Z Ya~Db8XJi$FC9g!nqԌA*^(q񄞈nhP%.fD>IUpZC-Qg`ݳQL?N0}^M6KИ9ځ~INoݔL M4.(G}M7IKLәBcmpU az{1ub-g cȼx7Uªj11^0B'\u9{Pl1f K6ZE ?n>OOPTsnG!\ x ^]H*ŎAq؋LOٝpp9:TzanN?6\Bshc6Ϻ Y7Isw(xbN8c!q!$#7Cq0z=|/};@?ԍt sQ}T+iK`kXf7_\P8~ͅVCÕRs"gڪ(%~A9H h6UN`9O+a+z8T d2eYg[pUR;^jz^8}uvP’-Tj3FxZF8*n3FͲɨ-A٬QpPau -`ʷBd\9hWk[ü >B(X++VO22hmO}qXXBsfL̊Q,0t?JDoRp~⧾CSx=Rc[$ϼFZ TТЙ%OYcA}";^E a 8,Lhg/ӒCA]( -*[@!}&c#'l:c gQTZIFE1ɉ@CgGɖs4Mxt]' ?][xj(vy / gR/XIy-H=33'èo1qNNTL?aQO*\pچsb׋W؏hDS-OqW-Oa*1@#a}jN8ɭ@}Jj4"f;QbĨ-DwCqGil_ D8 .;?J^xV({g6*yyÐrsX1G{Pƃ@nb[o#GP, *Ǣa= {>̓D>F]ʁY!bh4D Uԗ:s˨CھSXbojƠMq;!j" y$gxyI'JG-!u! ޲k4-4Ґrc}$ xGm>D"f!2Y6ڧ MR}ddƇV#){b(wmڛ to:VͰ Ye68Љm3ǒ>hAԠt0M_1hk k|8_]4֟oZM५t{8Qg+ #Jf'/ b+lhHb+yǀoxjSp+ aR0AW$n8IC^Ȗ@8)/BB@MK~A7=j"_)|(QRe&E^^|xl.h 1*HC[})IӮ'cLlp+X!L#$Bf7սI Uub](M@@nCU(G!\">j=G ZRqf,(+o}+/}_R[tΆm.d?x;W"vȘqbho<َ,ͨpΉupՋ9:'$Y@opΗH R-&hń@lAD*zzW=?ȩZ膐nNoU{۲BGٗE{ =Xɳ{`;PaSL-}7ξb[>$P(emNF~0q>4!)uo}+ؗ[] %r2-<p&|ޒx)DDy8 1ԭB,=)hqfM)qG9b` q`O/-c1'D(Ϝ27Z9',a]v>Ƴ^[gS/,PFK'ԿdBp(%Ⱦ.]3)=!OAB{hv;D۬aUo6%!Hp > ;@ko4R$8&3i[0]eDhn8ndE( Bi awVx6d+:&Ƕثj5"x@HB; z bfșJcxʶ#k=XżxbPp쬳&z 7أe~֨m(`qfj'W߭/ϔzw?֫GSV"葜NX7b}҅6z'Ght:^Ќ.t_1u:5tbJDc[ȥ \/,y툯ŢWך}L&!E:_+moIU:op }کW?+ [3i/!÷/QRzzF!3|܉oBhxxe3XB3Wl t 3&[2Lş,RejSG'i^ʳȳ縫y!LW?k/m, [cBmGC!DD.@ĢUC+BDd}H?cNcI5|0`Byx j~P<iS!Ӳ& @@Thƻ^}6 o 4XtAbR5Ec]XD|~-^l[|a 7+U{4Q]m~d9;xRer?̗C˜7Y*3X}uJʹWGkxՇ^Zk Q:dDKdHGwbc<:|8m l62܎g㻞49f T7ڑoԈ* 7ފGK r6~SzE &ua/=rXt#22* 啇5+B<,1= ۷Tnނ:?I`Qn\I^}ogy/W+xpsAWSѭ.FDC\LhT?UnAW?:.^'WVvRnH={1u\e_7ߎjBR=F>i]^enuVn>_'plC-2|k'fG'%%q nK[![a+SHRÚ3CJEoWjnj~6IV 4yCݎl\DD$Wvd -[P?!l3Ğ* |q|(Y֜w J[mE^Z"^^MwC[&mQ~9ۮ9_Z^~˺ݖ{kEt5?ƪ.D/%ؖۺ8gGs;ZK>=kM~,/ydbkcq+wsձo,t^?dVλ"W мQ; f.iLDHp!J>7<#R=R̙ -ЗebӚl(?n^xaAY:RPK_{=Jߺ5ϙ'WHDZD[Xˑ:™X ~UZ(YrttTd<}CZZސvHZQ,[B:z}om ΋C>E=ޯA7t1܋ymZ y0[jx3V}:PwԯZ#Uޓ#ya$+|d=aB=ɧjtjIg~*;Vb%L~qWSQ l% vBHbxCQ 88ZdLo3+ךz\t36p=#F(kyހs|ɴ3j[QgVb5HYa{sbc.tұ &^M9y^r ּBmxk$ټ"z7څO{oI65A oQgǫr%f8)F~"lRp>Qzc~k֛SP&'6?U 'bP]{ܦ[ NGوCz<'& ]DQbeXS`K(~ QEw~NzRє/|6SMf#w)xCԻ߽WɮG"LS>ZyCI/p "ֽy¤T $~ 7\|p泽|8G,-}=V$62x=(o<!ixccV7xNDT,4l(NJ! ?~'q} B^KgDž-u 6f! ;q۞<}Z1}8l@dwS%+1q1>5 aRRN+Oڼ<ׁ#& ehO E5^GȓA VF%+$i  (|$Eϱx܆L896,DjV%aODԸy0o!j(&4^/>hďMX}cE-W]}^G/Y%7bsΓW?nBᏞyu&9ryld? Φl,WD bǟ K7sRl_'$}QDk9NB/?L$s!O-/kWr6hčз(p䑰?֙Hb(_Zփ3s[81x~=,'+yE4C4|<`X6#fwq FR3.l1 Mh $+Ci X4[T*b&N#@CFOҾxCs{싼s%u}MBS <!#4mOIC!!Z3xmMFaXkC>~E|m ߉/CO65|('=cdt?(àh^#Ǡ۩vkTG+̭7'ޫy_ʧQ<9K hR*!2/Z`J*L;JTpo;<'h$543mcГ gȘ8X3_㻑oWE1UUŰ>RZ\19x4@K XQ^: k: wr !LfV`Diik2ƽp^h(:O>JpP!#WEi=y&ٰ CGfd5Tj *'_2VGD_05)=j=J$"zgx5/;S\U*Be D%4)EwuΣOtN&>muS,/2[&,"dFCo=7AB#F-ԟ-00S ү 2okmO#p8&zFj>컟Jb,N/:ca/FZ+מ;K#&,^אy>̟+i}X%E=ɿ=?.;u{mFG09dǛJVmEJS( @h$H B@!PVB@!Pt!Jv!*iB@!P(AڀB@!P(%h\B@!P(Um@!P(]]JZ!P(JЪ6P( .D@ .W%P( %hUP( @"mV(  ( B P UI+ B@ Z B@!Ѕ(Aۅત B@!j B@!BBpU B@!PVB@!Pt!Jv!*iB@!P(AڀB@!P(%h\B@!P(Um@!P(]]JZ!P(JЪ6P( .D@ .W%P( %hUP( @"mV(  ( B P UI+ B@ Z B@!Ѕ(Aۅત B@!j B@!BBpU B@!PVB@!Pt!.L[%7"W.#\Wݝ_ B@!w"`\4n9wנ?0 Z3l`S% h({ӯljc{`3cOf CdjVtQ<~xJwiuiҟJLKP)`3f`oJק(dQ "3d@*۽Y툊j RB(44h‚o򊕷Xt"@X{Jy~ g?ڧ%>"_4^Q,hflwKekjShGt'k'mae~7 T/ NB-Sϊ{gObnN(=OŊhl΁ #GBd>oz?QS+c5rM`:22WZ$r\u؞Z  >2 knPŵH =|-Y90vYaV/_UP 4+ Ԅh4;ڈKuY+Vl~h^1``Dhnl;CR{\(d~ŵSܙ"tnPTUؔtZDwc۫us"cCpa#1*I4 ]۶aێwz)p6ra7 I6 a!O\نGW,I~Jaْ?|4$#gE;+}D]UbXr k4D%#QY=F>Bu>NepK|ܙ_}u[+V%֘_ZR$scCCIGF4iS*_@ CvKui >gl~.Ki_4O;n?.1-Fg%i=?kמ=+J5Ii|~Oz<:m'Y}n/b}/y &gws<,ۖ%k XIݣeUe\YS(_Ԯ83ՊͼW8.mg:m|M"zrme+ZL |ڒhSkƣv(f,5msjt2ةjeNCO}iG7q̠k32 {HI+ۤ}f錿.-$>\'41q{]mԡ/VW]-[D[n/jm[?Iի嬻+WjK.6o/l?/?6S&oے2Axzv݂-G \m9\M>u(Ut7Zog%Ƭ|/f~k3N4?hf%ZǦ׿XmԙOݷwzPݱhii~;jl ̘iڌٲ `#ʠN_x&$G`qwՇڂj}f 1DbUl[r"~<9{Yү'ueKsOj1OV4h3U2`a1i%g?3wWEĩX̴ƝrΝr ' XoLd{.c-0~*f^yb_0ʛ1yG9~z>d/XT-*^~#&w5:j~yo3Gv?nлT̷vUW{z'F[p=z7pR,T>e:Jx=6r,sWs,ܛ@غx$~dmW#) tPPܶ< D;P ONN;~3œqGc*mۗ1iଯF_nK5`&W[~~vˊ8u\x3e{b!wY3do?N=Q})q 0/*v Vb v?pྰjPXT߱|ZXsxQCvy~.?$Dž1iu;p;?b- c-}gB|H1*6x0 oF:.'qnzC#H=~ڟpi =9 6K^"-ڠc ^c +?/#h?{:fB ZՌ.]Q*7pW2;OC<.o_JC,kt7cӥMw!=v+8[?;HVߝl#uW^T؀_ȔnUx*rO@E|n[L//@ h ?_7 cZSMyLAIi5b"D0{?8 RPE&!? q;'eeDĊlaE;wwJe?$.?~Xp6JJif{󉕒179>X~`}e(MK]=*:@%cZtJrP˵ڼ6IHKcVjC̝Fg\ڇLOA0y Wo;T:}UE^rcقՒ{2/֖ޯFt\tբ}<{cm}nI, 2g>hY+èė_̾NMy5Lօ|sTk7jGʴQNө} Aa^9I%2>I֟Kw۟_X[ z$e[4mkAo:vmPu|sMڙ\{1 ~Mh0(dZ_[ci??K[B>[MxF2|]T{X6SW]V;6ĪYPP&jD^wD|:o޼Sa8Y[[`iã-za~ew*n>g/~jVQguygEڤ0f}XsvC/֎Y,z?zXcY{uIlmkn?x; D9!mQRw /w>ڎL6碟j+аtL)1(+‡~(2]}8E`NƑ&cwޓ̯Z,g7vf8ԈpPK9h0,Ggafo6ieۅ1H2⁆6n7; '[h*`4oŦ2Ѧd$_Aq __jGb̼,z}3joK1-A&,dI>u;[޽qKqe``)'aHn&"]PvQ ? Z8 h6 h3,=0cp$j4RZU8җz7f3O(@n u}xlm J7H= eoԳM{tfw2 q\xS1wf7hI8n≯P/%jmXZF&&.a .%BI,ǘpH*s 0).}/W:8€+&}CUw0,`: `׈k ?R˷!`N40m^E'^ br[@1%0\WOAY Q itp)Zu3H1'=z1ۓo^.Y+{}8 @jܧE+߸ ʿpeĩr~dۗ[S[fL%& f8c1az7f IC!$hŞ<8I:ռx18պsXGz NxɇZiH#WxW;VfOM?D<Lּvj@CH2R>+jrp9?˯GO=; y7]:1'cH&lĀ㍠O3 ~ǟ_}5>yiQ Oy=2nT44/(SBޙI6v6aRM7*OS0v [/MX">(S۔jR;2e(8lUz,luãCiϺN/~iDu |`Z$2}92[󛥹hP ux׈Pba[$'_nlubT#g+L8Obkpbb&V4yoB1[Al!B |j5WVUs:6ؓ 7B}p[rϻt$` şmU&Fjc&fyER6K4z$$;Lזdwm![x,=z"<]rU?YWUN1?76z!SO|8o^LvLZG'u2aטQZVӺ7Qpeomi6>~u<0LP4q芅58H <ܽ;:h<7;w n5ޛ&xUx 5O^Qr?L+oXRi{CU|{nx=N4~)*CX[+w9g31]q}Cjz.h0x\Jєb#dXVxc闪X~we6ڮj4,aͪ5( Tرn!V[mSnZ );+=XSQ|=Ї}F|/-Wߠۂk/XN:I` ס1S$(>"SܿGv΄yIVW75|2$J&i{Ґbsw ոrwm]j<:ބ./4i -;?ㇸ_z[q|7zrL,;+|/oEX K Ada?)D9>yL'^}'N .r0ig]q3a`>4hLW(&wkOs4Bmp 7 >;[?07\hݗS^/Q{8A{0AsHon|ىBOxg:J[mknJecƸшǨAX4k ^'tN\שO6&IuRQUeFB3hҌO@.q,S#~RŸ!2 555SXN mZ s+FŒ^п[[O~==Y \m A$(=.NL{v"ǭK=Ͼ )xɗe m5,+zom^@}͖j\7VᵧG`c{a:A\t׫pDž9~^(Y }-?5+}xpD6|ccLMuؼr>^0Q}-f 3t& (K:kϥxoe.^zf/Z4"s K8сG;ʱķm"ʲJh턥 ғ7@,yI*_74ǺoF;womSq4̣5TX}9Ŗ׀a\e\ Ki0,+}r|Oc|FɓGKG }eGZem糟/Ў`rחYfqo4ƽR'7tͳxiE[mY4 .`TXivd}z_esfeonՎ4Hr3u>}#~5<.xRx"6lM]|OkU׵Si˽i ˵=W=nRh5ZE{,n 鸋-\9S,VhV4i3,ŽgϫdThi"V,/.n}mKeeÂ\·y-EڞyCM^(Op<ιϲ؛ktsK>PW}`tY]_T]u>j(ǁ-F܏2h>sQ:ă}w`tqcjqXw:,Y; TRW SF C\7:K 炌mXn t>O Btb{Fǔ>蓒=Hi[EK3-Aѻ q"9N})[}GnlNM[aof򳲑_ XBе{o7u`+*Aci sF,][v(N&^ǟSNrʐAycTN%:`(z'Ve@'VnHEDǞ8C;^!~,uXt=`u)Ovud]oΝ;g"8: q򰓸҂XAӠ3'v̧ɓ8w7~[循^4@G 3Ja7nª?cu lpL lFk+)H65׽?umor9;ḁ@9 gog{ٌN2h`k,e̟Vm Ht՛<n X?s"]0N~e08q6xÓV^mSQP^Dt=@.uvc5v@-@c#S:&wC#zݑ7{oŎ AFv.ʹY Ũ?B5͠ɾ,FY Rj:TV!<&IIoKI'VK-؆{yJgY)$SpAyg3+c-Ř5ex Cx;5.ݾl{7ZQ-0U+q~63+ׂ [鈬\:B6nZ5\y6:&,܎[CS|i`4ۗkO5jU6@Mi]ΆNY*3c45g11WrpMO7}G:~{mů׉g:g~8\a琁j]p n)- >YcZMmO}onɘFҩcMGg/ND>~ħ/ψ]!<{Cslssp Vst2C|c8 ƚ|m):I:!'bopښs>vh9cӗsZ\4_@ǜ%65STyu܃!yhvS9+`f_RFZ5x\Yؿ~,G:NJT|Z:l^e]Ai30G^#ޝϏN[xm[:Sj +$Njϕ)ް.߉ TvIx4;i\>3_9ph=@-$7naաlK^ ( (t 7G_˔7R#Q/ZaC`2' kuY>~eR^îy} tbփI>lyp{[޷:l6:+pHԳ δCKH78p^zH/wuY:&>mf-;zs+=l xn9p9VGn9X_]זTWTI 04={O2dNC9?dnk9VڪuX[k5́q`V ;nm-Pj=e}yPkścZsnps7 x(1AH7ps7rQ^Anps7mh;voڼxhܙƳ3+Mΐ=?Й宋C?Fލ7/ :߻.2;V<蠨᱃ZN0xZSXeP}ew삐AF:\4ڟ=XS<60Op(\SAK9"]͏%Sі.w>ř-?'f,a . >cZ~07["ZMo g }dĜ T5e߉!I, nM{QhE $H޸v=|H+C שc0e-rT^S:B6Eyfװ[o6iNX~?H~* dxDAU\ܧ0}2n}vu\Sq: <6(uYn4.8c>/dۮE` ,l#B4ѷӍF.^tMll%zeFMs-S8Ho Z8 @*R`ye՟;l%(0:@#=|` E(^VD<\w޴ضo JA\@A h@h +?;ĉ#F9EPH|% ;yi'>5zT8ѨPqqZW3b dG$N{'p]3`UۜàQ-ҩ24ѯ륱N%'Aᬫ[)i 7|۠d7ː=m"z1}fJ_^'u t]CA*4YUG*@]Mvȫ3)93AENo!ݴTzyk%t~n7g)> #ԳY' |ʘD7WG~.hZ!)05z#iEe^)Q'8Tg~=3s`U$O<"з?,|gY~86ThZ !lEa.Fͷ#'#OQ! gRCs㣭{ǘ[He(ٸ%Vü'60? 3G"8&FC󰥠b(^ b3?;¿k?>mO E [htkEh")}#*wlFU(s3,UxЛ;> ] tK\QWcB! Duveo&: qgo7!V[ sj:&/@Q5=K=6po(]Ey(GP0ײ 0+:uFhrw\jɪy(e 4qJr{2 _I.VbݯA]q9L|AL|iHWgDm) lox'"&y'tDx.,P$A+y6[ NtEpޅDla~Ԡl&rTmKu}*#? .("7pQG|9(tkL+X)3H|"=d Rv@C\A * kM(K_|i!Y9xزMꅈQJVg93眅ЄfbqocۥLWnI Q眃Ȟa UQ+ME(ڰNw `Ӑp RFpR=lYߤMT#`HĞ{:ƒXҞΟ&[y_<"Lǀ."4:sv(㬻+Qsv^yjHwٗo䦗+C4f`ǰ \ ^Bٜ(|3:'pFP6= 7|%<c0` T|l)ރPye.M.4JPwė'WHzΊTfpu-5 9OG g2ٖ"ՓWylwhGE)tE?;U޹L8*eg^7KyvFH ޛrn#ѰEx#aH:c3_x,- |~ßàxaYU Gɶ~^";kriSyrO5{^^ 6 }ݮC,(~r3b>%H{L:T 0~ȎZ]'"{[G)r,b'Aôz[R fb+o!ip{b2GӨhʗ2ʴ}/cO e<ZmK%K~)$ݮj{^"H3Wf8lCogN~xuqa\C=hhmH=}\|# qwʯ^%Wv{Q<1w>MsPr+*v+E[ٽy*42{ϱwg6P~D)Zi(*[Fp6xy@/Ț*׭DC/!`$Hw[#JJr}4FpV[RTn^ V݊o_Ďw~Qtw@,+f#mWt֒ tEW@jw@<_t/;ѡhȿ U[n-x8}jWo|>@u~NDXJ ?y 5;P#.LDd#ȟ9Bba-@{QZd\(| \pJgv.v\qoIq05Tu1Ej V803E=ӎדI7ceנcBH'(j Q#*MʼJQ!g$; ~îC×3 @7?+4@א ߯jic}ElZgޮzH<~s/)17c*J[1btɧ%w 2ݭz)}N{*z+kZ@tr}bj}݆sORȕ&RQSy"O}Y%6}#ӯ?ve4xoibj*Rt݈TXBϠd-rf/DCWVcC@+o҅2b: ^ |>"?ˊA\=CGm牃J6sٴܭCS/IQ$Z Df^6;/WKEh0g_!y?A=}bAwH85m1,eڌ_Mf, r/|jo.w>[.yNF29# 2CA|o:ЯH=*6,Ak*%HVɗJXab{U1]t̕Ԏբՙ?dr5 .@WW!N#WQ7~.[=!i=.N! @_K~=}22z$^|ɗ5 %eL_+YIX .)H};(Ä",\ Ce V7ſI.w_e!f\-xJbJsά؇z/S Eנ(uEEp?$#( 8cGWX ȗH<7j/JokMۿ#s"|s !Lw{9кfꈾ4!82 G '̰jߎNչ^ kIDATޱL)cq*?+D 㪫錵8FuKekC)$ hZ7`ߣW~?mp `<ɳQY+z::uwH?!?ŋk,Q4:T, \}4:.Cc]B5RX,["<ɼ5j%)Y=NDǺLSlf>ܕW ̨JS)ag5if A[JQO\^ QH I8 1L!>Wq\ASFk rmzy˕4QYy&{,g>RCi 4f|(b:Or]~KE~f6&:1 &g)w1%NnP'@.(Iwaw "D H[bĺg4Oz!Kff,@u"byj@HXMx1tt=ޯHJvX峑GWݧ;idZ5dsaĩkȥKnGo9TL6_h)կRLbk8%L(,e gH,x vhLR ޫfq܇8ΰwZf\XyVO, z wY={!6r9tR]_E&T'_x"=qS-Kg~ԕo8-s6Msƣ/u:)j7GnAy n0[mgT֪d=NG=8:iUڐ 7";[dQ9H^g`mD]>߸#iz3OqjKMi]C ?e43踤˥ Έ[@"dZzI41P>)VR(d0*IP<.񝴟1Jz&ExB{oDTT}v%ǘsGihIYGFP#?n'0FƋ]5)t&l"{uyZ“5C!w~Ws NJ+*>}/{t}Mq06:mT9>K:)/+֠x5|s2j]I >z%|tH1e+u} 1j,F'!k"umHUQzIYD~M Χ(1Eyخ`0M5cGT:j@<җ A^0wl't.,GgQePϣ}cASD+MY%Bh6ెgjA Ws}9 ջa!_r8tyvn@B&v(^ uU"G,۬ ƕ re PmAE0dOĬ급p* ncf*QO-6֟ ̙#1ҵYP`e0MߊSJ`wt R|L_3eoNG#6s';2h]ъI,=5rFSZO 5zm,G`{|Rޱ!`$)j4J.CcQ ɧQ4NQE5N#~ii%GN@&_P%t ]ݲ D  YH[k '58*xtDz;g fU3+ z᯽|Q\2wթT\;48|ҁ̈t $i:ظOVE>O*6+8i̅_}"Qq-r{՛RQ1qw7yxr̙[;;Ah!ta~O#=3z&ltSϪUt Y3~pۿ6dY1~% HH)@s")y3|)Ƞ!sP'Vh&Իԉ-^$hKnPOO| z25:6sRvGի) 4sILA_¶m0͢M,=p*048](m V#UZV#K1P89U+տ&~11? f|::]NZ=Xt:wDE7'-V|/tYRʪHE'[މFGq+Ư|v̓1{X`@BK~\)Eta "M/• Mt3b-E [AނD9i @ |H$J9LVP!wM@lLꤠUfa~](|?"*EK b$ڹGWȗ< vf$E*iuyEAF"z;1RAk(͵aeAs+ًPIg89Jkp鿑z3g{B6[Z|BZC  ( ^NH >ʭYWɊJ NACT#Buw݉2'kJXrxp@] $-+"HDi CՅ%! # Qޢ| ҿ[ѭ^<&9Y'U4^3@]\BY7Az!'~m~c]#~T_FdXU 3;rM–='|v[Gv5 ߹gN\lIFȷdշcJ(b@(DxU#/Y??9Br:d-Xu7y G$칇xJ:FT nQ(W)Y63;\$r{WZb"BGT*i 9C^Q}HFle&4٨(6p@DŬEhSWT*K "5ȟ˸e[j$#C#]mi9?$,-fʳ~XZZP>A< JLN<(̍O3K-x+~_7^Gխ"J  jݶWri!.셰oP+sN~Rj2w {(:!ԕ "l8ѳQrE4' &RO#Lpm@'/Gg1W#Eɖ|,j{}Uؑ]#k<{"Ԧyl@CI!*i .sy'R/| y {:/v:m Pq'1 9Je@J֝SzFR~K^𡧮hen[XFCf\v')9>BW_Eo՜ǃ1^T_"_R"| mӣ!>|B|a^ pp+-Y_eCެOPw)a}ږŠ"nH2I4y<$ex syHü}#'ZSg98dEHyfUm!r>K&!(r*]{rS;2-EFhm DDܪŞ >{; _|u- $aS i<۾A 6)]@qxEgn@Iek=M/瑟ۙ@ˊ3-iA5l7zj ̴@}Pgg+;:}:29ȼg$E@Ĝ$#MaHwQΧ(~I+X8et?QzkJVqJ__FQN#[ ^LM20{F Aoaϐz50X|cfiL2!#g B=RQ_Zs񯿎HLkDqjLѨl2O"D ~$GE2-eSHyF'ϡG~晲C 3:rٷo(?Z oXE('Gއ68@i^~]O@ysxK(s?g6iUAՓ(,mx+g0!:;Ls1ъޛy3DS8@DsEP.k,/7 4|d*DE%sVoiVL2Xwg*6z>wxOP7B<%x'Dany<-8Ν At>UgR4sy@n񎊃s6X#8C+/9C.|\FvqlcV5EKQf:Nɽ~[ya1GOGZT&: *r,8an9+y$¥#_΃=F˥=i(*`ufvOh9sO3dl+'lӋfv`[ݨ1Ț "C.dkOEǀ#.B|vXq>ڀI]D"ゟ8J |}E*ygh[?Mt<23"@y`&-s9`Wp|pjRP2eסI]UHd`^+/F疡&Meƴ͊$N,;8` mlfFSrj7:i5:9e;G:XPmN!Me_&4eUo~ZGX%=]vx|y5gFN>[P;L*Ych2#X"\lTnCy%S0x2;ʅl-jF%|N ,T%(zsh!wvхLk ǵ,hpS/@sn+B/9eӳAr4rc_epо9BӁiLt^ ;@Y$dZh6$d5 FjFh{ }ܸH:)MhR-|wՁO O%emf8Ǜ5-;VdF8eUp$` .2%|F~FBVxg$1"ӭ1M @KmNpC[hqDYwGgO`f.s#4SeG ]n29w6.f_ {Z to[w;<2Ў)˿LMOt@)mss7Ep+Qe怛n9pqm:>5EX7pśZq"IENDB`maxitest-7.1.1/gemfiles/000077500000000000000000000000001513323350600151525ustar00rootroot00000000000000maxitest-7.1.1/gemfiles/60.gemfile000066400000000000000000000001531513323350600167300ustar00rootroot00000000000000# frozen_string_literal: true source "https://rubygems.org" gemspec path: ".." gem "minitest", "~> 6.0.0" maxitest-7.1.1/gemfiles/60.gemfile.lock000066400000000000000000000030771513323350600176670ustar00rootroot00000000000000PATH remote: .. specs: maxitest (7.1.1) minitest (>= 6.0.0, < 6.1.0) GEM remote: https://rubygems.org/ specs: diff-lcs (1.6.2) minitest (6.0.0) prism (~> 1.5) prism (1.7.0) rake (13.3.1) rspec (3.13.2) rspec-core (~> 3.13.0) rspec-expectations (~> 3.13.0) rspec-mocks (~> 3.13.0) rspec-core (3.13.6) rspec-support (~> 3.13.0) rspec-expectations (3.13.5) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.13.0) rspec-mocks (3.13.7) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.13.0) rspec-support (3.13.6) PLATFORMS arm64-darwin-24 ruby DEPENDENCIES maxitest! minitest (~> 6.0.0) rake rspec CHECKSUMS diff-lcs (1.6.2) sha256=9ae0d2cba7d4df3075fe8cd8602a8604993efc0dfa934cff568969efb1909962 maxitest (7.1.0) minitest (6.0.0) sha256=4ca597fc1d735ea18d2b4b98c5fb1d5a6da4a6f35ddf32bd5fa3eded33a453be prism (1.7.0) sha256=10062f734bf7985c8424c44fac382ac04a58124ea3d220ec3ba9fe4f2da65103 rake (13.3.1) sha256=8c9e89d09f66a26a01264e7e3480ec0607f0c497a861ef16063604b1b08eb19c rspec (3.13.2) sha256=206284a08ad798e61f86d7ca3e376718d52c0bc944626b2349266f239f820587 rspec-core (3.13.6) sha256=a8823c6411667b60a8bca135364351dda34cd55e44ff94c4be4633b37d828b2d rspec-expectations (3.13.5) sha256=33a4d3a1d95060aea4c94e9f237030a8f9eae5615e9bd85718fe3a09e4b58836 rspec-mocks (3.13.7) sha256=0979034e64b1d7a838aaaddf12bf065ea4dc40ef3d4c39f01f93ae2c66c62b1c rspec-support (3.13.6) sha256=2e8de3702427eab064c9352fe74488cc12a1bfae887ad8b91cba480ec9f8afb2 BUNDLED WITH 4.0.3 maxitest-7.1.1/lib/000077500000000000000000000000001513323350600141255ustar00rootroot00000000000000maxitest-7.1.1/lib/maxitest/000077500000000000000000000000001513323350600157635ustar00rootroot00000000000000maxitest-7.1.1/lib/maxitest/autorun.rb000066400000000000000000000025251513323350600200110ustar00rootroot00000000000000# frozen_string_literal: true require "minitest" require "minitest/autorun" require "maxitest/vendor/around" require "maxitest/interrupt" unless ENV["MAXITEST_NO_INTERRUPT"] require "maxitest/let_bang" require "maxitest/let_all" require "maxitest/hook_all" require "maxitest/pending" require "maxitest/helpers" require "maxitest/xit" require "maxitest/static_class_order" require "maxitest/shorted_backtrace" unless Gem::Specification.find_all_by_name("rails").any? # rails adds default red/green output require "maxitest/vendor/rg" Minitest.extensions << "rg" Minitest::RG.rg! if $stdout.tty? end require "maxitest/verbose_backtrace" Minitest.extensions << Maxitest::VerboseBacktrace::MinitestPlugin require "maxitest/line" Minitest.extensions << Maxitest::Line::MinitestPlugin Minitest::Spec::DSL.send(:alias_method, :context, :describe) class << Minitest::Test alias order_dependent! i_suck_and_my_tests_are_order_dependent! end # do not show maxitest as causing errors, but the last line in the users code old = Minitest::BacktraceFilter::MT_RE Minitest::BacktraceFilter.send(:remove_const, :MT_RE) Minitest::BacktraceFilter::MT_RE = Regexp.union(old, %r{lib/maxitest}) # if already initialized the override if Minitest.backtrace_filter.class == Minitest::BacktraceFilter Minitest.backtrace_filter.regexp = Minitest::BacktraceFilter::MT_RE end maxitest-7.1.1/lib/maxitest/global_must.rb000066400000000000000000000022101513323350600206130ustar00rootroot00000000000000# frozen_string_literal: true # Allow .must_* and .wont_* assertions on all objects # this was removed from minitest v6 # # Must be required before maxitest/autorun require "minitest" require "minitest/spec" module Maxitest # Track current test instance for global must_* support def self.current_test Thread.current[:maxitest_current_test] end def self.current_test=(test) Thread.current[:maxitest_current_test] = test end end # Track the current test instance using prepend on run Minitest::Test.prepend( Module.new do def run Maxitest.current_test = self super ensure Maxitest.current_test = nil end end ) # Define global must_* methods on Object # This mimics what mintest 5 infect_an_assertion used to do expectation_methods = Minitest::Expectation.instance_methods - Object.instance_methods expectation_methods.grep(/^must_|^wont_/).each do |meth| Object.define_method(meth) do |*args, &block| ctx = Maxitest.current_test || raise(NotImplementedError, "Global #{meth} called outside of test context") Minitest::Expectation.new(self, ctx).public_send(meth, *args, &block) end end maxitest-7.1.1/lib/maxitest/helpers.rb000066400000000000000000000022371513323350600177560ustar00rootroot00000000000000# frozen_string_literal: true module Maxitest module Helpers module InstanceMethods def with_env(env) _synchronize do old = ENV.to_h env.each { |k, v| ENV[k.to_s] = v } yield ensure ENV.replace old end end # stripped down version of capture_io def capture_stdout _synchronize do captured_stdout = StringIO.new orig_stdout = $stdout $stdout = captured_stdout yield return captured_stdout.string ensure $stdout = orig_stdout end end # stripped down version of capture_io def capture_stderr _synchronize do captured_stderr = StringIO.new orig_stderr = $stderr $stderr = captured_stderr yield return captured_stderr.string ensure $stderr = orig_stderr end end end module ClassMethods def with_env(env) around { |t| with_env(env, &t) } end end end end Minitest::Test.include Maxitest::Helpers::InstanceMethods Minitest::Test.extend Maxitest::Helpers::ClassMethods maxitest-7.1.1/lib/maxitest/hook_all.rb000066400000000000000000000014731513323350600201050ustar00rootroot00000000000000# frozen_string_literal: true module Maxitest class << self attr_accessor :hook_all_counter end end Maxitest.hook_all_counter = 0 module Maxitest module HookAll [:before, :after].each do |hook| # minitest discards the type argument, so we are not sending it along define_method(hook) do |type = :each, &block| case type when :each then super(&block) when :all raise ArgumentError, ":all is not supported in after" if hook == :after c = (Maxitest.hook_all_counter += 1) callback = :"maxitest_hook_all_#{c}" let_all(callback, &block) super() { send callback } else raise ArgumentError, "only :each and :all are supported" end end end end end Minitest::Spec::DSL.prepend(Maxitest::HookAll) maxitest-7.1.1/lib/maxitest/implicit_subject.rb000066400000000000000000000007351513323350600216460ustar00rootroot00000000000000# frozen_string_literal: true # this is a bit hacky / overwrites describe, so not included by default ... module Maxitest module ImplicitSubject def describe(*args, &block) klass = super if args.first.is_a?(Class) && !klass.method_defined?(:subject, false) klass.let(:subject) { args.first.new } end klass end end end Object.include Maxitest::ImplicitSubject # Minitest hacks Kernel -> we need to use alias method or go into Object maxitest-7.1.1/lib/maxitest/interrupt.rb000066400000000000000000000017561513323350600203550ustar00rootroot00000000000000# frozen_string_literal: true # - show current backtrace when interrupting a stuck test with Ctrl+c # - skip remaining tests module Maxitest Interrupted = Class.new(StandardError) class << self attr_accessor :interrupted end module InterruptHandler # capture interrupt and treat it as a regular error so we get a backtrace def capture_exceptions(&block) super rescue Interrupt => e Maxitest.interrupted = true failures << Minitest::UnexpectedError.new(e) end # skip remaining tests if we were interrupted def run if Maxitest.interrupted # produce a real error so we do not crash in -v mode failures << begin raise Minitest::Skip, 'Maxitest::Interrupted' rescue Minitest::Skip $! end result = Minitest::Result.from(self) result.time = 0 result else super end end end end Minitest::Test.prepend(Maxitest::InterruptHandler) maxitest-7.1.1/lib/maxitest/let_all.rb000066400000000000000000000005631513323350600177300ustar00rootroot00000000000000# frozen_string_literal: true module Maxitest module LetAll def let_all(name, &block) cache = [] define_method(name) do if cache.empty? cache << instance_eval(&block) end cache.first end end def self.included(base) base.extend(self) end end end Minitest::Spec::DSL.include(Maxitest::LetAll) maxitest-7.1.1/lib/maxitest/let_bang.rb000066400000000000000000000002231513323350600200600ustar00rootroot00000000000000# frozen_string_literal: true Minitest::Spec::DSL.class_eval do def let!(name, &block) let(name, &block) before { send(name) } end end maxitest-7.1.1/lib/maxitest/line.rb000066400000000000000000000046271513323350600172500ustar00rootroot00000000000000# frozen_string_literal: true # https://raw.githubusercontent.com/judofyr/minitest-line/master/MIT-LICENSE.txt =begin Copyright (c) 2014 Magnus Holm Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. =end # https://raw.githubusercontent.com/judofyr/minitest-line/master/lib/minitest/line_plugin.rb module Maxitest module Line module MinitestPlugin def self.minitest_plugin_init(options) return if options[:include] # do not re-print when already filtered Minitest.reporter.reporters << LineReporter.new end end class LineReporter < Minitest::Reporter def initialize(*) super @failures = [] end def record(result) if !result.skipped? && !result.passed? @failures << result end end def report return unless @failures.any? io.puts io.puts "Focus on failing tests:" pwd = Pathname.new(Dir.pwd) bin_rails = File.exist?("bin/rails") @failures.each do |res| result = (res.respond_to?(:source_location) ? res : res.method(res.name)) file, line = result.source_location next unless file file = Pathname.new(file) file = file.relative_path_from(pwd) if file.absolute? output = "#{bin_rails ? "bin/rails test" : "minitest"} #{file}:#{line}" output = "\e[31m#{output}\e[0m" if $stdout.tty? io.puts output end end end end end maxitest-7.1.1/lib/maxitest/pending.rb000066400000000000000000000012411513323350600177320ustar00rootroot00000000000000# frozen_string_literal: true module Maxitest module Pending def pending(reason = nil, **kwargs) raise ArgumentError, "Need a block to execute" unless block_given? raise ArgumentError, "Only :if option is supported" if (kwargs.keys | [:if]) != [:if] # allow user to for example mark test only pending on CI with `if: ENV["CI"]` return yield if kwargs.fetch(:if, true) == false begin yield # execute test rescue StandardError, Minitest::Assertion skip reason # test failed as expected else flunk "Test is fixed, remove `pending`" end end end end Minitest::Test.include Maxitest::Pending maxitest-7.1.1/lib/maxitest/shorted_backtrace.rb000066400000000000000000000004741513323350600217640ustar00rootroot00000000000000# frozen_string_literal: true # # convert absolute paths in backtrace to relative paths Minitest::BacktraceFilter.prepend( Module.new do def filter(*) backtrace = super pwd = "#{Dir.pwd}/" section = pwd.size..-1 backtrace.map { |b| b.start_with?(pwd) ? b[section] : b } end end ) maxitest-7.1.1/lib/maxitest/static_class_order.rb000066400000000000000000000012351513323350600221600ustar00rootroot00000000000000# frozen_string_literal: true module Maxitest class << self attr_accessor :static_class_order end end class << Minitest::Runnable alias runnables_without_static_order runnables def runnables return runnables_without_static_order unless Maxitest.static_class_order # Minitest.__run uses Runnable.runnables.shuffle -> hack it runnables = runnables_without_static_order def runnables.shuffle self end # ugly hack to fight minitest 5.10 https://github.com/seattlerb/minitest/commit/478e3f9cfeb0a2f8cc4b029bbcbe7bb16648dd96 def runnables.reject(*args, &block) reject!(*args, &block) end runnables end end maxitest-7.1.1/lib/maxitest/threads.rb000066400000000000000000000021361513323350600177440ustar00rootroot00000000000000# frozen_string_literal: true # tests that leave extra threads running can break other tests in weird ways ... prevent that from happening module Maxitest module Threads def setup @maxitest_threads_before = Thread.list super end def teardown super found = maxitest_extra_threads raise "Test left #{found.size} extra threads (#{found})" if found.any? ensure maxitest_kill_extra_threads end # also a helper methods for users def maxitest_wait_for_extra_threads sleep 0.01 while maxitest_extra_threads.any? end # also a helper methods for users def maxitest_kill_extra_threads maxitest_extra_threads.map(&:kill).map(&:join) end # if setup crashes we do not return anything to make the initial error visible def maxitest_extra_threads @maxitest_threads_before ? Thread.list - @maxitest_threads_before : [] end end end # not using prepend since that would clash with webmock # include works because original setup lives in also included Minitest::LifecycleHooks Minitest::Test.include Maxitest::Threads maxitest-7.1.1/lib/maxitest/timeout.rb000066400000000000000000000016571513323350600200070ustar00rootroot00000000000000# frozen_string_literal: true # tests sometimes hang locally or on ci and with this we can actually debug the cause instead of just hanging forever require 'timeout' module Maxitest class << self attr_accessor :timeout end module Timeout class TestCaseTimeout < StandardError def message "Test took too long to finish, aborting. To use a debugger, def maxitest_timeout;false;end in the test file." end end def run(*, &block) # NOTE: having a default def maxitest_timeout would break using let(:maxitest_timeout) timeout = (defined?(maxitest_timeout) ? maxitest_timeout : Maxitest.timeout || 5) if timeout == false super else begin ::Timeout.timeout(timeout, TestCaseTimeout) { super } rescue TestCaseTimeout => e failures << UnexpectedError.new(e) end end end end end Minitest::Test.prepend Maxitest::Timeout maxitest-7.1.1/lib/maxitest/vendor/000077500000000000000000000000001513323350600172605ustar00rootroot00000000000000maxitest-7.1.1/lib/maxitest/vendor/around.rb000066400000000000000000000061201513323350600210740ustar00rootroot00000000000000# BEGIN generated by rake update, do not modify # https://raw.githubusercontent.com/splattael/minitest-around/master/LICENSE =begin Copyright (c) 2012 Peter Suschlik Copyright (c) 2018 Peter Leitzen (Suschlik) MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. =end # END generated by rake update, do not modify # BEGIN generated by rake update, do not modify # https://raw.githubusercontent.com/splattael/minitest-around/master/lib/minitest/around/version.rb module MinitestAround VERSION = '0.6.0' end # END generated by rake update, do not modify # BEGIN generated by rake update, do not modify # https://raw.githubusercontent.com/splattael/minitest-around/master/lib/minitest/around/unit.rb Minitest::Test.prepend(Module.new do def run(*args) if defined?(around) result = nil around { result = super(*args) } result else super(*args) end end end) # END generated by rake update, do not modify # BEGIN generated by rake update, do not modify # https://raw.githubusercontent.com/splattael/minitest-around/master/lib/minitest/around/spec.rb Minitest::Spec::DSL.class_eval do # - resume to call first part # - execute test # - resume fiber to execute last part def around(*args, &block) raise ArgumentError, "only :each, :example, or no argument are supported" if args - [:each, :example] != [] fib = nil before do fib = Fiber.new do |context, resume| begin context.instance_exec(resume, &block) rescue Object fib = :failed raise end end fib.resume(self, lambda { Fiber.yield }) end after { fib.resume if fib && fib != :failed } end # Minitest does not support multiple before/after blocks remove_method :before def before(type=nil, &block) include Module.new { define_method(:setup) { super(); instance_exec(&block) } } end remove_method :after def after(type=nil, &block) include(Module.new do define_method(:teardown) do begin instance_exec(&block) ensure super() end end end) end end # END generated by rake update, do not modify maxitest-7.1.1/lib/maxitest/vendor/rg.rb000066400000000000000000000055061513323350600202230ustar00rootroot00000000000000# BEGIN generated by rake update, do not modify # https://raw.githubusercontent.com/blowmage/minitest-rg/master/LICENSE =begin Copyright (c) 2023 Mike Moore Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. =end # END generated by rake update, do not modify # BEGIN generated by rake update, do not modify # https://raw.githubusercontent.com/blowmage/minitest-rg/master/lib/minitest/rg_plugin.rb # frozen_string_literal: true module Minitest def self.plugin_rg_options opts, _options # :nodoc: opts.on "--[no-]rg", "Add red/green to test output." do |bool| RG.rg! color: bool end end def self.plugin_rg_init options # :nodoc: return unless RG.rg? io = RG.new options[:io] reporter.reporters.grep(Minitest::Reporter).each { |rep| rep.io = io } end class RG VERSION = "5.4.0" COLORS = { "." => "\e[32m.\e[0m", "E" => "\e[33mE\e[0m", "F" => "\e[31mF\e[0m", "S" => "\e[36mS\e[0m" }.freeze attr_reader :io, :colors def self.rg! color: true @rg = color end def self.rg? @rg ||= false end def initialize io, colors = COLORS @io = io @colors = colors end def print output io.print(colors[output] || output) end def puts output = nil return io.puts if output.nil? if output =~ /(\d+) failures, (\d+) errors/ if Regexp.last_match[1] != "0" || Regexp.last_match[2] != "0" io.puts "\e[31m#{output}\e[0m" else io.puts "\e[32m#{output}\e[0m" end else io.puts output end end def method_missing msg, *args return io.send(msg, *args) if io.respond_to? msg super end def respond_to_missing? method_name, include_all = false return true if io.respond_to? method_name, include_all super end end end # END generated by rake update, do not modify maxitest-7.1.1/lib/maxitest/verbose_backtrace.rb000066400000000000000000000020061513323350600217520ustar00rootroot00000000000000# frozen_string_literal: true module Maxitest module VerboseBacktrace class NullFilter def self.filter(backtrace) backtrace end end # when printing messages print more if verbose was enabled module Assertion def message if Maxitest::VerboseBacktrace.enabled "#{self.class}: #{super}\n #{backtrace.join "\n "}" else super end end end module MinitestPlugin def self.minitest_plugin_init(options) return unless options[:verbose] Maxitest::VerboseBacktrace.enabled = true Minitest.backtrace_filter = Maxitest::VerboseBacktrace::NullFilter # rails has --backtrace which disables rails own backtrace cleaner, but not minitests Rails.backtrace_cleaner.remove_silencers! if defined?(Rails) && Rails.respond_to?(:backtrace_cleaner) end end class << self attr_accessor :enabled end end end Minitest::Assertion.include Maxitest::VerboseBacktrace::Assertion maxitest-7.1.1/lib/maxitest/version.rb000066400000000000000000000001061513323350600177720ustar00rootroot00000000000000# frozen_string_literal: true module Maxitest VERSION = "7.1.1" end maxitest-7.1.1/lib/maxitest/xit.rb000066400000000000000000000005311513323350600171130ustar00rootroot00000000000000# frozen_string_literal: true module Maxitest module XitMethod def xit(*args, &_block) describe 'skip' do define_method(:setup) {} define_method(:teardown) {} it(*args) end end def self.included(base) base.extend(self) end end end Minitest::Spec::DSL.include(Maxitest::XitMethod) maxitest-7.1.1/maxitest.gemspec000066400000000000000000000011761513323350600165670ustar00rootroot00000000000000# frozen_string_literal: true require_relative "lib/maxitest/version" Gem::Specification.new "maxitest", Maxitest::VERSION do |s| s.summary = "Minitest + all the features you always wanted" s.authors = ["Michael Grosser"] s.email = "michael@grosser.it" s.homepage = "https://github.com/grosser/maxitest" s.files = Dir["{bin,lib}/**/*", "MIT-LICENSE", "README.md", "CHANGELOG.md"] s.license = "MIT" # keep in sync with .github/workflows/actions.yml s.add_dependency "minitest", [">= 6.0.0", "< 6.1.0"] s.required_ruby_version = '>= 3.2' s.add_development_dependency "rake" s.add_development_dependency "rspec" end maxitest-7.1.1/spec/000077500000000000000000000000001513323350600143115ustar00rootroot00000000000000maxitest-7.1.1/spec/cases/000077500000000000000000000000001513323350600154075ustar00rootroot00000000000000maxitest-7.1.1/spec/cases/around.rb000066400000000000000000000007461513323350600172330ustar00rootroot00000000000000# frozen_string_literal: true require "./spec/cases/helper" describe "2" do let(:calls) { [] } before { calls << 1 } around((ENV["HOOK_TYPE"] || "each").to_sym) { |test| calls << 2; test.call } around { |test| calls << 3; test.call } after { _(calls).must_equal [1, 2, 3, 4] } after { calls << 4 } it "is ordered" do _(calls).must_equal [1, 2, 3] end end class AroundTest < Minitest::Test def around yield end def test_things assert 1 end end maxitest-7.1.1/spec/cases/catch_interrupt.rb000066400000000000000000000003401513323350600211270ustar00rootroot00000000000000# frozen_string_literal: true require "./spec/cases/helper" describe 2 do it "xx" do x = 2 begin raise Interrupt rescue Interrupt x = 1 else x = 3 end _(x).must_equal 1 end end maxitest-7.1.1/spec/cases/cltr_c.rb000066400000000000000000000007021513323350600172010ustar00rootroot00000000000000# frozen_string_literal: true require "./spec/cases/helper" describe 2 do i_suck_and_my_tests_are_order_dependent! before { puts "BEFORE" } after { puts "AFTER" } it "is even" do _(false).must_equal true end it "is not odd" do puts "hit Cltr+c" sleep 10 end it "stops after" do puts "should not get here ..." sleep 10 end it "really does ..." do puts "should not get here ..." sleep 10 end end maxitest-7.1.1/spec/cases/context.rb000066400000000000000000000003521513323350600174200ustar00rootroot00000000000000# frozen_string_literal: true require "./spec/cases/helper" describe 2 do context "methods" do it "is even" do _(2.even?).must_equal true end it "is not odd" do _(2.odd?).must_equal false end end end maxitest-7.1.1/spec/cases/error_and_failure.rb000066400000000000000000000002301513323350600214110ustar00rootroot00000000000000# frozen_string_literal: true require "./spec/cases/helper" describe 2 do it 'errors' do raise end it 'fails' do assert false end end maxitest-7.1.1/spec/cases/global_must.rb000066400000000000000000000007441513323350600202510ustar00rootroot00000000000000# frozen_string_literal: true if ENV['GLOBAL_MUST'] require 'maxitest/global_must' end require "./spec/cases/helper" describe "threads" do def assert_it 1.must_equal 1 end it "can assert normal" do assert_it end it "fails" do ENV["FAIL"].must_be_nil end it "can assert in threads" do result = "not called" Thread.new do assert_it rescue NotImplementedError result = "error" end.join result.must_equal "error" end end maxitest-7.1.1/spec/cases/helper.rb000066400000000000000000000002401513323350600172070ustar00rootroot00000000000000# frozen_string_literal: true require 'bundler/setup' $VERBOSE = true if ENV['SIMULATE_TTY'] def $stdout.tty? true end end require 'maxitest/autorun' maxitest-7.1.1/spec/cases/helpers.rb000066400000000000000000000021331513323350600173750ustar00rootroot00000000000000# frozen_string_literal: true require "./spec/cases/helper" describe "helpers" do describe "#with_env" do it "changes env" do with_env A: "b" do _(ENV["A"]).must_equal "b" end end it "restores env" do ENV["A"] = "c" with_env A: "b" do ENV["B"] = "a" _(ENV["A"]).must_equal "b" end _(ENV["A"]).must_equal "c" _(ENV["B"]).must_be_nil end end describe ".with_env" do with_env A: "a" it "sets env" do _(ENV["A"]).must_equal "a" end end describe "#capture_stdout" do it "keeps stdout" do _(capture_stdout { puts "X" }).must_equal "X\n" end it "lets stderr through" do out, err = capture_io { capture_stdout { warn "X" } } _(out).must_equal "" _(err).must_equal "X\n" end end describe "#capture_stderr" do it "keeps stderr" do _(capture_stderr { warn "X" }).must_equal "X\n" end it "lets stdout through" do out, err = capture_io { capture_stderr { puts "X" } } _(out).must_equal "X\n" _(err).must_equal "" end end end maxitest-7.1.1/spec/cases/hook_all.rb000066400000000000000000000013261513323350600175260ustar00rootroot00000000000000# frozen_string_literal: true require "./spec/cases/helper" hook_method = (ENV["HOOK_METHOD"] || "before").to_sym hook_type = (ENV["HOOK_TYPE"] || "all").to_sym # need this globally or classes don't sort r = Minitest::Runnable.runnables def r.shuffle self end # needed or minitest <=5.15 def r.reject replace super end describe 2 do order_dependent! send hook_method, hook_type do puts "ALL" end it "works" do puts "T1" end describe "subclass" do order_dependent! send hook_method, hook_type do puts "ALL-SUB" end it "still works" do puts "TS1" end it "yes it does" do puts "TS2" end end it "works after subclass" do puts "T2" end end maxitest-7.1.1/spec/cases/implicit_subject.rb000066400000000000000000000017601513323350600212710ustar00rootroot00000000000000# frozen_string_literal: true require "./spec/cases/helper" require "maxitest/implicit_subject" class DoNotCallMe def initialize raise "WRONG" end end describe String do it "has implicit subject" do _(subject).must_equal "" end describe Array do def other_method true end it "has nested implicit subject" do _(subject).must_equal [] _(other_method).must_equal true end end describe Hash do it "has other nested implicit subject" do _(subject).must_equal({}) end describe "strings" do it "does not overwrite subject" do _(subject).must_equal({}) end end describe :symbols do it "does not overwrite subject" do _(subject).must_equal({}) end end end describe DoNotCallMe do let(:subject) { 1 } it "can overwrite" do subject.must_equal 1 end end end describe "without" do it "raises as expected" do assert_raises(NameError) { subject } end end maxitest-7.1.1/spec/cases/let_all.rb000066400000000000000000000021251513323350600173500ustar00rootroot00000000000000# frozen_string_literal: true require "./spec/cases/helper" # executing sub-classes first makes the tests fail Maxitest.static_class_order = true describe "A" do order_dependent! let(:calls) { [] } let_all(:foo) { calls << 1; nil } describe "subclass gets randomly executed first" do it "is called when used" do _(calls).must_equal [] _(foo).must_be_nil _(calls).must_equal [1] end end describe "then another subclass" do it "is not called multiple times" do _(calls).must_equal [] _(foo).must_be_nil _(calls).must_equal [] end end describe "overwrite" do let_all(:foo) { calls << 2; true } it "can overwrite" do _(calls).must_equal [] _(foo).must_equal true _(calls).must_equal [2] end end describe "nested" do it "is not called multiple times from child classes" do _(calls).must_equal [] _(foo).must_be_nil _(calls).must_equal [] end end end describe "B" do let_all(:foo) { :foo } it "does not go across class boundaries" do _(foo).must_equal :foo end end maxitest-7.1.1/spec/cases/let_bang.rb000066400000000000000000000003321513323350600175050ustar00rootroot00000000000000# frozen_string_literal: true require "./spec/cases/helper" describe 2 do let(:calls) { [] } let!(:foo) { calls << 1 } before { calls << 2 } it "is called before" do _(calls).must_equal [1, 2] end end maxitest-7.1.1/spec/cases/line.rb000066400000000000000000000005361513323350600166670ustar00rootroot00000000000000# frozen_string_literal: true require "./spec/cases/helper" describe 2 do it "is even" do _(2.even?).must_equal true end it "is not odd" do _(2.odd?).must_equal true end describe "block" do it "is even" do _(2.even?).must_equal true end it "is still even" do _(2.even?).must_equal true end end end maxitest-7.1.1/spec/cases/mtest/000077500000000000000000000000001513323350600165435ustar00rootroot00000000000000maxitest-7.1.1/spec/cases/mtest/a_test.rb000066400000000000000000000002061513323350600203450ustar00rootroot00000000000000# frozen_string_literal: true require "./spec/cases/helper" describe 1 do it "is even" do _(2.even?).must_equal true end end maxitest-7.1.1/spec/cases/mtest/b_test.rb000066400000000000000000000002061513323350600203460ustar00rootroot00000000000000# frozen_string_literal: true require "./spec/cases/helper" describe 2 do it "is even" do _(2.even?).must_equal true end end maxitest-7.1.1/spec/cases/mtest/c.rb000066400000000000000000000002061513323350600173100ustar00rootroot00000000000000# frozen_string_literal: true require "./spec/cases/helper" describe 3 do it "is even" do _(2.even?).must_equal true end end maxitest-7.1.1/spec/cases/order_dependent.rb000066400000000000000000000005441513323350600211000ustar00rootroot00000000000000# frozen_string_literal: true require "./spec/cases/helper" $ordered_calls = [] describe 2 do order_dependent! it "a" do $ordered_calls << 1 end it "c" do $ordered_calls << 2 end it "b" do $ordered_calls << 3 end it "d" do $ordered_calls << 4 end it "z" do _($ordered_calls).must_equal [1, 2, 3, 4] end end maxitest-7.1.1/spec/cases/parallel.rb000066400000000000000000000004451513323350600175330ustar00rootroot00000000000000# frozen_string_literal: true ENV["MT_CPU"] = "3" # make this test hardware independent, need N for old minitest versions require "./spec/cases/helper" describe String do parallelize_me! it "1" do sleep 0.1 end it "2" do sleep 0.1 end it "3" do sleep 0.1 end end maxitest-7.1.1/spec/cases/pending.rb000066400000000000000000000026631513323350600173670ustar00rootroot00000000000000# frozen_string_literal: true require "./spec/cases/helper" describe 2 do it "runs regular tests" do _(2.even?).must_equal true end it "fails when pending is fixed" do e = assert_raises Minitest::Assertion do pending "fail" do _(2).must_equal 2 end end _(e.message).must_include "fixed" end it "skips when pending still needed" do e = assert_raises Minitest::Skip do pending "Skipping with reason" do _(2).must_equal 3, "This should not fail" end end _(e.message).must_equal "Skipping with reason" end it "skips exceptions" do e = assert_raises Minitest::Skip do pending "Skipping with exception" do raise "Oh noes" end end _(e.message).must_equal "Skipping with exception" end it "skips without reason" do pending do _(2).must_equal 3 end end it "fails without block" do e = assert_raises(ArgumentError) do pending "success" end _(e.message).must_equal "Need a block to execute" end it "can disable pending" do pending "Not skipping", if: false do _(2).must_equal 2 end end it "can enable pending" do pending "skipping conditionally", if: true do raise "Oh noes" end end it "fails when given unknown kwargs" do assert_raises(ArgumentError) do pending "skipping conditionally", unless: true do raise "Oh noes" end end end end maxitest-7.1.1/spec/cases/plain.rb000066400000000000000000000003011513323350600170310ustar00rootroot00000000000000# frozen_string_literal: true require "./spec/cases/helper" describe 2 do it "is even" do _(2.even?).must_equal true end it "is not odd" do _(2.odd?).must_equal false end end maxitest-7.1.1/spec/cases/raise.rb000066400000000000000000000003351513323350600170400ustar00rootroot00000000000000# frozen_string_literal: true require "./spec/cases/helper" # cause a raise in a required file module Maxitest class Timeout end end describe "explode" do it "explodes" do require 'maxitest/timeout' end end maxitest-7.1.1/spec/cases/raise_interrupt.rb000066400000000000000000000003101513323350600211450ustar00rootroot00000000000000# frozen_string_literal: true require "./spec/cases/helper" describe 2 do i_suck_and_my_tests_are_order_dependent! it "xx" do raise Interrupt end it "yyy" do assert false end end maxitest-7.1.1/spec/cases/static_class_order.rb000066400000000000000000000003421513323350600216020ustar00rootroot00000000000000# frozen_string_literal: true require "./spec/cases/helper" Maxitest.static_class_order = true $calls = [] 5.times do |i| describe rand do it { puts i } describe rand do it { puts "#{i}n" } end end end maxitest-7.1.1/spec/cases/threads.rb000066400000000000000000000014141513323350600173660ustar00rootroot00000000000000# frozen_string_literal: true ENV["MT_CPU"] = "2" # so we get 3 threads total and not variation based on machines cpus require "./spec/cases/helper" require "maxitest/threads" describe "threads" do order_dependent! def assert_correct_threads _(Thread.list.count).must_equal 3, Thread.list end def create_thread Thread.new { sleep 0.1 } end it "is fine without extra threads" do assert_correct_threads end it "fails on extra threads" do assert_correct_threads create_thread _(Thread.list).must_equal 4 end it "can kill extra threads" do assert_correct_threads create_thread maxitest_kill_extra_threads end it "can wait for extra threads" do assert_correct_threads maxitest_wait_for_extra_threads end end maxitest-7.1.1/spec/cases/timeout.rb000066400000000000000000000010051513323350600174160ustar00rootroot00000000000000# frozen_string_literal: true require "./spec/cases/helper" require "maxitest/timeout" Maxitest.timeout = (ENV['DISABLE'] || ENV['CUSTOM'] ? false : 0.1) describe 2 do if ENV['CUSTOM'] let(:maxitest_timeout) { 0.1 } end it "x" do 1 end it "times out" do sleep 1 puts "DID NOT TIME OUT" end it "y" do 1 end describe "sum" do before { sleep 0.04 } after do sleep 0.04 puts "DID NOT TIME OUT" end it "fails" do sleep 0.04 end end end maxitest-7.1.1/spec/cases/xit.rb000066400000000000000000000007441513323350600165450ustar00rootroot00000000000000# frozen_string_literal: true require "./spec/cases/helper" describe 2 do it 'includes the xit module' do assert_includes Minitest::Spec::DSL.included_modules, Maxitest::XitMethod end xit "is even" do _(2.even?).must_equal true end it "is odd" do _(2.odd?).must_equal false end describe "with evil setup/teardown" do before { raise "called before" } after { raise "called after" } xit "should not be called" do raise end end end maxitest-7.1.1/spec/maxitest_spec.rb000066400000000000000000000271051513323350600175130ustar00rootroot00000000000000# frozen_string_literal: true require "spec_helper" require 'open3' describe Maxitest do it "has a VERSION" do Maxitest::VERSION.should =~ /^[.\da-z]+$/ end it "does not add extra output" do result = run_cmd("ruby spec/cases/plain.rb") result.sub!(/seed \d+/, 'seed X') result.gsub!(/\d+\.\d+/, 'X') result.should == "Run options: --seed X\n\n# Running:\n\n..\n\nFinished in Xs, X runs/s, X assertions/s.\n\n2 runs, 2 assertions, 0 failures, 0 errors, 0 skips" end it "runs via ruby" do run_cmd("ruby spec/cases/plain.rb").should include "\n2 runs, 2 assertions" end it "supports context" do run_cmd("ruby spec/cases/context.rb").should include "\n2 runs, 2 assertions" end it "supports let!" do run_cmd("ruby spec/cases/let_bang.rb").should include "\n1 runs, 1 assertions" end it "supports let_all" do run_cmd("ruby spec/cases/let_all.rb") end it "can use static_class_order" do run_cmd("ruby spec/cases/static_class_order.rb").should include("\n0\n.0n\n.1\n.1n\n.2\n.2n\n.3\n.3n\n.4\n.4n\n.\n") end it "supports order_dependent" do run_cmd("ruby spec/cases/order_dependent.rb").should include "5 runs, 1 assertions, 0 failures, 0 errors, 0 skips" end it "has pending" do run_cmd("ruby spec/cases/pending.rb") end it "does not call xit specs" do result = run_cmd("ruby spec/cases/xit.rb -v") result.should include "(no tests defined)" result.should include "4 runs, 3 assertions, 0 failures, 0 errors, 2 skips" end it "shows short backtraces" do out = run_cmd("ruby spec/cases/raise.rb", fail: true) # Ruby 3.2 has a different backtrace it add 2 lines between the lib/maxitest/timeout.rb # and the spec/cases/raise.rb out.gsub!(/\n.*previous definition of Timeout.*/, "") # unify backtraces between ruby versions output_in = out.gsub!(/:in .*/, "") output_in.should include "TypeError: Timeout is not a module" output_in.should include 'spec/cases/raise.rb:12' # Minitest 5.21.0+ backtrace is more verbose and the short backtrace feature seems to be gone # re-test by running spec/cases/raise.rb and only loading minitest/autorun and not maxitest if Minitest::VERSION <= "5.21.0" output_in.should_not include 'lib/maxitest' end end it "has helpers" do run_cmd("ruby spec/cases/helpers.rb") end it "does not use old MiniTest constant" do Dir["lib/**/*.rb"].each do |p| File.read(p).should_not include "MiniTest" end end describe "before/after/around" do it "works" do out = run_cmd("ruby spec/cases/hook_all.rb") out.should include "Running:\n\nALL\nT1\n.T2\n.ALL-SUB\nTS1\n.TS2\n.\n\nFinished" end it "fails when using unsupported type" do with_env HOOK_TYPE: "foo" do out = run_cmd("ruby spec/cases/hook_all.rb", fail: true) out.should include "only :each and :all are supported (ArgumentError)" end end it "informs user about missing after :all" do with_env HOOK_METHOD: "after" do out = run_cmd("ruby spec/cases/hook_all.rb --seed 123", fail: true) out.should include ":all is not supported in after (ArgumentError)" end end it "supports around" do run_cmd("ruby spec/cases/around.rb").should include "\n2 runs, 3 assertions" end it "informs user about missing around :all" do with_env HOOK_TYPE: "all" do out = run_cmd("ruby spec/cases/around.rb", fail: true) out.should include "only :each" end end end describe "color" do it "is color-less without tty" do run_cmd("ruby spec/cases/plain.rb").should include "\n2 runs, 2 assertions" end it "is colorful on tty" do simulate_tty do run_cmd("ruby spec/cases/plain.rb").should include "\n\e[32m2 runs, 2 assertions" end end it "is colorful without tty but --rg" do run_cmd("ruby spec/cases/plain.rb --rg").should include "\n\e[32m2 runs, 2 assertions" end it "is color-less with --no-rg and tty" do simulate_tty do run_cmd("ruby spec/cases/plain.rb --no-rg").should include "\n2 runs, 2 assertions" end end end describe "timeout" do it "times out long running tests" do result = run_cmd("ruby spec/cases/timeout.rb -v", fail: true) # 1 test takes too long and fails with a nice error message result.should include "Maxitest::Timeout::TestCaseTimeout: Test took too long to finish, aborting" # results look normal result.should include ", 2 errors," end it "times out after custom interval" do result = run_cmd("CUSTOM=1 ruby spec/cases/timeout.rb -v", fail: true) # 1 test takes too long and fails with a nice error message result.should include "Maxitest::Timeout::TestCaseTimeout: Test took too long to finish, aborting" # results look normal result.should include ", 2 errors," end it "does not time out when disabled" do result = run_cmd("DISABLE=1 ruby spec/cases/timeout.rb -v") # 1 test takes too long and fails with a nice error message result.should include "DID NOT TIME OUT" # results look normal result.should include "4 runs" end end describe "extra threads" do it "fails on extra and passes on regular" do result = run_cmd("ruby spec/cases/threads.rb -v", fail: true) result.gsub(/\d\.\d+/, "0.0").should include <<-OUT.gsub(/^\s+/, "") threads#test_0001_is fine without extra threads = 0.0 s = . threads#test_0002_fails on extra threads = 0.0 s = F threads#test_0003_can kill extra threads = 0.0 s = . threads#test_0004_can wait for extra threads = 0.0 s = . OUT end end describe "global_must" do it "does not complain when used and loaded" do with_env GLOBAL_MUST: 'true' do run_cmd("ruby spec/cases/global_must.rb") end end it "complains when used and not loaded" do out = run_cmd("ruby spec/cases/global_must.rb", fail: true) out.gsub!('`', "'") # for ruby <3.4 had out.should include "undefined method 'must_equal'" end it "does not obfuscate test origin" do with_env GLOBAL_MUST: 'true', FAIL: 'true' do out = run_cmd("ruby spec/cases/global_must.rb", fail: true) out.should include "_fails [spec/cases/global_must.rb:18]:" end end end describe "Interrupts" do it "stops on ctrl+c and prints errors" do t = Thread.new { run_cmd("ruby spec/cases/cltr_c.rb", fail: true) } sleep 1 # let thread start kill_process_with_name("spec/cases/cltr_c.rb") output = t.value output.should include "4 runs, 1 assertions, 1 failures, 1 errors, 2 skips" # failed, error from interrupt (so you see a backtrace), rest skipped output.gsub(/:\d+:in/, ":D:in").should match(/cltr_c\.rb:D:in (`|'Kernel#)sleep'/) # let you know where it happened output.should include "Interrupt:" # let you know what happened output.should include "Expected: true\n Actual: false" # not hide other errors output.scan('BEFORE').size.should == 2 # before calls avoided when skipping output.scan('AFTER').size.should == 2 # after calls avoided when skipping end it "allows Interrupts to be caught normally" do output = run_cmd("ruby spec/cases/catch_interrupt.rb") output.should include "1 runs, 1 assertions, 0 failures, 0 errors, 0 skips" end it "catches directly raised Interrupt" do output = run_cmd("ruby spec/cases/raise_interrupt.rb", fail: true) output.should include "runs, " output.should include "Interrupt: Interrupt" end it "shows backtraces when in verbose mode" do t = Thread.new { run_cmd("ruby spec/cases/cltr_c.rb -v", fail: true) } sleep 1 # let thread start kill_process_with_name("spec/cases/cltr_c.rb") output = t.value output.gsub(/:\d+:in/, ":D:in").should match(/cltr_c.rb:D:in (`|'Kernel#)sleep'/) # let you know where it happened end end describe "minitest executable" do it "shows version" do run_cmd("minitest --version", fail: true).should include "minitest" end it "shows help" do run_cmd("minitest -h", fail: true).should include "Usage:" run_cmd("minitest --help", fail: true).should include "Usage:" end it "runs a single file" do run_cmd("minitest spec/cases/plain.rb").should include "2 runs, 2 assertions, 0 failures, 0 errors, 0 skips" end it "runs a single line" do run_cmd("minitest spec/cases/plain.rb:6").should include "1 runs, 1 assertions, 0 failures, 0 errors, 0 skips" end it "runs a folder" do run_cmd("minitest spec/cases/mtest").should include "2 runs, 2 assertions, 0 failures, 0 errors, 0 skips" end it "runs multiple files" do run_cmd("minitest spec/cases/mtest/a_test.rb spec/cases/mtest/c.rb").should include "2 runs, 2 assertions, 0 failures, 0 errors, 0 skips" end end describe "line" do let(:separator) { "Focus on failing tests:\n" } it "prints rerun commands" do result = run_cmd("ruby spec/cases/line.rb", fail: true) result.should include "4 runs, 4 assertions" foucs = result.split(separator, 2)[1] foucs.should == "minitest spec/cases/line.rb:9" end it "does not print rerun commands when already filtered" do result = run_cmd("minitest spec/cases/line.rb:9", fail: true) result.should include "1 runs, 1 assertions" result.should_not include separator end end describe "backtraces" do it "shows no backtrace without verbose" do result = run_cmd("ruby spec/cases/error_and_failure.rb", fail: true) result.should include "error_and_failure.rb:6" result.should include "error_and_failure.rb:10" result.should_not include "minitest.rb" end it "shows backtrace for errors with verbose" do result = run_cmd("ruby spec/cases/error_and_failure.rb -n '/errors/' -v", fail: true) result.should include "1 run" result.should include "error_and_failure.rb:6" result.should include "minitest.rb" end it "shows backtrace for failures with verbose" do result = run_cmd("ruby spec/cases/error_and_failure.rb -n '/fails/' -v", fail: true) result.should include "1 run" result.should include "error_and_failure.rb:10" result.should include "minitest.rb" end end describe "parallel" do it "can run in parallel" do result = run_cmd("ruby spec/cases/parallel.rb -v") result.should include "\n3 runs" result.should include "Finished in 0.1" end end private def simulate_tty(&block) with_env SIMULATE_TTY: 'true', &block end def with_env(h) old = ENV.to_h h.each { |k, v| ENV[k.to_s] = v } yield ensure ENV.replace old end def run_cmd(command, deprecated: :fail, keep_output: false, fail: false) stdout, stderr, status = Open3.capture3(command) stderr.should_not include("DEPRECATED") unless deprecated == :ignore stdout += "\n#{stderr}" unless keep_output if status.success? == fail raise "#{fail ? "SUCCESS" : "FAIL"} #{command}\n#{stdout}" end stdout.strip end # copied from https://github.com/grosser/parallel/blob/master/spec/parallel_spec.rb#L10-L15 def kill_process_with_name(file, signal = 'INT') running_processes = `ps -f`.split("\n").map { |line| line.split(/\s+/) } pid_index = running_processes.detect { |p| p.include?("UID") }.index("UID") + 1 parent = running_processes.detect { |p| p.include?(file) and !p.include?("sh") } raise "Unable to find parent in #{running_processes} with #{file}" unless parent `kill -s #{signal} #{parent.fetch(pid_index)}` end end maxitest-7.1.1/spec/spec_helper.rb000066400000000000000000000003331513323350600171260ustar00rootroot00000000000000# frozen_string_literal: true require "maxitest/version" require "minitest" RSpec.configure do |config| config.expect_with(:rspec) { |c| c.syntax = :should } config.mock_with(:rspec) { |c| c.syntax = :should } end